首页 > 编程学习 > 文本纠错--N-gram--Macbert模型的调用以及对返回结果的处理

文本根据词典进行纠错

输入一段可能带有错误信息的文字, 通过词典来检测其中可能错误的词。
例如:有句子如下:中央人民政府驻澳门特别行政区联络办公室1日在机关大楼设灵堂
   有词典如下:中国人民,中央人民,澳门,西门
   检测时,根据词典可以得出句子中的中央人民可能为中国人民,澳门可能为西门,并返回结果

处理逻辑如下:

  • 首先对词典进行逐字打码,例如中国人民处理成:*国人民,中*人民,中国*民,中国人*,并返回一个index_list记录对应的位置和打码的位置(后面才可以根据这个index_list找到候选词)。
  • 接着对句子进行N-gram,比如检测第二个字时,设置n为4(一般都处理为4),处理成:中央,中央人,中央人民,央人,央人民,央人民政,并对央打码,处理成:中*,中*人,中*人民,*人,*人民,*人民政
  • 最后与上述处理完的词典进行对比,如果找到相同的比如:词典里面的 中*人民 与 检测时返回的N-gram里面的 中*人民相同,便根据index_list找到词典中的中国人民,由此可得,字的候选词为。如下:{‘correction’: ‘国’, ‘index’: 1, ‘candidate’: [‘中国人民’], ‘original’: ‘央’}

实现代码如下:

  • 对词典进行处理:
def get_new_dict(dict):'''将词典逐字打码:param dict::return: 新词典以及对应的index'''new_dict = []index_list = []for j in range(len(dict)):for i in range(len(dict[j])):if i < len(dict[j]):new_dic = dict[j][:i] + '*' + dict[j][i+1:]else:new_dic = dict[j][:i] + '*'new_dict.append(new_dic)index_list.append((j,i))return new_dict,index_list
#测试:
dicts = ['中国人民','中央人民','澳门','西门']
new_dict,index_list = get_new_dict(dicts)
print(new_dict)
print("**********************")
print(index_list)

输出:

index_list的元组第一个值表示词典的索引位置,第二个值表示对应这个词打码位置的索引

在这里插入图片描述

  • 对句子进行N-gram
def get_ngram(content,loc,n):'''切分Ngram.函数为根据索引位置切分,如果想切分整个content,只需要加一个循环使loc从0到len(conten)-1:param content: 原文:param loc: 想要检测的字的索引位置:param n: 切分长度:return: ngram'''i_min = loc-n+1 if loc-n+1 >= 0 else 0i_max = loc+1j_min = loc+1j_max = loc+1+n if loc+1+n < len(content) else loc+1+1ngram_list = []for i in range(i_min,i_max):for j in range(j_min,j_max):if j-i > 4 or j - i < 2:continuengram_list.append(content[i:j].replace(content[loc],'*'))return ngram_list
#测试
content = '中央人民政府驻澳门特别行政区联络办公室1日在机关大楼设灵堂'
loc = 1
ngram_list = get_ngram(content,loc,n=4)
print(ngram_list)

输出:
在这里插入图片描述

  • 最后进行词典与N-gram的比对并返回相应结果:
def get_result(ngram_list,new_dict,index_list,loc,original,dicts):'''获取结果:param ngram_list: 原文分割后的Ngram:param new_dict: 打码处理后的字典:param index_list: 处理后的字典对应的索引位置:param loc: 检测字的索引位置:param original: 检测的字:param dicts: 原始词典:return:'''candidate = []error_dic = {}for word in ngram_list:if word in new_dict:indexs = [i for (i, v) in enumerate(new_dict) if v == word]for index in indexs:index = index_list[index]correction = dicts[index[0]][index[1]]if original == correction:continuecandidate.append(dicts[index[0]])error_dic['correction'] = correctionerror_dic['index'] = locerror_dic['candidate'] = candidateerror_dic['original'] = originalreturn error_dic
#测试
original = content[loc]
error_dic = get_result(ngram_list,new_dict,index_list,loc,original,dicts)
print(error_dic)

输出:

{‘correction’: ‘国’, ‘index’: 1, ‘candidate’: [‘中国人民’], ‘original’: ‘央’}

完整代码如下:

def get_ngram(content,loc,n):'''切分Ngram.函数为根据索引位置切分,如果想切分整个content,只需要加一个循环使loc从0到len(conten)-1:param content: 原文:param loc: 想要检测的字的索引位置:param n: 切分长度:return: ngram'''i_min = loc-n+1 if loc-n+1 >= 0 else 0i_max = loc+1j_min = loc+1j_max = loc+1+n if loc+1+n < len(content) else loc+1+1ngram_list = []for i in range(i_min,i_max):for j in range(j_min,j_max):if j-i > 4 or j - i < 2:continuengram_list.append(content[i:j].replace(content[loc],'*'))return ngram_listdef get_new_dict(dict):'''将词典逐字打码:param dict::return: 新词典以及对应的index'''new_dict = []index_list = []for j in range(len(dict)):for i in range(len(dict[j])):if i < len(dict[j]):new_dic = dict[j][:i] + '*' + dict[j][i+1:]else:new_dic = dict[j][:i] + '*'new_dict.append(new_dic)index_list.append((j,i))return new_dict,index_listdef get_result(ngram_list,new_dict,index_list,loc,original,dicts):'''获取结果:param ngram_list: 原文分割后的Ngram:param new_dict: 打码处理后的字典:param index_list: 处理后的字典对应的索引位置:param loc: 检测字的索引位置:param original: 检测的字:param dicts: 原始词典:return:'''candidate = []error_dic = {}for word in ngram_list:if word in new_dict:indexs = [i for (i, v) in enumerate(new_dict) if v == word]for index in indexs:index = index_list[index]correction = dicts[index[0]][index[1]]if original == correction:continuecandidate.append(dicts[index[0]])error_dic['correction'] = correctionerror_dic['index'] = locerror_dic['candidate'] = candidateerror_dic['original'] = originalreturn error_dic
#测试#测试
dicts = ['中国人民','中央人民','澳门','西门']
content = '中央人民政府驻澳门特别行政区联络办公室1日在机关大楼设灵堂'
loc = 7
original = content[loc]
ngram_list = get_ngram(content,loc,n=4)
new_dict,index_list = get_new_dict(dicts)
error_dic = get_result(ngram_list,new_dict,index_list,loc,original,dicts)
print(error_dic)
'''
输出:
{'correction': '西', 'index': 7, 'candidate': ['西门'], 'original': '澳'}
'''

Macbert是什么?

原始 BERT 模型的缺点之一是预训练和微调阶段任务不一致,pretrain 有 [mask] 字符,而 finetune 没有。
MacBERT 用目标单词的相似单词,替代被 mask 的字符,减轻了预训练和微调阶段之间的差距。
输入一句话,给其中的字打上“mask”标记,来预测“mask”标记的地方原本是哪个字。

input: 欲把西[mask]比西子,淡[mask]浓抹总相宜
output: 欲把西[湖]比西子,淡[妆]浓抹总相宜

通过tensorformers使用macbert:


本文链接:https://www.ngui.cc/article/show-747351.html
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000