虽说本篇博文的标题是《数学之美读书笔记三》(分词模型),然而本篇主要内容是讲讲自己在这么长时间以来,在自然语言处理这条路上初探和走的一些弯路。
在看完语言模型和HMM后,我又看了几篇论文,并且尝试了一些语言处理工具包、心累。
还有很多尝试用代码去实现模型的一些工作。
算了,直接进入正题吧。
数学之美中的分词模型
Step1:构建词典
构建词典,词典中包含大量的已有的离散词语。
比如在结巴中文分词中,/jieba/dict.txt中词典一般。
关于构建词典的步骤,我目前还不是很了解…不过这个也需要进行一个比较长时间的训练过程吧。
Step2: 解决分词二义性问题,即套统计语言模型
之前的词典构建好了之后,可以直接根据一个句子进行分词了,而且也可以让人感觉挺好的。
不过我们还是要进一步增加精度,比如【北京大学生】,到底怎么分?可以是【北京 | 大学生】,也可以是【北京大学 | 生】,分出来的词语在词典中都是存在的,不过很明显正确的应该是【北京 | 大学生】。 |
于是机智的研究人员就看【北京大学 | 生】和【北京 | 大学生】这两种不同的分词在大量正确的语料库得到的概率呗。哪个概率高就说明哪个更好啦啦啦。 |
用数学语言描述如下:
对一句话S,假定有下列三种(n种也一样)分词方案:
\(A_1, A_2, A_3, A_4…, A_n\)
\(B_1, B_2, B_3, B_4…, B_n\)
\(C_1, C_2, C_3, C_4…, C_n\)
假设概率\(P(A_1, A_2, A_3…, A_n) > P(B_1, B_2, B_3, …, B_n) > P(C_1, C_2, C_3…, C_n)\)的话,那么明显使用第一种分词方法更加的棒棒。
实现小技巧:穷举的话计算量相当大(这点本人深深感受过…我在自己的统计语言模型中做了一个n^n复杂度的东西,计算量不要太大..),于是可以使用动态规划来减少复杂度,我特么也是醉了…这里究竟怎么动龟呀。。
整个过程如下图。
Step3:套上复合词
这里主要是解决复合词和基本词的矛盾。
在Step1中我们构建的词表,可以作为【基本词表】,在此之上,我们还需要一个【复合词表】,然后各自套统计语言模型L1, 和L2。
于是这个步骤应该是:先按照Step1-Step2得到【基本词串】,然后在基本词串的基础上,再进行一遍Step2的操作,不过词典变成了一个【复合词表】,语言模型只是语料库变了,这样输出的就是一个复合词处理后的【复合词串】。
最后中文分词差不多已经解决了…
结巴中文分词
结巴中文分词是一个分词工具包,支持各种语言。
我想说的差不多按照官方文档就可以解决掉。
关于安装和示例,可以直接看文档就行。我这里只多说一点,关于Python3中print的中文问题,加上这三行就可以处理了:
import io
import sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
比如示例代码就可以改成以下这样:
#coding=utf-8
import jieba
import io
import sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
sentence = jieba.cut("我来到了江苏扬州,送给了她一朵很美的鲜花", cut_all=False)
print("Full Mode: " + "/ ".join(sentence))
我主要想说的是关于他的算法过程:
基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)
采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合
对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法
我来解读一下吧:
构图
第一步主要是根据词典找到所有的可能分词结果,构建如图像神经网络一般的有向无环图:
其中每一条从头到尾的路径,都是一个未检验的分词结果。
寻找最大概率路径
在上图的所有的路径中,根据已有的语料库套统计语言模型,找到基于词语频率的最大概率的一条路径,如果这里不懂的话,建议去看我关于《数学之美》的第一篇笔记。
HMM
对于在词典中没有的词语,他采用了基于汉字成词能力的隐含马尔可夫模型,使用了Viterbi算法。
我对Viterbi算法并不了解,但我大概了解一下隐含马尔可夫模型(HMM),我猜想这里主要是根据输入的这段话作为明码,来推测分词(暗码)的结果。
这篇博文就先写到这里吧,还有些东西我需要再参考某些文献才能继续讲下去并且带更多的示例。