jieba分词的原理

 jieba介绍:

一、支持三种分词模式:

  • 精确模式,试图将句子最精确地切开,适合文本分析;
  • 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
  • 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

二、jieba自带了一个叫做dict.txt的词典, 里面有2万多条词, 包含了词条出现的次数(这个次数是于作者自己基于人民日报语料等资源训练得出来的)和词性. 这个第一条的trie树结构的词图扫描, 说的就是把这2万多条词语, 放到一个trie树中, 而trie树是有名的前缀树, 也就是说一个词语的前面几个字一样, 就表示他们具有相同的前缀, 就可以使用trie树来存储, 具有查找速度快的优势。

三、jieba分词应该属于概率语言模型分词

概率语言模型分词的任务是:在全切分所得的所有结果中求某个切分方案S,使得P(S)最大。

jieba用到的算法:

一、基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG)

1. 根据dict.txt生成trie树。字典在生成trie树的同时, 也把每个词的出现次数转换为了频率;

2. 对待分词句子, 根据dict.txt生成的trie树, 生成DAG, 实际上通俗的说, 就是对待分词句子, 根据给定的词典进行查词典操作, 生成几种可能的句子切分。jieba的作者在DAG中记录的是句子中某个词的开始位             置, 从0到n-1(n为句子的长度), 每个开始位置作为字典的键, value是个list, 其中保存了可能的词语的结束位置(通过查字典得到词, 开始位置+词语的长度得到结束位置)注:所以可以联想到,jieba支持全模             式分词,能把句子中所有的可以成词的词语都扫描出来

例如:{0:[1,2,3]} 这样一个简单的DAG, 就是表示0位置开始, 在1,2,3位置都是词, 就是说0~1, 0~2,0~3这三个起始位置之间的字符, 在dict.txt中是词语.可看示例切分词图

二、采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

1.查找待分词句子中已经切分好的词语(我觉得这里应该是全模式下的分词list), 对该词语查找该词语出现的频率(次数/总数), 如果没有该词(既然是基于词典查找进行的分词, 应该是有的), 就把词典中出现频率最小的那个词语的频率作为该词的频率, 也就是说P(某词语)=FREQ.get(‘某词语’,min_freq)

2.根据动态规划查找最大概率路径的方法, 对句子从右往左反向计算最大概率(一些教科书上可能是从左往右, 这里反向是因为汉语句子的重心经常落在后面, 就是落在右边, 因为通常情况下形容词太多, 后面的才是主干, 因此, 从右往左计算, 正确率要高于从左往右计算, 这个类似于逆向最大匹配), P(NodeN)=1.0, P(NodeN-1)=P(NodeN)*Max(P(倒数第一个词))…依次类推, 最后得到最大概率路径, 得到最大概率的切分组合.

 1 def calc(sentence,DAG,idx,route):  #动态规划,计算最大概率的切分组合
 2     #输入sentence是句子,DAG句子的有向无环图
 3     N = len(sentence)  #句子长度
 4     route[N] = (0.0,‘‘)
 5     for idx in xrange(N-1,-1,-1):  #和range用法一样,不过还是建议使用xrange
 6         #可以看出是从后往前遍历每个分词方式的
 7
 8         #下面的FREQ保存的是每个词在dict中的频度得分,打分的公式是 log(float(v)/total),其中v就是被打分词语的频数
 9          #FREQ.get(sentence[idx:x+1],min_freq)表示,如果字典get没有找到这个key,那么我们就使用最后的frequency来做
10          #由于DAG中是以字典+list的结构存储的,所以确定了idx为key之外,
11          #仍然需要for x in DAG[idx]来遍历所有的单词结合方式(因为存在不同的结合方法,例如“国”,“国家”等)
12          #以(频度得分值,词语最后一个字的位置)这样的tuple保存在route中
13         candidates = [ ( FREQ.get(sentence[idx:x+1],min_freq) + route[x+1][0] , x ) for x in DAG[idx] ]
14         route[idx] = max(candidates) 

三、对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法

未登录词:词典 dict.txt 中没有记录的词(注: 就算把dict.txt中所有的词汇全部删掉, jieba依然能够分词, 不过分出来的词, 大部分的长度为2.这个就是基于HMM来预测分词了)

1.中文词汇按照BEMS四个状态来标记, B是开始begin位置, E是end, 是结束位置, M是middle, 是中间位置, S是singgle, 单独成词的位置, 没有前, 也没有后. jieba作者就是采用了状态为(B,E,M,S)这四种状态来标记中文词语, 比如北京可以标注为 BE, 即 北/B 京/E, 表示北是开始位置, 京是结束位置, 中华民族可以标注为BMME, 就是开始, 中间, 中间, 结束.

2.作者对大量语料进行训练, 得到了三个概率表。训通过练得到的概率表和viterbi算法, 就可以得到一个概率最大的BEMS序列, 按照B打头, E结尾的方式, 对待分词的句子重新组合, 就得到了分词结果. 比如 对待分词的句子 ‘全世界都在学中国话’ 得到一个BEMS序列 [S,B,E,S,S,S,B,E,S] 这个序列只是举例, 不一定正确, 通过把连续的BE凑合到一起得到一个词, 单独的S放单, 就得到一个分词结果了: 上面的BE位置和句子中单个汉字的位置一一对应, 得到全/S 世界/BE 都/S 在/S 学/S 中国/BE 话/S 从而将句子切分为词语.

jeiba分词过程:

生成全切分词图:根据trie树对句子进行全切分,并且生成一个邻接链表表示的词图(DAG),查词典形成切分词图的主体过程如下所示:

 1 for(int i=0;i<len;){
 2     boolean match = dict.getMatch(sentence, i,
 3 wordMatch);//到词典中查询
 4     if (match) {// 已经匹配上
 5         for (String word:wordMatch.values)
 6 {//把查询到的词作为边加入切分词图中
 7             j = i+word.length();
 8             g.addEdge(new CnToken(i, j, 10, word));
 9         }
10         i=wordMatch.end;
11     }else{//把单字作为边加入切分词图中
12         j = i+1;
13         g.addEdge(new CnToken(i,j,1,sentence.substring(i,j)));
14         i=j;
15     }
16 }  

计算最佳切分路径:在这个词图的基础上,运用动态规划算法生成切分最佳路径。

使用了HMM模型对未登录词进行识别:如进行中国人名、外国人名、地名、机构名等未登录名词的识别。

重新计算最佳切分路径。

以上整理于对Python中文分词模块结巴分词算法过程的理解和分析

疑问:

1.识别出的未登录词貌似是没有频率的以及用户自定义词典中词频和词性都是可省略的,那jieba重新计算最佳切分组合是怎么算的?,是把词典中频率最小的那个词语的频率作为该词的频率?

时间: 2024-10-11 12:49:16

jieba分词的原理的相关文章

jieba分词的词性标注

号称"做最好的Python中文分词组件"的jieba分词是python语言的一个中文分词包.它的特点有: 支持三种分词模式: ? 精确模式,试图将句子最精确地切开,适合文本分析: ? 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义: ? 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词. 支持繁体分词 支持自定义词典 Python 2.x 下的安装 全自动安装:easy_install jieba 或者 pip inst

python结巴(jieba)分词

python结巴(jieba)分词 一.特点 1.支持三种分词模式: (1)精确模式:试图将句子最精确的切开,适合文本分析. (2)全模式:把句子中所有可以成词的词语都扫描出来,速度非常快,但是不能解决歧义. (3)搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词.2.支持繁体分词3.支持自定义词典 二.实现 结巴分词的实现原理主要有一下三点:(1)基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG).(2)采用了动态

Lucene.net(4.8.0) 学习问题记录五: JIEba分词和Lucene的结合,以及对分词器的思考

前言:目前自己在做使用Lucene.net和PanGu分词实现全文检索的工作,不过自己是把别人做好的项目进行迁移.因为项目整体要迁移到ASP.NET Core 2.0版本,而Lucene使用的版本是3.6.0 ,PanGu分词也是对应Lucene3.6.0版本的.不过好在Lucene.net 已经有了Core 2.0版本(4.8.0 bate版),而PanGu分词,目前有人正在做,貌似已经做完,只是还没有测试~,Lucene升级的改变我都会加粗表示. Lucene.net 4.8.0 https

自然语言处理之jieba分词

英文分词可以使用空格,中文就不同了,一些分词的原理后面再来说,先说下python中常用的jieba这个工具. 首先要注意自己在做练习时不要使用jieba.Py命名文件,否则会出现 jieba has no attribute named cut -等这些,如果删除了自己创建的jieba.py还有错误是因为没有删除jieba.pyc文件. (1)基本分词函数和用法 首先介绍下分词的三种模式: 精确模式:适合将句子最精确的分开,适合文本分析: 全模式:把句子中所有可以成词的词语都扫描出来,速度快,但

jieba 分词简单应用

关键词抽取就是从文本里面把跟这篇文档意义最相关的一些词抽取出来.这个可以追溯到文献检索初期,当时还不支持全文搜索的时候,关键词就可以作为搜索这篇论文的词语.因此,目前依然可以在论文中看到关键词这一项. 除了这些,关键词还可以在文本聚类.分类.自动摘要等领域中有着重要的作用.比如在聚类时将关键词相似的几篇文档看成一个团簇,可以大大提高聚类算法的收敛速度:从某天所有的新闻中提取出这些新闻的关键词,就可以大致了解那天发生了什么事情:或者将某段时间内几个人的微博拼成一篇长文本,然后抽取关键词就可以知道他

jieba分词与HMM学习

问题1:jieba中文分词的原理? 问题2:HMM在jieba中的应用? 问题3:HMM在其他行业内有何应用? 首先学一个东西的第一步应该先看官网https://github.com/fxsjy/jieba 官网给出jieba中应用到的算法有: 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG) 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法 功能解析: 主

python爬虫——京东评论、jieba分词、wordcloud词云统计

接上一章,抓取京东评论区内容. url='https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv399&productId=4560435&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1' 重点是productId--产品id.page--页码.pageSize:指定

【原】关于使用jieba分词+PyInstaller进行打包时出现的一些问题的解决方法

错误现象: 最近在做一个小项目,在Python中使用了jieba分词,感觉非常简洁方便.在Python端进行调试的时候没有任何问题,使用PyInstaller打包成exe文件后,就会报错: 错误原因分析: 参考文献1中的说明,WindowsError:[Error 3]是系统找不到指定文件. 参考文献2中@fxsjy同学的解释,应该是PyInstaller在打包的时候没有将词典文件一起打包导致结巴分词找不到指定的词典文件. 解决方案如下: 1.在python中查询结巴分词的词典文件: 1 2 3

Jieba分词包(三)——基于词频最大切分组合

Jieba分词包(三)--基于词频最大切分组合 在前面,我们已经知道dict中所有的单词和词频信息已经存在了一个trie树中,并且需要分词的句子已经构建成了一个DAG图,构建的过程也运用了dict.那么这次我们来说如何基于每句话的DAG图,找到一个组合路径,使得该组合最合理(即打分最高)? 我们直接针对Jieba分词的源代码来解释,其中已经有了很多注释: def calc(sentence,DAG,idx,route): #动态规划,计算最大概率的切分组合 #输入sentence是句子,DAG句