本次实验内容是基于词典的双向匹配算法的中文分词算法的实现。使用正向和反向最大匹配算法对给定句子进行分词,对得到的结果进行比较,从而决定正确的分词方法。

算法描述
正向最大匹配算法
先设定扫描的窗口大小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实现的更多相关文章

  1. Elasticsearch(10) --- 内置分词器、中文分词器

    Elasticsearch(10) --- 内置分词器.中文分词器 这篇博客主要讲:分词器概念.ES内置分词器.ES中文分词器. 一.分词器概念 1.Analysis 和 Analyzer Analy ...

  2. 中文分词接口api,采用结巴分词PHP版中文分词接口

    中文分词,分词就是将连续的字序列按照一定的规范重新组合成词序列的过程.我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字.句和段能通过明显的分界符来简单划界,唯独词没有一个形式上 ...

  3. 关于yaha中文分词(将中文分词后,结合TfidfVectorizer变成向量)

    https://github.com/jannson/yaha # -*- coding: utf-8 -*- """ Created on Wed Aug 10 08: ...

  4. python中文分词:结巴分词

    中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...

  5. [python] 使用Jieba工具中文分词及文本聚类概念

    声明:由于担心CSDN博客丢失,在博客园简单对其进行备份,以后两个地方都会写文章的~感谢CSDN和博客园提供的平台.        前面讲述了很多关于Python爬取本体Ontology.消息盒Inf ...

  6. python 中文分词:结巴分词

    中文分词是中文文本处理的一个基础性工作,结巴分词利用进行中文分词.其基本实现原理有三点: 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG) 采用了动态规 ...

  7. 自制基于HMM的python中文分词器

    不像英文那样单词之间有空格作为天然的分界线, 中文词语之间没有明显界限.必须采用一些方法将中文语句划分为单词序列才能进一步处理, 这一划分步骤即是所谓的中文分词. 主流中文分词方法包括基于规则的分词, ...

  8. NLP自然语言处理 jieba中文分词,关键词提取,词性标注,并行分词,起止位置,文本挖掘,NLP WordEmbedding的概念和实现

    1. NLP 走近自然语言处理 概念 Natural Language Processing/Understanding,自然语言处理/理解 日常对话.办公写作.上网浏览 希望机器能像人一样去理解,以 ...

  9. 深度学习实战篇-基于RNN的中文分词探索

    深度学习实战篇-基于RNN的中文分词探索 近年来,深度学习在人工智能的多个领域取得了显著成绩.微软使用的152层深度神经网络在ImageNet的比赛上斩获多项第一,同时在图像识别中超过了人类的识别水平 ...

随机推荐

  1. 字节码联盟成立,WebAssembly 生态将完善网络安全性

    近日 Mozilla.Fastly.Intel 与 Red Hat 宣布成立联合组织 Bytecode Alliance(字节码联盟),该联盟旨在通过协作实施标准和提出新标准,以完善 WebAssem ...

  2. 《Web Development with Go》Mangodb插入map,slice,Embedded Documents

    这几个好理解, 更好的实现,再说. package main import ( "fmt" "log" "time" "gopkg ...

  3. Node.js上传文件出现Unexpected field

    上传文件时,input框的name值要与node接口中single(' ')中的参数一致,否则会报"意外字段的错" 前端用的layui 后端node接口

  4. POJ-2018 Authors Register Update your info Authors ranklist

    Best Cow Fences Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16945   Accepted: 5425 ...

  5. DNS解析服务结构图

    1.DNS(domain name system) 域名 <==> IP地址 DNS解析过程:

  6. Windows下第一个驱动程序

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 参考下面博客: VS2017搭建驱动开发环境WDK :https: ...

  7. INT 3 中断调试处理流程

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html INT 3 中断调试处理流程 一.调试器如何下INT 3 断点 1 ...

  8. (六十三)c#Winform自定义控件-箭头(工业)-HZHControls

    官网 http://www.hzhcontrols.com 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kww ...

  9. Python实现变声器功能,萝莉音御姐音都有的哦

    登录百度AL开发平台 在控制台选择语音合成 创建应用 填写应用信息 在应用列表获取(Appid.API Key.Secret Key) 6. 安装pythonsdk 安装使用Python SDK有如下 ...

  10. Linux介绍以及VMware和Centos的安装

    一. Linux介绍 1 Linux诞生的故事 Unix篇: 为了进一步强化大型主机的功能,让主机的资源可以提供更多的使用者来利用,所以在1964年, 由AT&A公司的贝尔实验室(Bell). ...