中文分词概述及结巴分词原理

Posted 高校大数据团队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中文分词概述及结巴分词原理相关的知识,希望对你有一定的参考价值。

词是中文表达语义的最小单位,中文分词是中文文本处理的一个基础步骤,分词的结果对中文信息处理至为关键。

本文先对中文分词方法进行概述,然后简单介绍结巴分词背后的原理。

 

1. 中文分词概述

 

中文分词根据实现特点大致可分为两类:基于词典的分词方法、基于统计的分词方法。

 

1.1 基于词典的分词方法

 

基于词典的分词方法首先会建立一个充分大的词典,然后依据一定的策略扫描句子,若句子中的某个子串与词典中的某个词匹配,则分词成功。

常见的扫描策略有:正向最大匹配、逆向最大匹配、双向最大匹配和最少词数分词。

 

1.1.1 正向最大匹配

对输入的句子从左至右,取词典中最长单词的个数作为第一次取词的个数,在词典中进行扫描若不匹配,则逐字递减若匹配,则取出当前词,从后面的词开始正向最大匹配组不了词的字单独划开。其分词基本原则是:词的颗粒度越大越好;切分结果中非词典词越少越好总体词数越少越好。

 

1.1.2 逆向最大匹配

分词原则与正向最大匹配相同,但顺序不是从首字开始,而是从末字开始,而且它使用的分词词典是逆序词典,其中每个词条都按逆序方式存放。在实际处理时,先将句子进行倒排处理,生成逆序句子,然后根据逆序词典,对逆序句子用正向最大匹配处理

 

1.1.3 双向最大匹配

将正向最大匹配与逆向最大匹配组合起来,对句子使用这两种方式进行扫描切分如果两种分词方法得到的匹配结果相同,则认为分词正确,否则,按最小集处理。

 

1.1.4 最少词数分词

即一句话应该分成数量最少的词串,该方法首先会查找词典中最长的词,看是不是所要分词的句子的子串,如果是则切分,然后不断迭代以上步骤,每次都会在剩余的字符串中取最长的词进行分词,最后就可以得到最少的词数。

 

总结:基于词典的分词方法简单速度快,效果也可以但对歧义和新词的处理不是很好,对词典中未登录的词没法进行处理

 

1.2 基于统计的分词方法

 

基于统计的分词方法是从大量已经分词的文本,利用统计机器学习模型学习词切分规律,从而实现对未知文本的切分。随着大规模语料库的建立,基于统计的分词方法不断受到研究和发展,渐渐成为了主流。

常用的统计学习方法有:隐马尔可夫模型(HMM)、条件随机场(CRF)和基于深度学习的方法。

 

1.2.1 HMMCRF

这两种方法实质上是对序列进行标注,将分词问题转化为字的分类问题,每个字有4种词位(类别):词首(B)、词中(M)、词尾(E)和单字成词(S)。由字构词的方法并不依赖于事先编制好的词典,只需对分好词的语料进行训练即可。当模型训练好后,就可对新句子进行预测,预测时会针对每个字生成不同的词位。其中HMM属于生成式模型,CRF属于判别式模型。

 

1.2.2 基于深度学习的方法

神经网络的序列标注算法在词性标注、命名实体识别等问题上取得了优秀的进展,这些端到端的方法也可以迁移到分词问题上。与所有深度学习的方法一样,该方法需要较大的训练语料才能体现优势,代表为BiLSTM-CRF

 

总结:基于统计的分词法能很好处理歧义和词问题,效果比基于词典的要,但该方法需要有大量人工标注分好词的语料作支撑,训练开销大,就分词速度而言不如前一种。

 

在实际应用中一般是将词典与统计学习方法结合起来,既发挥词典分词切分速度快的特点,又利用了统计分词结合上下文识别生词、自动消除歧义的优点。结巴分词正是这一类的代表,下面简介绍它的实现算法。

 

2. 结巴分词原理

 

官方Github上对所用算法的描述为:

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

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

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

下面逐一介绍:

 

2.1 构造前缀词典

结巴分词首先会依照统计词典dict.txt构造前缀词典dict.txt含有近35万的词条,每个词条占用一行,其中每一行有3列,第一列为词条,第二列为对应的词频,第三列为词性,构造前缀词典需要用到前两列。

具体做法为:首先定义一个空的python字典,然后遍历dict.txt的每一行,取词条作为字典的键,词频作为对应的键值,然后遍历该词条的前缀,如果前缀对应的键不在字典里,就把该前缀设为字典新的键,对应的键值设为0,如果前缀在字典里,则什么都不做。

这样等遍历完dict.txt后,前缀词典就构造好了。在构造前缀词典时,会累加统计词典里所有词条的词频,累加值等计算最大概率路径时会用到。

 

2.2 生成有向无环图(DAG

用正则表达式分割句子后,对每一个单独的子句会生成一个有向无环图。

具体方式为:先定义一个空的python字典,然后遍历子句,当前子句元素的索引会作为字典的一个键,对应的键值为一个python列表(初始为空),然后会以当前索引作为子串的起始索引,不断向后遍历生成不同的子串,如果子串在前缀词典里且键值不为0的话,则把子串的终止索引添加到列表中。

这样等遍历完子句的所有字后,对应的DAG就生成好了。(子串的键值如果是0,则说明它不是一个词条)

 

2.3 计算最大概率路径

DAG的起点到终点会有很多路径,需要找到一条概率最大的路径,然后据此进行分词。可以采用动态规划来求解最大概率路径。

具体:从子句的最后一个字开始倒序遍历子句的每个字,取当前字对应索引在DAG字典中的键值(一个python列表),然后遍历该列表,当前会和列表中每个字两两组合成一个词条,然后基于词频计算出当前字到句尾的概率,以python元组的方式保存最大概率,元祖第一个元素是最大概率的对数,第二个元素为最大概率对应条的终止索引。

词频可看作DAG中边的权重,之所以取概率的对数是为了防止数值下溢。有了最大概率路径,分词结果也就随之确定。

 

2.4 对未登录词采用HMM模型进行分词

当出现没有在前缀词典里收录的词时,会采用HMM模型进行分词。HMM模型有5个基本组成:观测序列、状态序列、状态初始概率、状态转移概率和状态发射概率。分词属于HMM的预测问题,即已知观测序列、状态初始概率、状态转移概率和状态发射概率的条件下,求状态序列。结巴分词已经内置了训练好的状态初始概率、状态转移概率和状态发射概率。

句子会作为观测序列,当有新句子进来时,具体做法为:先通过Viterbi算法求出概率最大的状态序列,然后基于状态序列输出分词结果(每个字的状态为BMES之一)。

 

       至此,结巴分词的原理就简单介绍完了。


下面举一个简单的例子:

假如待分词的句子为: “这几天都在学自然语言处理”。

首先依据前缀词典生成DAG

{  0: [0],

   1: [1, 2],

   2: [2, 3],

   3: [3],

   4: [4],

   5: [5],

   6: [6, 7, 9],

   7: [7],

   8: [8, 9],

   9: [9],

 10: [10, 11],

 11: [11]  }

句子元素对应的索引会作为字典的键,对应键值的第一项与当前索引相同,其余项会与当前索引组成词条,这个词条在前缀词典里且对应键值不为0

生成的DAG如下:

然后采用动态规划求出的最大概率路径为:

{12: (0, 0),

 11: (-9.073726763747516, 11),

 10: (-8.620554852761583, 11),

   9: (-17.35315508178225, 9),

   8: (-17.590039287472578, 9),

   7: (-27.280113467960604, 7),

   6: (-22.70346658402771, 9),

   5: (-30.846092652642497, 5),

   4: (-35.25970621827743, 4),

   3: (-40.95138241952608, 3),

   2: (-48.372244833381465, 2),

   1: (-50.4870755319817, 2),

   0: (-55.92332690525722, 0)}

最大概率路径按句子索引倒序排列,但分词时会从索引0开始顺序遍历句子。

具体做法为

首先遍历00对应的键值最后一项为0即词的长度为1,遇到长度为1的词时(即单字)先不分,继续往后看,然后遍历11对应的键值最后一项为2即词的长度为2,这时会把索引为0的单字作为词分割出来,然后接着把索引12对应的词分割出来,然后遍历33对应的键值最后一项为3,属于单字,先不分,索引45同理,然后遍历66对应的键值最后一项为9,即词的长度为4,注意,这里索引345对应的单字序列(即都在学)如果不在前缀词典中或者在前缀词典中但键值为0,则会对单字序列采用HMM模型进行分词,否则的话,会单字序列每个字进行分词,分好之后把索引6789对应的词分割出去,然后遍历1010对应的键值最后一项为11,即词的长度为2,直接把索引1011对应的词分割出去,至此分词结束


下面对结巴分词的逻辑进行总结:

在遇到长度>=2的词之前会把它前面出现的所有单字保存下来

如果保存下来的单字序列长度为0,则直接把当前词分割出去;

如果保存下来的单字序列长度为1,则直接把单字作为词分割出去,然后把后面词分割出去;

如果保存下来的单字序列长度>1,会分两种情况:假如单字序列不在前缀词典中或者在前缀词典中但键值为0,则会对单字序列采用HMM模型进行分词,否则的话,会单字序列每个字进行分词。


最后分好的词为:['',  '几天',  '',  '',  '',  '自然语言',  '处理']

 

3. 总结

本文先对中文分词方法进行了概述,然后讲解了结巴分词原理。实际应用中,一般将基于词典的分词方法和基于统计的分词方法相结合以达到比较好的效果。除结巴分词外,成熟的中文分词包还有北大中文分词工具、HanLP等,可多了解比较它们的效果。



以上是关于中文分词概述及结巴分词原理的主要内容,如果未能解决你的问题,请参考以下文章

结巴中文分词原理分析2

python中文分词,使用结巴分词对python进行分词

结巴分词原理

结巴分词

如何利用Python对中文进行分词处理

中文分词及词性标注工具使用