用python实现FMM和BMM
词是自然语言中能够独立运用的最小单位,是自然语言处理的基本单位。
自动分词分析就是利用计算机对自然语言的形态进行分析,判断词的结构和类别等。
最大匹配法(Maximum Match Method)
- 正向最大匹配算法(Forward MM,FMM)
- 逆向最大匹配算法(Backward MM,BMM)
- 双向最大匹配法(Bi-directional MM)
算法流程
前向最⼤匹配算法(FMM):
(1)待切分的汉字串 s1 ,已切分的汉字串 s2(初始为空);
(2)如果 s1 为空串,转到(6);
(3)从 s1 的左边复制⼀个⼦串 w 作为候选词, w 尽可能长,但不超过最⼤词长;
(4)如果在词表中能找到 w,或者 w 的长度为2(这个数值可以自己根据情况设定,通常为词表内最短的词的长度),那么,将 w 和⼀个界词标记⼀起加到 s2 的右边,并从 s1 的左边去掉 w,转 到(2);
(5)去掉w的最后⼀个汉字,转到(4);
(6)结束。
实例
给定词表:
['他', '是', '研究', '研究⽣', '⽣物', '物化', '化学', '⽣物化学', '的', '⼀位', '科学家', '学']
待划分句⼦:
"他是研究⽣物化学的⼀位科学家"
最⼤词长:
MaxWordLength = 8 (汉字)
划分过程
FMM划分过程:
1、考虑子串 "他是研究生物化学" ,判断其不再给定词表中,因此,删除最后一个汉字,考虑子串 "他是研究生物化",再次判断其不再给定词表中,因此,再次删除最后一个汉字;重复这个过程,直到最后只剩一个汉字或考虑的子串在给定的词表中,通过这一轮划分,可以将 '他' 划分出来。
2、将 '他' 从待划分句子中排出,考虑子串 "是研究生物化学的"。重复(1)中的步骤,最终可以把 '是' 划分出来。
3、重复上述的步骤,可以得到最终的划分结果。
FMM划分结果:他/是/研究⽣/物化/学/的/⼀/位/科学家
BMM的原理和FMM差不多,只不过BMM是从后往前划分,如上述例子,BMM先考虑子串 "化学的一位科学家",不再给定词表中,BMM删除的是子串的第一个汉字。
BMM划分结果:他/是/研究/⽣物化学/的/⼀位/科学家
从划分结果可以看出,FMM和BMM的划分并不同,在这个例子中显然BMM的划分更好。
代码实现
# -*- coding:utf-8 -*-def FMM(user_dict, sentence):""""前向最大匹配算法 FMM"""segment_words = [] # 用于保存已经划分好的词max_len = max([len(item) for item in user_dict]) # 获得给定的词表中最长词的长度start = 0 # 起始划分位置,FMM从前往后划分nums = 1 # 记录划分轮数print("FMM:")print("*****开始切分*****")while start != len(sentence):index = start + max_len # 每一轮划分考虑 index-start=max_len 长度if index > len(sentence): # 如果当前的 index 位置超过了句子长度,则让其指向句子的最后index = len(sentence)for i in range(max_len):print(sentence[start:index])# 如果当前考虑的词在我们给定的词表中或者词的长度已经等于1,就将其加入到划分好的列表中if (sentence[start:index] in user_dict)\or (len(sentence[start:index]) == 1):segment_words.append(sentence[start:index])start = indexbreakindex -= 1print('当前已切分:', segment_words)print("————第 %d 轮结束————" % nums)nums += 1return segment_wordsdef BMM(user_dict, sentence):""""逆向最大匹配算法 BMM"""# 大部分代码同FMM一致,只需把start转换为end即可segment_words = []max_len = max([len(item) for item in user_dict])end = len(sentence) # 起始划分位置,BMM从后往前划分nums = 1 # 记录划分轮数print("BMM:")print("*****开始切分*****")while end != 0:index = end - max_len # 每一轮划分考虑 end-index=max_len 长度if index < 0:index = 0for i in range(max_len):print(sentence[index:end])if (sentence[index:end] in user_dict)\or (len(sentence[index:end]) == 1):segment_words.append(sentence[index:end])end = indexbreakindex += 1print('当前已切分:', segment_words)print("————第 %d 轮结束————" % nums)nums += 1return segment_wordsif __name__ == '__main__':user_dict = ['时间', '就', '是', '生命'] # 给定词表sentence = "时间就是生命" # 待划分的例句# 使用FMM划分segment_words = FMM(user_dict, sentence)print("最终结果:\n", segment_words)print()# 使用BMM划分segment_words = BMM(user_dict, sentence)print("最终结果:\n", segment_words[::-1]) # 由于BMM是逆向划分的,将其倒转就与例句中词的出现顺序一致了
上述代码考虑的实例:
词表:['时间', '就', '是', '生命']
例句:"时间就是生命"
划分结果:
FMM:
*****开始切分*****
时间
当前已切分: ['时间']
————第 1 轮结束————
就是
就
当前已切分: ['时间', '就']
————第 2 轮结束————
是生
是
当前已切分: ['时间', '就', '是']
————第 3 轮结束————
生命
当前已切分: ['时间', '就', '是', '生命']
————第 4 轮结束————
最终结果:['时间', '就', '是', '生命']BMM:
*****开始切分*****
生命
当前已切分: ['生命']
————第 1 轮结束————
就是
是
当前已切分: ['生命', '是']
————第 2 轮结束————
间就
就
当前已切分: ['生命', '是', '就']
————第 3 轮结束————
时间
当前已切分: ['生命', '是', '就', '时间']
————第 4 轮结束————
最终结果:['时间', '就', '是', '生命']进程已结束,退出代码为 0
从这个例子可以看出,FMM和BMM的划分结果相同,我们现在将代码的词表和例句改为上述的例子:
词表:['他', '是', '研究', '研究⽣', '⽣物', '物化', '化学', '⽣物化学', '的', '⼀位', '科学家', '学']
例句:"他是研究⽣物化学的⼀位科学家"
划分结果:
FMM:
*****开始切分*****
他是研究
他是研
他是
他
当前已切分: ['他']
————第 1 轮结束————
是研究⽣
是研究
是研
是
当前已切分: ['他', '是']
————第 2 轮结束————
研究⽣物
研究⽣
当前已切分: ['他', '是', '研究⽣']
————第 3 轮结束————
物化学的
物化学
物化
当前已切分: ['他', '是', '研究⽣', '物化']
————第 4 轮结束————
学的⼀位
学的⼀
学的
学
当前已切分: ['他', '是', '研究⽣', '物化', '学']
————第 5 轮结束————
的⼀位科
的⼀位
的⼀
的
当前已切分: ['他', '是', '研究⽣', '物化', '学', '的']
————第 6 轮结束————
⼀位科学
⼀位科
⼀位
当前已切分: ['他', '是', '研究⽣', '物化', '学', '的', '⼀位']
————第 7 轮结束————
科学家
当前已切分: ['他', '是', '研究⽣', '物化', '学', '的', '⼀位', '科学家']
————第 8 轮结束————
最终结果:['他', '是', '研究⽣', '物化', '学', '的', '⼀位', '科学家']BMM:
*****开始切分*****
位科学家
科学家
当前已切分: ['科学家']
————第 1 轮结束————
学的⼀位
的⼀位
⼀位
当前已切分: ['科学家', '⼀位']
————第 2 轮结束————
物化学的
化学的
学的
的
当前已切分: ['科学家', '⼀位', '的']
————第 3 轮结束————
⽣物化学
当前已切分: ['科学家', '⼀位', '的', '⽣物化学']
————第 4 轮结束————
他是研究
是研究
研究
当前已切分: ['科学家', '⼀位', '的', '⽣物化学', '研究']
————第 5 轮结束————
他是
是
当前已切分: ['科学家', '⼀位', '的', '⽣物化学', '研究', '是']
————第 6 轮结束————
他
当前已切分: ['科学家', '⼀位', '的', '⽣物化学', '研究', '是', '他']
————第 7 轮结束————
最终结果:['他', '是', '研究', '⽣物化学', '的', '⼀位', '科学家']进程已结束,退出代码为 0
FMM的划分结果:
['他', '是', '研究⽣', '物化', '学', '的', '⼀位', '科学家']
BMM的划分结果:
['他', '是', '研究', '⽣物化学', '的', '⼀位', '科学家']
可以看出两者的划分结果并不相同。
用python实现FMM和BMM相关推荐
- FMM和BMM的python代码实现
FMM和BMM的python代码实现 FMM和BMM的编程实现,其实两个算法思路都挺简单,一个是从前取最大词长度的小分句,查找字典是否有该词,若无则分句去掉最后面一个字,再次查找,直至分句变成单词或者 ...
- FMM和BMM分词题目
题目:假设词典中包括词{的确,王公,实在,在理,公子}以及所有单字集合,请分别给出句子"王公子说的确实在理"的FMM和BMM分词结果. FMM分词结果: 王公/子/说/的确/实在/ ...
- 词频统计,中文分词FMM,BMM博客
分词 | 双向匹配中文分词算法python实现 https://blog.csdn.net/Elenore1997/article/details/83274720 正向最大匹配算法实现之python ...
- 中文分词的古今中外,你想知道的都在这里
作者:QvQ,夕小瑶,小鹿鹿鹿 前言 分词(word tokenization),也叫切词,即通过某种方式将句子中的各个词语识别并分离开来,使得文本从"字序列"的表示升级为&quo ...
- 史上最全的分词算法与工具介绍
分词(word tokenization),也叫切词,即通过某种方式将句子中的各个词语识别并分离开来,使得文本从"字序列"的表示升级为"词序列"表示.分词技术不 ...
- 中文分词算法之--最大匹配法
中文分词算法之–最大匹配法 前段时间研究了如何用分词工具进行分词,但是分词中涉及的一些算法,不太了解,所以,准备这段时间专攻分词算法原理,大家有补充,或者建议,欢迎留言. 1. 最大匹配法(Max ...
- NLP-基础任务-中文分词算法(1)-基于词典: 机械分词(词典字符串匹配):前向最大匹配、后向最大匹配、双向最大匹配【OOV:基于现有词典,不能进行新词发现处理】
分词与NLP关系:分词是中文自然语言处理的基础,没有中文分词,我们对语言很难量化,进而很能运用数学的知识去解决问题.对于拉丁语系是不需要分词的. 拉丁语系与亚系语言区别 拉丁语言系不需要分词,因为他们 ...
- 中文分词方法汇总笔记
中文分词方法汇总笔记 分词难点 分词方法 传统基于字典(规则分词) 基于机器学习的分词方法 统计分词 语言模型 隐马尔可夫 HMM 模型 其他 分词工具和云服务 其他 感谢知乎 @华天清 的总结 分词 ...
- 【自然语言处理与文本分析】中文分词的基本原理,如何进行词性标注 使用HMM算法提高准确率
分词(中文) 本次内容 分词: N-Gram vs.中文分词 分词的难点 法则式分词 统计式分词 词性标注: 词性标注简介 词性标注的难点 词性的种类及意义 保留某些词性的词 分词: N-Gram v ...
最新文章
- ‘utf-8‘ codec can‘t decode byte 0xa8 in position 1210: invalid start byte报错解决
- android wm 改变大小,Android 屏幕适配经验总结
- java 链表实现堆栈_《Java数据结构与算法》笔记-CH5-链表-4用链表实现堆栈
- 一个小栗子聊聊JAVA泛型基础
- [css] 你知道什么是面向对象的css(oocss)吗?有没有实践过?
- 15款精美的 WordPress 电子商务网站模板
- 微众银行在联邦推荐算法上的探索及应用(文末附PPT下载链接)
- socket编程(三)
- Synchronous Bidirectional Inference for Neural Sequence Generation
- 网站测试自动化系统—在测试代码中硬编码测试数据
- Excel表格数据生成ECharts图表
- 局域网共享工具_Win10局域网共享开启工具
- 风机盘管介绍,及其控制 (1)
- DSP eQEP正交编码
- 后台管理系统 - 权限设计
- 关系数据库的三大范式以及BCNF范式
- 双窗格文件管理器:Commander One PRO Mac中文版
- mysql 5.7的my.ini的位置在隐藏文件夹“ProgramData”下面
- ac3168无线网卡驱动下载_台式机无线网卡驱动怎么安装
- python查看图片的源代码,python网络爬虫源代码(可直接抓取图片)
热门文章
- Java代码分析器(一): JDT入门
- vue实现分屏_WebRTC如何在Vue.js 配合video标签实现多分屏功能?
- “熊猫烧香”主犯:毒王?黑客英雄?
- linux 编译-l,GCC编译器下的-L与-l的区别
- 关于物联网卡,您想了解的都在这里
- python 绘制多分类变量折线图
- 孙悟空在大闹蟠桃园的时候,第一天吃掉了所有桃子总数一半多一个,第二天又将剩下的桃子吃掉一半多一个,以后每天吃掉前一天剩下的一半多一个,到第n天准备吃的时候只剩下一个桃子。第一天开始吃的时候一共有多少个
- win用户计算机批量添加用户,win10系统巧用cmd命令快速创建新账户的技巧
- 使用certbot openresty执行获取 Let’s Encrypt https 免费证书
- [java8] Stream流