jieba中文分词源码分析(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gfsfg8545/article/details/48195287

一、缘由

接触自然语言处理(NLP)有段时间,理论知识有些了解,挺想动手写些东西,想想开源界关于NLP的东西肯定不少,其中分词是NLP的基础,遂在网上找了些资源,其中结巴分词是国内程序员用python开发的一个中文分词模块, 源码已托管在github: 源码地址 ,代码用python实现,源码中也有注释,但一些细节并没有相应文档,因此这里打算对源码进行分析,一来把知识分享,让更多的童鞋更快的对源码有个认识,二来使自己对分词这一块有个更深入的理解。

二、中文分词介绍

  • 为什么中文分词
    1. 词是最小的能够独立活动的有意义的语言成分
    2. 汉语是以字位单位,不像西方语言,词与词之间没有空格之类的标志指示词的边界
    3. 分词问题为中文文本处理的基础性工作,分词的好坏对后面的中文信息处理其关键作用
  • 中文分词的难点
    1. 分词规范,词的定义还不明确 (《统计自然语言处理》宗成庆)
    2. 歧义切分问题,交集型切分问题,多义组合型切分歧义等
      结婚的和尚未结婚的 =>
      结婚/的/和/尚未/结婚/的
      结婚/的/和尚/未/结婚/的
    3. 未登录词问题
      有两种解释:一是已有的词表中没有收录的词,二是已有的训练语料中未曾出现过的词,第二种含义中未登录词又称OOV(Out of Vocabulary)。对于大规模真实文本来说,未登录词对于分词的精度的影响远超歧义切分。一些网络新词,自造词一般都属于这些词。
  • 汉语分词方法
    1. 基于字典、词库匹配的分词方法(基于规则)
      基于字符串匹配分词,机械分词算法。将待分的字符串与一个充分大的机器词典中的词条进行匹配。分为正向匹配和逆向匹配;最大长度匹配和最小长度匹配;单纯分词和分词与标注过程相结合的一体化方法。所以常用的有:正向最大匹配,逆向最大匹配,最少切分法。实际应用中,将机械分词作为初分手段,利用语言信息提高切分准确率。优先识别具有明显特征的词,以这些词为断点,将原字符串分为较小字符串再机械匹配,以减少匹配错误率,或将分词与词类标注结合。
    2. 基于词频度统计的分词方法(基于统计)
      相邻的字同时出现的次数越多,越有可能构成一个词语,对语料中的字组频度进行统计,基于词的频度统计的分词方法是一种全切分方法。jieba是基于统计的分词方法,jieba分词采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合,对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。
    3. 基于知识理解的分词方法。
      该方法主要基于句法、语法分析,并结合语义分析,通过对上下文内容所提供信息的分析对词进行定界,它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断。这类方法试图让机器具有人类的理解能力,需要使用大量的语言知识和信息。由于汉语语言知识的笼统、复杂性,难以将各种语言信息组织成机器可直接读取的形式。因此目前基于知识的分词系统还处在试验阶段。

三、jieba中文分词介绍

  • 特点
    1. 支持三种分词模式:
      a. 精确模式,试图将句子最精确地切开,适合文本分析;
      b. 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
      c. 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
    2. 支持繁体分词
    3. 支持自定义词典
    4. MIT 授权协议
  • 安装
    全自动安装:easy_install jieba 或者 pip install jieba 或者把源代码下载下来直接安装,解压后直接运行setup脚本:python setup.py install
  • jieba的主要功能
    详见这里 jieba主要功能其中主要包括:分词;添加自定义词典(开发者可以指定自己自定义的词典,以便包含 jieba 词库里没有的词);关键词提取;词性标注;并行分词;ChineseAnalyzer for Whoosh 搜索引擎等
  • jieba分词的算法策略
    1. 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
    2. 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
    3. 对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法
  • jieba源码组织形式
    下面是jieba源码的树结构
jieba
|-- Changelog
|-- extra_dict
|   |-- dict.txt.big
|   |-- dict.txt.small
|   |-- idf.txt.big
|   `-- stop_words.txt
|-- jieba
|   |-- analyse
|   |   |-- analyzer.py
|   |   |-- idf.txt
|   |   |-- __init__.py
|   |   |-- textrank.py
|   |   `-- tfidf.py
|   |-- _compat.py
|   |-- dict.txt
|   |-- finalseg
|   |   |-- __init__.py
|   |   |-- prob_emit.p
|   |   |-- prob_emit.py
|   |   |-- prob_start.p
|   |   |-- prob_start.py
|   |   |-- prob_trans.p
|   |   `-- prob_trans.py
|   |-- __init__.py
|   |-- __main__.py
|   `-- posseg
|       |-- char_state_tab.p
|       |-- char_state_tab.py
|       |-- __init__.py
|       |-- prob_emit.p
|       |-- prob_emit.py
|       |-- prob_start.p
|       |-- prob_start.py
|       |-- prob_trans.p
|       |-- prob_trans.py
|       `-- viterbi.py
|-- LICENSE
|-- setup.py
`-- test
    |-- *.py
    |-- parallel
    |   |-- extract_tags.py
    |   `-- test*.py
    `-- userdict.txt

代码行数统计(没有统计test文件夹下的代码):

    256 ./posseg/prob_start.py
   5307 ./posseg/prob_trans.py
    304 ./posseg/__init__.py
  89372 ./posseg/prob_emit.py
  61087 ./posseg/char_state_tab.py
     53 ./posseg/viterbi.py
    578 ./__init__.py
      4 ./finalseg/prob_start.py
      4 ./finalseg/prob_trans.py
    107 ./finalseg/__init__.py
  35226 ./finalseg/prob_emit.py
     31 ./_compat.py
     50 ./__main__.py
    111 ./analyse/tfidf.py
     37 ./analyse/analyzer.py
    104 ./analyse/textrank.py
     18 ./analyse/__init__.py
 192649 总用量

其中prob*.py的文件是作者事先训练好的模型参数(λ=(A,B,π)),如状态转移概率、发射概率等。真正的代码数也就:304+53+578+107+31+50+111+37+104+18=1393行(不包括test文件中的代码),当然作者的代码写的比较简洁。

  • jieba分词模型的参数数据(λ=(A,B,π))是如何生成的?
    即文件finalseg/prob_*.py,中初始化概率,状态转移概率,发射概率怎么算出来的?
    来源主要有两个: 一个是网上能下载到的1998人民日报的切分语料还有一个msr的切分语料; 另一个是作者自己收集的一些txt小说,用ictclas把他们切分(可能有一定误差)。 然后用python脚本统计词频 具体详情
    要统计的主要有三个概率表:
    1) 位置转换概率(状态转移概率),即B(开头),M(中间),E(结尾),S(独立成词)四种状态的转移概率;
    2) 位置到单字的发射概率,比如P(“和”|M)表示一个词的中间出现”和”这个字的概率;
    3) 词语以某种状态开头的概率,其实只有两种,要么是B,要么是S。

接下来就具体介绍jieba源码了,具体源码见github注释

参考:

  1. 《 统计自然语言处理》 宗成庆
  2. 《统计学习方法》 李航
  3. http://www.cnblogs.com/flish/archive/2011/08/08/2131031.html

猜你喜欢

转载自blog.csdn.net/gfsfg8545/article/details/48195287