中文分词中的匹配方法——机械分词法
中文分词 /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_dictwindow_size = 5
·正向最大匹配法:
def fmm(source, words_dict):len_source = len(source) # 原句长度index = 0words = [] # 分词后句子每个词的列表while index < len_source: # 如果下标未超过句子长度match = Falsefor i in range(window_size, 0, -1):sub_str = source[index: index+i]if sub_str in words_dict:match = Truewords.append(sub_str)index += ibreakif not match:words.append(source[index])index += 1return words
·逆向最大匹配法:
def bmm(source, word_dict):len_source = len(source) # 原句长度index = len_sourcewords = [] # 分词后句子每个词的列表while index > 0:match = Falsefor i in range(window_size, 0, -1):sub_str = source[index-i: index]if sub_str in words_dict:match = Truewords.append(sub_str)index -= ibreakif not match:words.append(source[index-1])index -= 1words.reverse() # 得到的列表倒序return words
·双向匹配法:
在上面的基础上,引入比较取舍的程序:
def bi_mm(source, word_dict):forward = fmm(source, words_dict)backward = bmm(source, words_dict)# 正反向分词结果: ", forward): ", backward)# 单字词个数f_single_word = 0b_single_word = 0# 总词数tot_fmm = len(forward)tot_bmm = len(backward)# 非字典词数oov_fmm = 0oov_bmm = 0# 罚分,罚分值越低越好score_fmm = 0score_bmm = 0# 如果正向和反向结果一样,返回任意一个if forward == backward:return backward# print(backward)else: # 分词结果不同,返回单字数、非字典词、总词数少的那一个for each in forward:if len(each) == 1:f_single_word += 1for each in backward:if len(each) == 1:b_single_word += 1for each in forward:if each not in words_dict:oov_fmm += 1for each in backward:if each not in backward:oov_bmm += 1# 可以根据实际情况调整惩罚分值# 这里都罚分都为1分# 非字典词越少越好if oov_fmm > oov_bmm:score_bmm += 1elif oov_fmm < oov_bmm:score_fmm += 1# 总词数越少越好if tot_fmm > tot_bmm:score_bmm += 1elif tot_fmm < tot_bmm:score_fmm += 1# 单字词越少越好if f_single_word > b_single_word:score_bmm += 1elif f_single_word < b_single_word:score_fmm += 1# 返回罚分少的那个if score_fmm < score_bmm:return forwardelse:return backward
除了以上介绍的常见中文分词方法——机械分词法,近几年逐渐诞生出了更加智能化、准确化的中文分词方法。让机器不再用这种机械的方式去拆分语句。而是通过对语义的理解去进行更精准的划分。应用的领域也越来越广泛,例如:机器翻译(MT)、语音合成、自动分类、自动摘要、自动校对等。
但是作为自然语言处理中的重要环节,中文分词还面临着很多挑战。比如:热词、流行词不断出现给机器学习造成了很大的困难。汉字的不同搭配容易造成歧义,导致多种划分标准。我国专门研究中文分词的机构也很少,大部分都集中在科研院校当中。
所以中文分词面临着许多机遇和挑战,追求效率和准确率是中文分词未来的发展目标。要想让中文分词更好应用服务于其他领域,就需要先对其深刻研究,将机器人性化。
