中文分词中的匹配方法——机械分词法
中文分词 /Chinese Word Segmentation
近几年中文分词技术逐渐运用在很多领域。中文分词是自然语言处理的重要步骤。
分词就是将句子、段落、文章等连续的长文本,按照一定的规范重新组合分解,使其成为以字、词为基本单位的数据结构,从而方便后续的处理分析工作
为了让计算机能够更快理解中文文章,就需要提取出文章词与词分开。
对于我们新闻媒体领域而言,中文分词不仅是机器翻译等高级任务的基础、新闻自动归档任务的基础,也是人工智能新闻采写编辑的重要步骤。
中文分词相对于其他语言的分词来说有更大的难度
因为中文的单词之间没有间隔,需要通过语义来进行单词之间的匹配。这对于计算机来说具有非常大的挑战性。
所以针对中文单词的匹配,诞生出了各种技术
中文的分词方法一共分为了三类:
·机械分词方法
·基于统计的分词方法
·机器学习分词方法
其中机械分词方法是三者中最传统与最常见的方法
机械分词法
它是基于字典的分词方法,顾名思义就是将单词与字典中的词条进行匹配。如果识别到的一个词在字典中有出现就算识别成功。
按照不同的识别顺序,匹配方法又分为了正向匹配法和逆向匹配法。
按照不同长度优先匹配,又可以分为最大匹配法和最小匹配法。
我们最常见的匹配方法有正向最大匹配法、逆向最大匹配法与双向匹配法。
#以“我们在野生动物园玩“这个短句为例:
【正向最大匹配法】:先确定最长词的字数,接着从左到右,按照最大长度依次递减,直到出现在词典中存在的词,将词语截取下来。比如设定最大长度为5。机器就会从左到右选取五个字:”我们在野生”,显然这不是一个词语。于是依次递减一个字,“我们在野”、“我们在”都不是存在于词典中的词语。直到出现“我们”,将这个词语截取下来。紧接着又从“在”开始往右的5个字依次递减,直到出现“在野”。继续从”生“开始往右的5个依次递减,出现”生动“。但是发现最后的三个字都无法组成词语,所以单独截取出来。这样正向最大法划分后形成的字段是:我们/在野/生动/物/园/玩。
【逆向最大匹配法】:与正向相反,逆向是从右到左依次减少字数进行词语的划分。最后形成的字段是:我们/在/野生动物园/玩。
【双向匹配法】:我们可以看到无论是正向还是逆向,都不能够很精准进行词语划分。所以为了达到更高的精准度,有人提出了双向匹配法。即两种算法都要进行一遍,最后输出大颗粒词多且单字词少的结果。所以对比以上输出的两个字段,逆向最大匹配法的词数量少,大颗粒词更多,单字的单词少。最终应该输出的是逆向最大匹配法的结果。
·在编写中文分词代码时我们会先导入词典:
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 = 5
·正向最大匹配法:
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)
# 正反向分词结果
", forward) :
", 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
除了以上介绍的常见中文分词方法——机械分词法,近几年逐渐诞生出了更加智能化、准确化的中文分词方法。让机器不再用这种机械的方式去拆分语句。而是通过对语义的理解去进行更精准的划分。应用的领域也越来越广泛,例如:机器翻译(MT)、语音合成、自动分类、自动摘要、自动校对等。
但是作为自然语言处理中的重要环节,中文分词还面临着很多挑战。比如:热词、流行词不断出现给机器学习造成了很大的困难。汉字的不同搭配容易造成歧义,导致多种划分标准。我国专门研究中文分词的机构也很少,大部分都集中在科研院校当中。
所以中文分词面临着许多机遇和挑战,追求效率和准确率是中文分词未来的发展目标。要想让中文分词更好应用服务于其他领域,就需要先对其深刻研究,将机器人性化。