1.常用的分词工具
调用 jieba
2. 分词方法1 —前向最大匹配法
注意:做分词必须有一个词典库,定义最大匹配法的 max_len = 5
从前往后扫描句子:
第一次扫描:
① [我们经常有] — 这5个字的组合不在词典中,因此 ×
② [我们经常] — 这4个字的组合不在词典中,因此 ×
③ [我们经] — 这3个字的组合不在词典中,因此 ×
④ [我们] — 这2个字的组合在词典中,因此 √
第二次扫描:
① [经常有意见] — 这5个字的组合不在词典中,因此 ×
② [经常有意] — 这4个字的组合不在词典中,因此 ×
③ [经常有] — 这3个字的组合不在词典中,因此 ×
④ [经常] — 这2个字的组合在词典中,因此 √
第三次扫描:
① [有意见分歧] — ×
② [有意见分] — x
③ [有意见] — √
第四次扫描:
① [分歧] — √
所以最后的分词结果: 我们 | 经常 | 有意见| 分歧
3.分词方法2 — 后向最大匹配法
与前向方法类似,只是 从后往前 扫描。这里就不详细说明了
4.最大匹配法的缺点
- 效率问题,max_len 越大,算法效率越低,时间复杂度越高
- 不能考虑语义信息,也就不能解决歧义问题
s1 = 我们| 经常| 有意见| 分歧
s2 = 我们 |经常 |有| 意见 |分歧
s1,s2到底哪个更好呢?
要想解决语义问题:必须借助语言模型
语言模型:通俗讲就是判断一句话是不是人话,具体细节这里就不说了
下图简单表示了unigram语言模型的计算例子,通过统计的方式计算概率
5. 解决效率问题
5.1
这张图的分词结果是由两步生成的。
step1:先生成所有
step2:再选择最好
这两步是分开,独立的,导致算法效率很低。
解决方法: 维特比算法,可以结合step1和step2来求解
用一个例子来说明:
上图中"概率" 和 -log(x) 的意思:
概率: p(单词) , 如 p(“经常”) = 0.1, p(“经”) = 0.05 …
-log(x) : -log ( p(“单词”) ), 如 -log( p(‘经常")) = 2.3, -log( p(“经”) ) = 3 …
维特比算法流程:
step1:维特比算法开始时都会画一个图,如下
图中每个箭头代表一个单词
step2:在箭头上标出每个单词的-log概率,这时候会发现 有的词不在词典库中,解决方法是:我们提前已经定义好 p(其他单词) = 0.0000001, 表示其他单词出现的概率很小。
所以: -log (p(经)) = 3 , -log(p(常)) = -log(p(其他单词)) = 16, -log(p(有)) = 2.3,…
step3: 两个单词的组合。如 “经常” 出现在词典库(标上它的-log概率), “常有” 没有出现在词典库中,所以不连箭头;“有意” 没有出现在词典库中,所以不连箭头;“意见” 出现在词典中,所以连箭头,并标上它的 -log 概率;”见分“ 没有出现在词典库中,所以不连箭头;”分歧“ 出现在词典中,所以连箭头,并标上它的 -log 概率;
step4:三个单词的组合。”经常有“ 没有出现在词典库;”常有意“ 没有出现在词典库;”有意见“ 出现在词典库,所以所以连箭头,并标上它的 -log 概率; ”意见分“ 没有出现在词典库中,所以不连箭头; ”见分歧“ 出现在词典库所以连箭头,并标上它的 -log 概率;
step5:由于词典库中并没有四个单词的组合,所以,所有情况都已经画出来了
5.2 根据上图开始计算
图中从开始到结束的每条路径都可以是一个分词结果,我们想要的路径是 -log 概率之和(score)最小的那条。寻找的思想其实就是 动态规划
我们先定义一个函数:f
f(8) : 从节点1 到节点 8 的最短路径的score值;
f(7) : 从节点1 到节点 7 的最短路径的score值;
f(6) : 从节点1 到节点 6 的最短路径的score值;
…
我们要求的是 f(8)
- 我们看,到节点8的箭头有三条:
. a) 从节点5 出发到节点8 ,
. b) 从节点6 出发到节点 8;
. c) 从节点7 出发到节点8
所以我们可以将 f(8)表示成:
同样 f(7) 可以表示为:
f(6)可以表示为
f(5)可以表示为:
f(4)可以表示为:
f(3)可以表示为:
f(2)可以表示为 - 代入数字:
. f(1) = 0, 记录下位置:即从开始 到的节点1
. f(2) = 0 + 3 = 3 , 记录下位置:即从节点1 到的节点2
. f(3) = min [ 0 + 2.3, 3+ 16] = 2.3 , 记录下位置:即从节点1 到的节点3
. f(4) = f(3) + 2.3 = 4.6, 记录下位置:即从节点3 到的节点4
. f(5) = f(4) + 3 = 7.6, 记录下位置:即从节点4 到的节点5
. f(6) = min [ 2.3+ 2.3, 4.6+1.6, 7.6+ 3] = 4.6 , 记录下位置:即从节点3 到的节点6
. f(7) = f(7) + 2.3 = 6.9, 记录下位置:即从节点6 到的节点7
. f(8) = min [7.6+3, 4.6 + 1.6, 6.9+16] = 7.2, 记录下位置:即从节点6 到的节点8
所以: f(8) 最小的score值是 7.2
从f(8) 开始反推 路径: 节点6 – 节点3 — 节点1 —开始