Python基于规则中文分词(正向最大匹配,逆向最大匹配,双向最大匹配)
最大匹配方法(基于规则的)是一种基于词典和规则的一种分词方法,最大的缺点是严重依赖词典,未登录词和分词歧义无法很好的处理 。优点是方法简单,容易实现,速度快,有一定规模的词典效果可以满足基本需求。
1.正向最大匹配法
正向最大匹配(Maximum Mach Method ,MM法) 基本算法描述: (1)从左向右取待切分汉语句的m 个字符作为匹配字段,m是词典中最长的词条的字符数 。 (2) 查找词典并进行匹配。 若匹配成功,则将这个匹配字段作为一个词切分出来。若匹配不成功,则将匹配字段的最后一个字去掉,然后剩下的字符串作为新的匹配字段,再进行匹配,重复以上过程,直到切分出所有词为止。算法基本实现如下:
class MM():
'''
正向最大匹配法
'''
def __init__(self, train):
"""
:param train: 训练数据(每个元素是分词后的一个句子)
"""
self.max = 0
self.list = []
[self.list.append(word) for line in train for word in line.split() if word not in self.list] # 去掉重复的单词
self.list = sorted(self.list, key=lambda i: len(i), reverse=True) # 排序 (可无可有,排序后第一个元素的长度最大)
self.max = len(self.list[0]) # 训练数据中最长单词的长度
def cut(self, text):
'''
:param text: 待分词字符串
:return: 分词结果(列表:每一个元素都是一个单词)
'''
result = []
index = 0
while index < len(text):
word = None
for size in range(self.max, 0, -1):
if len(text) < size:
continue
piece = text[index:size + index]
if piece in self.list: # 当前匹配段
word = piece
result.append(word)
index += size
break
if word == None:
# 如果是个未登录词 作为单独的一个单独的单词
result.append(text[index])
index += 1
return result
if __name__ == "__main__":
# 训练数据
train = ['我 是 北京 大学 的 学生 。', '我 是 中华人民共和国 公民 , 坚决 拥护 中国 共产党 的 领导 。']
# 训练并测试
print(MM(train).cut("我是中华人民共和国公民,坚决拥护中国共产党的领导。"))
运行结果:
正向最大匹配法.png
2.逆向最大匹配法
逆向最大匹配(Reverse Maximum Match Method,RMM) 的基本原理是与MM 法相同,只不过分词切分方向与MM法相反。RMM是从被处理文本的末段开始匹配扫描,每次去末尾段m 个字符作为匹配字段,若匹配失败,则去掉匹配字段的最前面的一个字,继续匹配。这样可以适当的提高精确度 。基本实现如下:
class RMM():
'''
逆向最大匹配法
'''
def __init__(self, train):
"""
:param train: 训练数据(每个元素是分词后的一个句子)
"""
self.max = 0
self.list = []
[self.list.append(word) for line in train for word in line.split() if word not in self.list] # 去掉重复的单词
self.list = sorted(self.list, key=lambda i: len(i), reverse=True) # 排序 (可无可有,排序后第一个元素的长度最大)
self.max = len(self.list[0]) # 训练数据中最长单词的长度
def cut(self, text):
'''
:param text: 待分词字符串
:return: 分词结果(列表:每一个元素都是一个单词)
'''
result = []
index = len(text)
while index > 0:
word = None
for size in range(self.max, 0, -1):
if index - size < 0:
continue
piece = text[(index - size):index]
if piece in self.list:
word = piece
result.append(word)
index -= size
break
if word == None:
result.append(text[index - 1])
index -= 1
return result
if __name__ == "__main__":
# 训练数据
train = ['我 是 北京 大学 的 学生 。', '我 是 中华人民共和国 公民 , 坚决 拥护 中国 共产党 的 领导 。']
# 训练并测试
print(RMM(train).cut("我是中华人民共和国公民,坚决拥护中国共产党的领导。")[::-1])
运行结果:
逆向最大匹配.png
3.双向最大匹配法
双向最大匹配(Bi-direction Matching Method) 是将正向最大匹配法得到的分词结果和逆向最大匹配法得到的结果进行比较,然后按照最大匹配原则,选取次数切分最少的作为结果。双向最大匹配法也可以适当的提高精确度,也在中文信息处理系统中得以广泛使用。以下是算法基本实现:
from mm import MM
from rmm import RMM
class BiMM():
'''
双向最大匹配
'''
def __init__(self, train):
self.mm = MM(train) # 正向最大匹配
self.rmm = RMM(train) # 逆向最大匹配
def cut(self, txt):
'''
:param txt: 待分词字符串
:return: 分词结果(列表:每一个元素都是一个单词)
'''
res_mm = self.mm.cut(txt) # 正向匹配
print("正向最大匹配:", res_mm)
res_rmm = self.rmm.cut(txt)
print("逆向最大匹配:", res_rmm) # 逆向匹配
return res_rmm[::-1] if len(res_rmm) <= len(res_mm) else res_mm # 选取字数最小的一个作为分词结果
if __name__ == "__main__":
# 训练数据
train = ['他 是 北京市长 陈吉宁 。', '你 去过 长江大桥 么 ?', '我 家 在 北京市 。', '在 大桥 附近 。']
# 训练并测试
print("双向最大匹配:", BiMM(train).cut("北京市长江大桥"))
运行结果:
双向最大匹配.png
4.总结
1.最大匹配方法简单,容易实现,速度快,有一定规模的词典效果可以满足基本需求。
2.严重依赖词典,未登录词和分词歧义无法很好的处理
网友评论