NLP之jieba分词

对于做NLP (Natural Laugurage Processing,自然语言处理) 的朋友来说,中文的分词工具 "结巴" 分词应该是再熟悉不过了。笔者在相关的工作中也从它受益颇丰,今天就着重介绍一下这个自称 "做最好的python中文分词组件" 的jieba分词。

简介

    如果要处理中文文本,首先要做的第一步就是将它进行拆分处理,但是不像英文文本中有" "空格 这种天然的分隔符,中文需要一些辅助工具来帮助完成分词的任务。

常见的中文分词工具

  • Jieba
  • SnowNLP (MIT)
  • Thulac(清华大学)
  • StanfNLP (斯坦福大学) 
  • FudanNLP(复旦大学)

我用的比较多的jieba和StanfNLP,其中jieba善于分词,StanfNLP则擅长词性标注和实体识别。这里主要分享一下对jieba的特点及其原理。

(jiaba完整文档 GitHub: https://github.com/fxsjy/jieba

jieba的特点

1.支持3种分词模式

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

2.支持繁体分体

3.支持自定义词典:  按照 "单词_词性_词频" 的格式加入,后两项可省略

import jieba
 
sent = '用刀尖入水,用显微镜看雪,就算反复如此,还是忍不住问一问,你数过天上的星星吗?它们和小鸟一样,总在我胸口跳伞。'
seg_list1 = jieba.cut(sent,cut_all=True)
print('全模式:','/'.join(seg_list1))
seg_list2 = jieba.cut(sent,cut_all=False)
print('精确模式:','/'.join(seg_list2))
seg_list3 = jieba.cut(sent)
print('默认精确模式:','/'.join(seg_list3))
seg_list4 = jieba.cut_for_search(sent)
print('搜索引擎模式:','/'.join(seg_list4))
全模式: 用/刀尖/入水///用/显微/显微镜/看/雪///就算/反复/如此///还是/忍不住/不住/问一问///你/数/过天/天上/的/星星/吗///它们/和/小鸟/一样///总/在/我/胸口/跳伞//
精确模式: 用/刀尖/入/水/,/用/显微镜/看雪/,/就算/反复/如此/,/还是/忍不住/问一问/,/你/数过/天上/的/星星/吗/?/它们/和/小鸟/一样/,/总在/我/胸口/跳伞/。
默认精确模式: 用/刀尖/入/水/,/用/显微镜/看雪/,/就算/反复/如此/,/还是/忍不住/问一问/,/你/数过/天上/的/星星/吗/?/它们/和/小鸟/一样/,/总在/我/胸口/跳伞/。
搜索引擎模式: 用/刀尖/入/水/,/用/显微/显微镜/看雪/,/就算/反复/如此/,/还是/不住/忍不住/问一问/,/你/数过/天上/的/星星/吗/?/它们/和/小鸟/一样/,/总在/我/胸口/跳伞/。

 

jieba分词原理

算法原理如下图所示,主要包含以下3项:

  1. "基于前缀 (Tier) 词典" 实现高效的词图扫描,生成句子中汉字所有可能 "成词" 情况所构成的 "有向无环图"(DAG)
  2. 采用了 "动态规划" (Dynamic Programming) 查找 最大概率路径,找出 "基于词频" 的 "最大切分组合";
  3. 对于词库中不存在的词,即新词(未登录词),采用了 "基于汉字成词能力" 的 "HMM模型",使用了 "Viterbi算法"

>> 通过前缀树 (Trie) 结构,生成所有成词可能的有向无环图(DAG)

Trie树,中文名叫字典树、前缀树等。主要用于将字符整合成树形。举例来看由 "清华大学"、"清华"、"清新"、"中华"、"华人"五个中文词构成的Trie树。树的结构如下:

其中,root时根节点,不代表任何字符。除根节点外,每个节点代表一个字符。从根节点到叶节点路径上的字符连接起来,构成一个词。叶节点的数字表示词在字典树中所处的 "链路"(字典有多少个词就由多少条链条),具有共同前缀的链路称为 "串"。在Tier 树中搜索一个字符串时,会从根节点出发,沿着某条链路向下查找,直到找到相应的根节点为止,这种处理方式有2个优点:

  1. 公共前缀树的词都位于同一个串内,查词范围大幅缩小。因为首字符不同的字符串,都会被排除
  2. Trie树实质是一个 有限状态自动机(Define Automata,DFA),表明从Trie树的一个节点(状态)  转移到另一个节点的行为完全由状态转移函数控制,本质上是一种影射。意味着逐字搜索Trie时,从一个字符到下一个字符比对是不需要遍历该节点的所有子节点的

构建完Trie树之后就可以根据Trie树生成句子的有向无环图(DAG)。如果待切分字符串有m个字符,考虑每个字符左边和右边的位置,则有m+1个点对应,点的编号从0到m。把候选词看成边,可以根据词典生成一个此份词图。切分词图是一个有向正权重的图。举例:"有意见分歧"

在 "有意见分歧" 的切分词图中:"有" 这条边的起点是0,终点是1; "有意" 这条边的起点是0,终点是2,以此类推。切分方案就是从源点0到终点5之间的路径,共存在2条切分路径。

       路径1:0-1-3-5    对应切分方案S1:有/  意见/  分歧/

  路径2:0-2-3-5    对应切分方案S2:有意/  见/  分歧/

>> 动态规划查找最大概率路径,找出基于最大词频的最大切分组合

    在jieba分词中的Trie树会标记每个词的频率,有个概率就可以动态规划的找寻最大分词路径了。一般动态规划都是从左往右,然而因为汉语句子的重心一般都在后面,所以我们一般采用 "从右往左" 的方式寻找最优路径。

>> 对于新词,采用 “HMM模型 + Viterbi算法”

未登录词就是在词典(Trie树)中未记录的词。对于这类词就是采用HMM模型来生成的(因此如果删除了词典,也是可以进行分词的)。那么HMM模型是如何构建的呢?首先定义了四种状态BEMS,B是开始,begin位置;E是end,是结束位置;M是middle,是中间位置;S是singgle,单独成词的位置,没有前,也没有后。也就是说,他采用了状态为 (B、E、M、S) 这四种状态来标记中文词语,比如北京可以标注为 BE,即 北/B 京/E,表示北是开始位置,京是结束位置;中华民族可以标注为BMME,就是开始、中间、中间、结束。

jieba分词的作者对大量语料进行的训练,得到了finalseg目录下的三个文件(prob_trans.py 、prob_emit.py 、prob_start.py )

要统计的主要有三个概率表:

prob_trans.py
1)位置转换概率,即B(开头),M(中间),E(结尾),S(独立成词)四种状态的转移概率;
    {‘B’: {‘E’: 0.8518218565181658, ‘M’: 0.14817814348183422},
    ‘E’: {‘B’: 0.5544853051164425, ‘S’: 0.44551469488355755},
    ‘M’: {‘E’: 0.7164487459986911, ‘M’: 0.2835512540013088},
‘    S’: {‘B’: 0.48617017333894563, ‘S’: 0.5138298266610544}}  

  P(E|B) = 0.851;P(M|B) = 0.149,说明当我们处于一个词的开头时,下一个字是结尾的概率要远高于下一个字是中间字的概率,符合我们的直觉,因为二个字的词比多个字的词更常见。  

prob_emit.py 

2)位置到单字的发射概率,比如P(“和”|M)表示一个词的中间出现”和”这个字的概率; 

prob_start.py 

3)词语以某种状态开头的概率,其实只有两种,要么是B,要么是S。这个就是起始向量,就是HMM系统的最初模型状态实际上,BEMS之间的转换有点类似于2元模型,就是2个词之间的转移二元模型考虑一个单词后出现另外一个单词的概率,是N元模型中的一种。例如:一般来说,”中国”之后出现”北京”的概率大于”中国”之后出现”北海”的概率,也就是:中国北京 比 中国北海出现的概率大些, 更有可能是一个中文词语。

因此jieba分词的过程:

1)生成Tier树

2)给定句子,使用正则获取连续的中文字符和英文字符,切分成短语列表,构建有向无环图(先生成,然后去词典中匹配寻找最大概率路径)和使用动态规划,得到概率最大的路径。对DAG中那些没有在字典中查到的词,组合成一个新的片段短语,使用HMM模型进行分词

3)使用python中的yield语法生成一个词语生成器返回

 

未完待续...

参考:

https://blog.csdn.net/gdh756462786/article/details/79102642

https://www.cnblogs.com/snailclimb/p/9086433.html

https://www.cnblogs.com/jiangxinyang/p/9330876.html

https://blog.csdn.net/u013982921/article/details/81085395

https://blog.csdn.net/qq_37098526/article/details/88877798

https://blog.csdn.net/weixin_30575309/article/details/98795091

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值