词,在中文里面是个很模糊的定义。英文的基本单位是单词,而中文的基本单位则是字,由字组成的词是千变万化的,这也体现出我们中华民族文化的博大精深。实现中文的分词是现代汉语学的难点,本文针对一些目前比较成熟的方法进行一些阐述。
规则分词法,是一种很机械的分词方法。就类似于我们查词典的形式,如果有这个词按词划分并记录下来,没有就当做一个字来划分。这种方法简单高效,但是由于词海的更新,维护这个词典是能否很好实现分词的关键所在。
正向最大匹配法(MM法)
从一句话中从左至右选取最大长度为m的字符串,m是机器最大能接受的字符数量。
将这个字符串放在词典里面进行匹配,看能不能找到。如果找到了,将这一字符串抓取出来,作为分词的结果;如果没有找到,那么就将这个字段的最后一个字去掉,剩下的重新在词典里面进行匹配,有就作为分词的结果,还没有就继续去掉最后一个字。直至在词典中找到匹配或是最后去掉着去掉着只剩下第一个字(这时就以字的形式保留分词)
经过了步骤2,总的字符串数肯定会有所减少,那么将剩下的字符串重新代入步骤2中,就会得到整个句子的分词结果。
看了上述的流程,可能还是有点懵,那么,我们就开始用例子加深理解,其中我们要分割的语句为“武汉市长江大桥”,我们构建的词典中的词有‘’武汉“,”武汉市长“,”市长“,”长江“,”大桥“。看懂上述流程的小伙伴应该已经知道了分词的结果,为”武汉市长/江/大桥“。我们假想将上述语句输入机器中,机器将这7个字符与词典进行匹配,没有。于是采用分割,分割至武汉市长,有了。将其保留至分词的结果。然后将后面的”江大桥“与词典进行匹配,没有。然后分割,得到”江“一个字,保留至分词结果。同理也可得到”大桥“。下面我们用代码来进行验证。
def forward_maximal_matching(s, vocab):
result = []
end_pos = len(s)
start_pos = 0
while start_pos < len(s):
found = False
for end_pos in range(len(s), start_pos, -1):
if s[start_pos:end_pos] in vocab:
# 找到最长匹配的单词,放在分词结果最前面
result = result + [s[start_pos:end_pos]]
found = True
break
if found:
start_pos = end_pos
else:
# 未找到匹配的单词,将单字作为词分出
result = result + [s[start_pos]]
start_pos += 1
return result
s0 = '武汉市长江大桥'
vocab0 = ['武汉', '武汉市长', '市长', '长江', '大桥']
ans = forward_maximal_matching(s0, vocab0)
print(ans) #输出结果就是['武汉市长','江','大桥']
逆向最大匹配法(RMM法)
与正向最大匹配法思路相似。
从一句话中选取最末端的最大长度为m的字符串,m是机器最大能接受的字符数量。
将这个字符串放在词典里面进行匹配,看能不能找到。如果找到了,将这一字符串抓取出来,作为分词的结果;如果没有找到,那么就将这个字段的最前面一个字去掉,剩下的重新在词典里面进行匹配,有就作为分词的结果,还没有就继续去掉最前面一个字。直至在词典中找到匹配或是最后去掉着去掉着只剩下最后一个字(这时就以字的形式保留分词)
经过了步骤2,总的字符串数肯定会有所减少,那么将剩下的字符串重新代入步骤2中,就会得到整个句子的分词结果。
我们还是以上面的例子为例,语句和词典都完全一样,看懂的小伙伴们估计心里也有RMM法的答案了,即“武汉/市/长江/大桥”。我们用代码验证一下。
def backward_maximal_matching(s, vocab):
result = []
end_pos = len(s)
while end_pos > 0:
found = False
for start_pos in range(end_pos):
if s[start_pos:end_pos] in vocab:
# 找到最长匹配的单词,放在分词结果最前面
result = [s[start_pos:end_pos]] + result
found = True
break
if found:
end_pos = start_pos
else:
# 未找到匹配的单词,将单字作为词分出
result = [s[end_pos - 1]] + result
end_pos -= 1
return result
s0 = '武汉市长江大桥'
vocab0 = ['武汉', '武汉市长', '市长', '长江', '大桥']
ans = backward_maximal_matching(s0, vocab0)
print(ans) #输出结果为['武汉','市','长江','大桥']
从上面的例子可以看出同一个句子,同一个词库,使用的方法不同,得到的结果也不尽相同,当然它们都有出错的时候。具体的研究表明,由于中文语句中偏正结构使用很多,所以RMM法比MM法的正确率高一点。比如说“武汉市长江大桥”一例,句子的重心放在后面,所以逆向算法往往优于正向算法
基于规则分词法,就写到这里,后面继续更新中......
本文章使用limfx的vsocde插件快速发布