分词 | 双向匹配中文分词算法python实现
本次实验内容是基于词典的双向匹配算法的中文分词算法的实现。使用正向和反向最大匹配算法对给定句子进行分词,对得到的结果进行比较,从而决定正确的分词方法。
算法描述
正向最大匹配算法
先设定扫描的窗口大小maxLen(最好是字典最长的单词长度),从左向右取待切分汉语句的maxLen个字符作为匹配字段。查找词典并进行匹配。若匹配成功,则将这个匹配字段作为一个词切分出来,并将窗口向右移动这个单词的长度。若匹配不成功,则将这个匹配字段的最后一个字去掉,剩下的字符串作为新的匹配字段,进行再次匹配,重复以上过程,直到切分出所有词为止。
反向最大匹配算法
该算法是正向的逆向算法,区别是窗口是从后向左扫描,若匹配不成功,则去掉第一个字符,重复上述的匹配步骤。
双向最大匹配算法
双向最大匹配法是将正向最大匹配法得到的分词结果和逆向最大匹配法的到的结果进行比较,从而决定正确的分词方法。定义的匹配规则如下:
如果正反向匹配算法得到的结果相同,我们则认为分词正确,返回任意一个结果即可。
如果正反向匹配算法得到的结果不同,则考虑单字词、非字典词、总词数数量的数量,三者的数量越少,认为分词的效果越好。我们设定一个惩罚分数(score_fmm / score_bmm = 0),例如:正向匹配中单字词数量多于反向匹配,则正向匹配的分值score_fmm += 1。其他两个条件相同。可以根据实际的分词效果调整惩罚分数的大小,但由于没有正确分词的数据,因此惩罚分数都设为1。最后比较惩罚分数,返回较小的匹配结果。
详例描述
以“对外经济技术合作与交流不断扩大。”为例,详细描述算法如下:
窗口大小设为4,句子长度为16,分词列表words = []。
首先是正向匹配。sub_str = ‘对外经济’与词典进行匹配,匹配失败,窗口大小减一。
sub_str = ‘对外经’与词典进行匹配,匹配失败,窗口大小减一。
sub_str = ‘对外’与词典进行匹配,匹配成功,窗口大小恢复为4,向右移动之前匹配词的长度,此时sub_str = ‘经济技术’,将其添加至列表words中。重复上述步骤。
当匹配到最后一个词时,算法停止。
正向匹配结果如下:[‘对外’, ‘经济’, ‘技术’, ‘合作’, ‘与’, ‘交流’, ‘不断’, ‘扩大’, ‘。’]
反向匹配如法炮制,结果如下:[‘对外’, ‘经济’, ‘技术’, ‘合作’, ‘与’, ‘交流’, ‘不断’, ‘扩大’, ‘。’]
正向与反向匹配结果相同,返回任意一个。
代码:
加载字典
def read_dict(path):
words_dict = []
with open(path, 'r') as r:
line = r.readlines()
# print(line)
for i in line:
word = i.split(',')
words_dict.append(word[0])
return words_dict window_size = 4
正向匹配算法
def fmm(source, words_dict):
len_source = len(source) # 原句长度
index = 0
words = [] # 分词后句子每个词的列表 while index < len_source: # 如果下标未超过句子长度
match = False
for i in range(window_size, 0, -1):
sub_str = source[index: index+i]
if sub_str in words_dict:
match = True
words.append(sub_str)
index += i
break
if not match:
words.append(source[index])
index += 1
return words
反向匹配算法
def bmm(source, word_dict):
len_source = len(source) # 原句长度
index = len_source
words = [] # 分词后句子每个词的列表 while index > 0:
match = False
for i in range(window_size, 0, -1):
sub_str = source[index-i: index]
if sub_str in words_dict:
match = True
words.append(sub_str)
index -= i
break
if not match:
words.append(source[index-1])
index -= 1
words.reverse() # 得到的列表倒序
return words
双向匹配算法
def bi_mm(source, word_dict):
forward = fmm(source, words_dict)
backward = bmm(source, words_dict)
# 正反向分词结果
print("FMM: ", forward)
print("BMM: ", backward)
# 单字词个数
f_single_word = 0
b_single_word = 0
# 总词数
tot_fmm = len(forward)
tot_bmm = len(backward)
# 非字典词数
oov_fmm = 0
oov_bmm = 0
# 罚分,罚分值越低越好
score_fmm = 0
score_bmm = 0
# 如果正向和反向结果一样,返回任意一个
if forward == backward:
return backward
# print(backward)
else: # 分词结果不同,返回单字数、非字典词、总词数少的那一个
for each in forward:
if len(each) == 1:
f_single_word += 1
for each in backward:
if len(each) == 1:
b_single_word += 1
for each in forward:
if each not in words_dict:
oov_fmm += 1
for each in backward:
if each not in backward:
oov_bmm += 1
# 可以根据实际情况调整惩罚分值
# 这里都罚分都为1分
# 非字典词越少越好
if oov_fmm > oov_bmm:
score_bmm += 1
elif oov_fmm < oov_bmm:
score_fmm += 1
# 总词数越少越好
if tot_fmm > tot_bmm:
score_bmm += 1
elif tot_fmm < tot_bmm:
score_fmm += 1
# 单字词越少越好
if f_single_word > b_single_word:
score_bmm += 1
elif f_single_word < b_single_word:
score_fmm += 1 # 返回罚分少的那个
if score_fmm < score_bmm:
return forward
else:
return backward
主函数,测试了分词的时间,包括加载词典的时间
if __name__ == '__main__':
start = time.time()
words_dict = read_dict('chineseDic.txt')
# print(bmm("我正在上自然语言处理课。", words_dict))
# print("result: ", result)
print("BiMM: ", bi_mm("对外经济技术合作与交流不断扩大。", words_dict))
end = time.time()
print("running time: " + str(end - start) + "s")
分词 | 双向匹配中文分词算法python实现的更多相关文章
- Elasticsearch(10) --- 内置分词器、中文分词器
Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...
- 中文分词接口api,采用结巴分词PHP版中文分词接口
中文分词,分词就是将连续的字序列按照一定的规范重新组合成词序列的过程.我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字.句和段能通过明显的分界符来简单划界,唯独词没有一个形式上 ...
- 关于yaha中文分词(将中文分词后,结合TfidfVectorizer变成向量)
https://github.com/jannson/yaha # -*- coding: utf-8 -*- """ Created on Wed Aug 10 08: ...
- python中文分词:结巴分词
中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...
- [python] 使用Jieba工具中文分词及文本聚类概念
声明:由于担心CSDN博客丢失,在博客园简单对其进行备份,以后两个地方都会写文章的~感谢CSDN和博客园提供的平台. 前面讲述了很多关于Python爬取本体Ontology.消息盒Inf ...
- python 中文分词:结巴分词
中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...
- 自制基于HMM的python中文分词器
不像英文那样单词之间有空格作为天然的分界线, 中文词语之间没有明显界限.必须采用一些方法将中文语句划分为单词序列才能进一步处理, 这一划分步骤即是所谓的中文分词. 主流中文分词方法包括基于规则的分词, ...
- NLP自然语言处理 jieba中文分词,关键词提取,词性标注,并行分词,起止位置,文本挖掘,NLP WordEmbedding的概念和实现
1. NLP 走近自然语言处理 概念 Natural Language Processing/Understanding,自然语言处理/理解 日常对话.办公写作.上网浏览 希望机器能像人一样去理解,以 ...
- 深度学习实战篇-基于RNN的中文分词探索
深度学习实战篇-基于RNN的中文分词探索 近年来,深度学习在人工智能的多个领域取得了显著成绩.微软使用的152层深度神经网络在ImageNet的比赛上斩获多项第一,同时在图像识别中超过了人类的识别水平 ...
随机推荐
- springboot打包 出错 Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1
遇到这个问题看了很多博客之后发现:执行这个语句就行了:mvn clean package -Dmaven.test.skip=true 本文链接:https://blog.csdn.net/weixi ...
- PC端视频播放器
视频播放器:Potplayer 它是一款纯净的.无广告.极速
- Windows10安装ubuntu18.04双系统教程
写在前面:本教程为windows10安装ubuntu18.04(64位)双系统教程,是我多次安装双系统的经验总结,安装方法同样适用于ubuntu16.04(64位).为了直观和易于理解,我会尽量图文并 ...
- 这可能是最漂亮的Spring事务管理详解
事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用 ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow (树上差分)
###题目链接### 题目大意: 给你一棵树,k 次操作,每次操作中有 a b 两点,这两点路上的所有点都被标记一次.问你 k 次操作之后,整棵树上的点中被标记的最大次数是多少. 分析: 1.由于数 ...
- ETCD:文档
原文地址:Documentation 文档 etcd是一个分布式键值对存储,被设计为可靠的,快速的保存并提供对关键数据的访问.通过分布式锁,领导选举和写屏障使能分布式一致性.一个etcd集群旨在实现高 ...
- javaWeb核心技术第十一篇之Listener
监听器:所谓的监听器是指对整个WEB环境的监听,当被监视的对象发生改变时,立即调用相应的方法进行处理. 监听术语: 事件源:被监听的对象. 监听器对象:监听事件源的对象 注册或绑定:1和2结合的过程 ...
- git如何合并远程2个分支
1,先检出项目到一个文件夹git clone 2,你检出的项目默认是master,所以现在要查看远程全部分支git branch -a * master remotes/origin/HEAD -&g ...
- es6 之class介绍
class ECMAScript 2015 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖.类语法不会为JavaScript引入新的面向对象的继承模型. ...
- Pyhton 连接数据库
Python连接MySql 步骤 开始 创建connection 获取cursor 操作过程 SQL语句 执行查询 执行命令 获取数据 处理数据 关闭游标:cursor.close() 关闭连接:co ...