[NLP]分词

简介

分词是NLP的基本功能之一,现在发展比较成熟了,目前比较热门的分词工具有jieba,snownlp,pkuseg等等。分词工具的使用是比较简单的,具体查询相应的github项目即可,上面有比较好的示例。本文我们主要讲解一下分词的相关算法:前向最大匹配,后向最大匹配,语言模型,维特比算法等。现分别讲解如下。

前向最大匹配算法

一句话总结:根据参数最大匹配长度max_len,获取一句话中的最大匹配长度的子句,逐步判断子句是否在词典中,是则分词成功,否则删除子句中的最后一个字再进行判断,子句是否在字典中。

输入:一句话sent,词典dic,最大匹配长度max_len

输出:分词后的单词列表words

①获取sent中最大匹配长度的子句sub_sent,判断sub_sent是否在词典dic中

②如果在列表中,则将sub_sent存放进words中,原句sent更新为sent-sub_sent;

③否则,sub_sent中删除最后一个字,判断sub_sent[:-2]是否在词典中

④重复上述步骤,直到sent句子为空为止。

举例:sent = 我要去上学了,词典 = [我,要去,上学,了,上学了,要,去],max_len = 5

①sub_sent = 我要去上学,不在词典中,则将其更新为:sub_sent = 我要去上

②sub_sent = 我要去上,不在词典中,将其更新为:sub_sent = 我要去

③sub_sent = 我要去,不在词典中,将其更新为:sub_sent = 我要

④sub_sent = 我要,不在词典中,将其更新为:sub_sent = 我

⑤sub_sent = 我,在词典中,因此words = [我]

⑥顺移一位,sub_sent = 要去上学了,不在词典中,更新为sub_sent = 要去上学

⑦sub_sent = 要去上学,不在词典中,更新为sub_sent = 要去上

⑧sub_sent = 要去上,不在词典中,更新为sub_sent = 要去

⑨sub_sent = 要去,在词典中,words = [我,要去]

⑩顺移一位,sub_sent = 上学了,在词典中,words = [我,要去,上学了]

最终返回的分词结果是:[我,要去,上学了]

后向最大匹配算法

前向最大匹配取前max_len个字符,后向最大匹配取后面max_len个字符。

举例:sent = 我要去上学了,词典 = [我,要去,上学,了,上学了,要,去],max_len = 5

①sub_sent = 要去上学了,不在词典中,则将其更新为:sub_sent = 去上学了

②sub_sent = 去上学了,不在词典中,将其更新为:sub_sent = 上学了

③sub_sent = 上学了,在词典中,words=[上学了]

④顺移一位,sub_sent = 我要去,不在词典中,将其更新为:sub_sent = 要去

⑤sub_sent = 要去,在词典中,因此words = [要去,上学了]

⑥顺移一位,sub_sent = 我,在词典中,words=[我,要去,上学了]

最终返回的分词结果是:[我,要去,上学了]

最大匹配的缺点:

①不够细分(有可能更好)

②局部最优

③效率(max_len)

④歧义(不能考虑语义

考虑语言模型(考虑语义)

语言模型就是为了计算一句话符合语义的程度,通过计算一句话的概率表示这句话的自然程度(或者说符合语义的程度)

过程:输入 -> 生成所有可能的分割 -> 选择其中最好的分词组合(工具,如unigram LM)

假设s1 = [我,要去,上学了],s2 = [我,要,去,上学,了]

分别计算概率:p(s1)=p(我,要去,上学了)=0.2,

p(s2)=p(我,要,去,上学,了)=0.4,可知,s2的分词效果更好。

这是unigram LM的模型,考虑了语义,选择最好的分词组合。(关于语言模型

缺点:复杂度高,效率低;概率计算有可能会溢出(解决办法是用log,这样乘法就变成了加法)

维特比算法(解决效率问题)

生成所有可能的分词后,可以将其转化成图来做,如下面例子所示。

转化成图之后,计算最佳的分词组合就是计算图的最短路径(之所以最短路径是取了词的概率的负对数,这样可以计算最小值),可以用维特比算法,核心是动态规划。

分词1

 

总结

分词的方法如下:

基于匹配规则的方法(最大匹配算法)

基于概率统计的方法(LM,HMM,CRF)

 

——来源于贪心科技NLP讲解

 

原文地址:https://www.cnblogs.com/mj-selina/p/12853082.html