NLP深入学习——分词(Segmentation )
文章目录
- 返回主目录
- 分词工具(Word Segmentation Tools)
- 分词方法(Segmentation Method)
- 1 前向最大匹配(forward-max matching)
- 2 后向最大匹配(backward-max matching)
- 3 双向最大匹配
返回主目录
这是一个系列的文章,点击返回综合目录页
分词工具(Word Segmentation Tools)
- Jieba分词:https://github.com/fxsjy/jieba
- SnowNLP:https://github.com/isnowfy/snownlp
- LTP:http://www.ltp-cloud.com/
- HanNLP:https://github.com/hankcs/HanLP/
- THULAC:https://github.com/thunlp/THULAC-Python
- NLPIR:https://github.com/NLPIR-team/NLPIR
- …
分词方法(Segmentation Method)
1 前向最大匹配(forward-max matching)
用图示来说明其思想及操作:
Python代码实现:
说明:为了突出应对不同的情况,如遇到没有收录的词汇。对测试的词库与测试的句子做了修改
词库(字典):word.txt
南京
南京市
长江
长江大桥
大桥
市长
北京
北京市长
烤鸭
南京烤鸭
class TMM(object):def __init__(self, dic_path):# 集合self.dictionary = set()self.maximum = 0# 读取词库(字典),并初始化词库(字典)及其长度with open(dic_path, 'r', encoding='utf8') as f:for line in f:line = line.strip()if line:self.dictionary.add(line)self.maximum = len(self.dictionary)def cut(self, text, max_len):result = [] # 用于存放切分出来的词index = max_lenno_word = '' # 记录没有在 词库(字典)中的词,可以用于发现新词while len(text) > 0:if index == 0: # 存储没有收录的词汇no_word += text[:index + 1]text = text[index + 1:]index = max_lenif text[:index] in self.dictionary:if no_word != '': # 把没有在 词库(字典)中的词 也存储的词汇加入分词后的结果中result.append(no_word)no_word = ''# 如果之前no_word存放了词库(字典)里面没有出现过的词result.append(text[:index])text = text[index:]index = max_lenelse:index -= 1return resultif __name__ == '__main__':text = '北京市长喜欢南京烤鸭和你南京市长江大桥'max_len = 5tokenizer = TMM('word.txt')print(tokenizer.cut(text, max_len))输出:
['北京市长', '喜欢', '南京烤鸭', '和你', '南京市', '长江大桥']
2 后向最大匹配(backward-max matching)
用图示来说明其思想及操作:
Python代码实现
说明:为了突出应对不同的情况,如遇到没有收录的词汇。对测试的词库与测试的句子做了修改
词库(字典):word.txt
南京
南京市
长江
长江大桥
大桥
南京市长
市长
北京
北京市长
烤鸭
南京烤鸭
class BKMM(object):def __init__(self, dic_path):# 集合self.dictionary = set()self.maximum = 0# 读取词库(字典),并初始化词库(字典)及其长度with open(dic_path, 'r', encoding='utf8') as f:for line in f:line = line.strip()if line:self.dictionary.add(line)self.maximum = len(self.dictionary)def cut(self, text, max_len):result = [] # 用于存放切分出来的词index = len(text) # 目标字符串的长度no_word = '' # 记录没有在 词库(字典)中的词,可以用于发现新词while index > 0:word = None# 实现 backward-max matching 算法for first in range(index - max_len if index > max_len else 0, index):if text[first:index] in self.dictionary:word = text[first:index]# 如果之前no_word存放了词库(字典)里面没有出现过的词if no_word != '': # 处理上次记录的不存在的词汇,比如 no_word='你和'result.append(no_word[::-1]) # 把不存在的词汇也加入result,因为这也是句子的一部分,# 反转是因为,之前存储的就是倒序的,比如 no_word='你和'no_word = '' # 置为空,用于存储下次不再词库(字典)中的词汇# 存储在词库(字典)中存在的词汇result.append(text[first:index])index = firstbreakif word == None: # 将不存在 词库(字典) 的词汇(单个词汇)加入index = index - 1no_word += text[index] # 注意:这里是倒序的,比如:和你-->在这里的no_word='你和'return result[::-1]if __name__ == '__main__':text = '北京市长喜欢南京烤鸭和你南京市长江大桥'max_len = 5tokenizer = BKMM('word.txt')print(tokenizer.cut(text, max_len))输出:
['北京市长', '喜欢', '南京烤鸭', '和你', '南京市', '长江大桥']
3 双向最大匹配
算法流程:
- 比较正向最大匹配和逆向最大匹配结果
- 如果分词数量结果不同,那么取分词数量较少的那个
- 如果分词数量结果相同:
- 分词结果相同,可以返回任何一个
- 分词结果不同,返回单字数比较少的那个
参考资料:
[1] https://blog.csdn.net/chenlei0630/article/details/40710441
[2] https://blog.csdn.net/qxdoit/article/details/83063794