入坑自然语言处理,最基本的就是要做文本挖掘,而首先要做的就是文本的预处理。自然语言处理的主要流程可以表示为:
文本->分句->分词->词性标注->短语分析->句法分析->语义分析->语篇分析->理解
分句这部分一般有标点符号分割,便于处理。于是首先要做的就是分词。英文单词天然有空格隔开容易按照空格分词,但是也有时候需要把多个单词做为一个分词,比如一些名词如“New York”,需要做为一个词看待。而中文由于没有空格,分词就是一个需要专门去解决的问题了。无论是英文还是中文,分词的原理都是类似的,本文就对文本挖掘时的分词原理做一个总结。
现代分词都是基于统计的分词,而统计的样本内容来自于一些标准的语料库。从统计学角度考虑,如果有一个句子S,它有m种分词选项如下:
其中下标ni代表第i种分词的词个数。如果我们从中选择了最优的第r种分词方法,那么这种分词方法对应的统计分布概率应该最大,即:
但是我们的概率分布P(Ai1,Ai2,...,Aini)并不好求出来,因为它涉及到ni个分词的联合分布。在NLP中,为了简化计算,我们通常使用马尔科夫假设,即每一个分词出现的概率仅仅和前一个分词有关,即:
而通过我们的标准语料库,我们可以近似的计算出所有的分词之间的二元条件概率,比如任意两个词w1,w2,它们的条件概率分布可以近似的表示为:
其中freq(w1,w2)表示w1,w2在语料库中相邻一起出现的次数,而其中freq(w1),freq(w2)分别表示w1,w2在语料库中出现的统计次数。
利用语料库建立的统计概率,对于一个新的句子,我们就可以通过计算各种分词方法对应的联合分布概率,找到最大概率对应的分词方法,即为最优分词。
这样也是可以的,只不过这样联合分布的计算量就大大增加了。我们一般称只依赖于前一个词的模型为二元模型(Bi-Gram model),而依赖于前两个词的模型为三元模型。以此类推,我们可以建立四元模型,五元模型,...一直到通用的N元模型。越往后,概率分布的计算复杂度越高。当然算法的原理是类似的。
在实际应用中,N一般都较小,一般都小于4,主要原因是N元模型概率分布的空间复杂度为O(|V|N),其中|V|为语料库大小,而N为模型的元数,当N增大时,复杂度呈指数级的增长。
N元模型的分词方法虽然很好,但是要在实际中应用也有很多问题,首先,某些生僻词,或者相邻分词联合分布在语料库中没有,概率为0。这种情况我们一般会使用拉普拉斯平滑,即给它一个较小的概率值,这个方法在朴素贝叶斯算法原理小结也有讲到。第二个问题是如果句子长,分词有很多情况,计算量也非常大,这时我们可以用下一节维特比算法来优化算法时间复杂度。
图中的箭头为通过统计语料库而得到的对应的各分词位置BEMS(开始位置,结束位置,中间位置,单词)的条件概率。比如P(生|人)=0.17。有了这个图,维特比算法需要找到从Start到End之间的一条最短路径。对于在End之前的任意一个当前局部节点,我们需要得到到达该节点的最大概率δ,和记录到达当前节点满足最大概率的前一节点位置Ψ。
我们先用这个例子来观察维特比算法的过程。首先我们初始化有:
δ(人)=0.26 Ψ(人)=Start
δ(人生)=0.44 Ψ(人生)=Start
对于节点"生",它只有一个前向节点,因此有:
δ(生)=δ(人)P(生|人)=0.0442 Ψ(生)=人
对于节点"如",就稍微复杂一点了,因为它有多个前向节点,我们要计算出到“如”概率最大的路径:
δ(如)=max{δ(生)P(如|生),δ(人生)P(如|人生)}=max{0.01680,0.3168}=0.3168 Ψ(如)=人生
类似的方法可以用于其他节点如下:
由于最后的最优解为“梦境”,现在我们开始用Ψ反推:
Ψ(End)=梦境→Ψ(梦境)=如→Ψ(如)=人生→Ψ(人生)=start
从而最终的分词结果为"人生/如/梦境"。是不是很简单呢。以上~