当前位置:   article > 正文

中文分词库jieba介绍

jieba词库

1.jieba库是较好的中文分词词库

2.jieba库分词思想有三步:定义前缀词典,构建字典树;生成句子有向图,路径规划输出最优路径;基于HMM模型求解decoding问题

3.生成句子有向图本质是贝叶斯网络,路径规划实质是求解联合概率分布

4.jieba的HMM模型的隐状态有四种:BMES,基于大量语料库初始化参数(初始概率分布,转移矩阵和发射矩阵)

分词是对文本预处理重要环节,英文分词可以针对空格切分达到很好的效果。而中国文字博大精深,需要用一定的方法处理。本文就介绍基于python第三方库jieba分词库,它是比较好的中文分词词库。jieba库的分词原理主要有三项:

  • 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的向无环图(DAG)

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

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

前缀词典与DAG

首先是前缀词典的扫描。jieba库是利用了Tier树进行高效扫描,Tier树中文名叫字典树、前缀树。它的用途主要是将字符串整合成树形。

比如由“清华”、“清华大学”、“清白”、“中华”、“华夏”五个中文词构成的Tier树:

这个树里面每一个方块代表一个节点,其中根节点Root不代表任何字符;紫色代表分支节点;绿色代表叶子节点。除根节点外每一个节点都只包含一个字符。从根节点到叶子节点,路径上经过的字符连接起来,构成一个词。而叶子节点内的数字代表该词在字典树中所处的链路(字典中有多少个词就有多少条链路),具有共同前缀的链路称为串。

字典树有以下三个特点:

  • 具有相同前缀的词必须位于同一个串内

比如“清华”和“清白”两个词语,都有“清”这个前缀,那么在字典树上只需要构建一个“清”节点即可,这在一定程度减少存储空间。

  • 字典树中的词只可共用前缀,不可共用词的其他部分

比如“华夏”和“中华”,这两个词都有共同的后缀“华”,但在字典树上必须是两条独立的链路,即字典树仅依靠公共前缀压缩字典存储空间。再看“清华大学”这个词语,“大学”也是一个词语,但是“清华大学”的后缀,所以“大学”必须从根节点开始重新构建。

  • 一个完整的词必须从根节点开始,至叶子节点结束

字典树实质是一个有限状态自动机(Definite Automata,DFA),它从一个节点(状态)转移到另一个节点(状态)的行为完全由状态转移函数控制,而状态转移函数本质上是一种映射,这意味着:逐字搜索字典树时,从一个字符到下一个字符比对是不需要遍历该节点的所有子节点的。

构建完字典树后就可以生成句子的有向无环图(DAG)

假设对于待切分的字符串(句子)有m个字符,考虑每个字符左右两边的位置,则有m+1个点,编号从0~m,把候选词看成边,根据前缀词典生成一个切分图。比如句子“我毕业于北京大学”:

“我”这条边起点是0,终点是1;“毕业”这条边起点是1,终点是3,依次类推,根据词典,我们可以得到两条路径:

路径1:0-1-3-4-6-8  切分方案S1:我/毕业/于/北京/大学

路径2:0-1-3-4-8      切分方案S2:我/毕业/于/北京大学

动态规划

对于方案S1和S2,我们最终选取哪种切分方案呢。jieba库的字典树会标记每个词的频率,它存储在dict.txt文件中:

该文件每一行代表一个词语,每一行存储【词名 词频 词性】三个字段。

注:词性标注表在网上有大量资料,读者可以自行查找

在知道每个词出现的频率之后,就可以基于动态规划的方法来寻找概率最大的分词路径,这里采取从右往左去寻找最优路径。具体怎么做,其实就是算每种路径的联合概率分布,还记得有向无环图(DAG)其实是一种贝叶斯网络嘛,我们在概率图模型中介绍过其联合概率分布的公式:

传送门:概率图模型(模型表示)

比如对于上一节的两种路径S1和S2,它其实对应着两个贝叶斯网络:

分别计算他们的联合概率分布,最大的那个即为最终切分方案

注:jieba分词是从右往左,所以实际中方向与上图箭头相反

HMM的译码分词

如果遇到一些词典中没有的词语,那怎么办呢。jieba采取了HMM模型进行生成,它主要是进行译码(Decoding)问题:


回顾一下HMM模型,要求解上述状态序列,需要知道HMM的参数λ=(π,A,B),即初始状态概率分布π,状态转移矩阵A和发射矩阵B.

传送门:

隐马尔可夫模型(背景介绍)

隐马尔可夫模型(前向算法与后向算法)

隐马尔可夫模型(Baum Welch算法与Viterbi算法)

隐马尔可夫模型(模型推断五大问题)

隐马尔可夫模型(算法流程&实例演示)

那么在jieba库里,这三个参数是什么呢。jieba库首先定义了四种状态BEMS,B是开始,begin位置;E是end,是结束位置;M是middle,是中间位置;S是singgle,单独成词的位置,没有前,也没有后。采用(B、E、M、S)这四种状态来标记中文词语,比如北京可以标注为 BE;中华民族可以标注为BMME,就是开始、中间、中间、结束。

然后采用大量的语料进行训练,得到了HMM的参数λ,分别存储在finalseg目录下的三个文件(prob_start.py、prob_trans.py 、prob_emit.py 、 )

我们来大概浏览一下这三个文件的内容,

  • 初始状态分布π

  • 状态转移矩阵A:

  • 发射矩阵B:

jieba库应用

总结一下,jieba库的分词原理是:生成字典树——给定句子生成DAG——路径规划输出概率最大切分组合——不在字典树的词语基于HMM模型求解Decoding问题

这一节我们简单介绍一下jieba库在代码层面的具体应用。

  • 分词

  1. import jieba
  2. jieba.cut(sentence,cut_all=False,HMM=True,use_paddle=False)
  3. jieba.cut_for_search(sentence,HMM=True)

cut 方法接受四个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型;use_paddl参数是否使用训练序列标注(双向GRU)网络模型实现分词。

cut_for_search 方法接受两个参数:需要分词的字符串;是否使用 HMM 模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细。

上面两个方法返回的结构是 generator,利用jieba.lcut 以及 jieba.lcut_for_search 直接返回 list

注:paddle需要额外安装,官网见参考资料

  • 字典

  1. jieba.load_userdict(filename)
  2. jieba.add_word(word, freq=None, tag=None)
  3. jieba.del_word(word)
  4. jieba.suggest_freq(segment, tune=False)

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍load_userdict方法添加自定义词典,词典格式和 dict.txt 一样,词频和词性可省略,顺序不可颠倒;add_word和 del_word可在程序中动态修改词典;suggest_freq可调节单个词语的词频

  • 关键词提取

   

  1. import jieba.analyse
  2. #基于TF-IDF算法的关键词抽取
  3. jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
  4. jieba.analyse.TFIDF(idf_path=None) #新建TFIDF 实例,idf_path 为IDF 频率文件
  5. jieba.analyse.set_idf_path(file_name)# 切换成自定义语料库,file_name为自定义语料库的路径
  6. #基于TextRank算法的关键词抽取
  7. jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'))
  8. jieba.analyse.TextRank()
  9. #关键词提取所使用停止词
  10. jieba.analyse.set_stop_words(file_name)

sentence为待提取的文本,topK 为返回权重最大的关键词的个数,默认 20,withWeight 为是否一并返回关键词权重值,默认 False,allowPOS 仅包括指定词性的词,默认为空。

TFIDF方法表示新建 TFIDF 实例,同理,TextRank方法新建自定义 TextRank 实例

  • 词性标注

  1. import jieba
  2. import jieba.posseg as pseg
  3. words = pseg.cut(sentence) #jieba默认模式
  4. jieba.enable_paddle()
  5. words = pseg.cut(sentence, use_paddle=True) # paddle模式
  6. for word, flag in words:
  7.     print(' %s %s ' % (word, flag))
  8. jieba.posseg.POSTokenizer(tokenizer=None)

POSTokenizer 方法是新建自定义分词器,tokenizer 参数可指定内部使用Tokenizer 分词器。jieba.posseg.dt 为默认词性标注分词器。

  • 其他

  1. import jieba
  2. #返回词语在原文的起止位置
  3. re = jieba.tokenize(sentence,mode='search',HMM=True) #默认模式
  4. for i in re:
  5.     print("word %s\t\t start: %d \t\t end:%d" % (i[0], i[1], i[2]))
  6. #延迟加载,初始化字典
  7. jieba.initialize() # 手动初始化(可选)
  8. jieba.set_dictionary('data/dict.txt.big')

jieba 采用延迟加载,import jieba 和 jieba.Tokenizer() 不会立即触发词典的加载,一旦有必要才开始加载词典构建前缀字典。也可以改变主词典的路径。

参考资料:

https://github.com/fxsjy/jieba

https://www.paddlepaddle.org.cn/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/243439
推荐阅读
相关标签
  

闽ICP备14008679号