这一段时间再研究身份证和面单识别项目,总发现一些识别准确率问题,在想办法提高识别率,突然看了一篇文字纠错方面资料,可以发现与ocr结合。开始收集纠错方面的框架,感觉网上评价pycorrector 这个项目不错。
pycorrector
中文文本纠错工具。音似、形似错字(或变体字)纠正,可用于中文拼音、笔画输入法的错误纠正。python3.6开发。
pycorrector依据语言模型检测错别字位置,通过拼音音似特征、笔画五笔编辑距离特征及语言模型困惑度特征纠正错别字。
https://www.borntowin.cn/product/corrector
中文文本纠错任务,常见错误类型包括:
当然,针对不同业务场景,这些问题并不一定全部存在,比如输入法中需要处理前四种,搜索引擎需要处理所有类型,语音识别后文本纠错只需要处理前两种, 其中'形似字错误'主要针对五笔或者笔画手写输入等。
git clone https://github.com/shibing624/pycorrector.git
cd pycorrector
python setup.py install
通过以上两种方法的任何一种完成安装都可以。如果不想安装,可以下载github源码包,安装下面依赖再使用。
安装依赖
pip install https://github.com/kpu/kenlm/archive/master.zip
pip install -r requirements.txt
import pycorrector
corrected_sent, detail = pycorrector.correct('少先队员因该为老人让坐')
print(corrected_sent, detail)
output:
少先队员应该为老人让座 [[('因该', '应该', 4, 6)], [('坐', '座', 10, 11)]]
规则方法默认会从路径
~/.pycorrector/datasets/zh_giga.no_cna_cmn.prune01244.klm
加载kenlm语言模型文件,如果检测没有该文件,则程序会自动联网下载。当然也可以手动下载模型文件(2.8G)并放置于该位置。
import pycorrector
idx_errors = pycorrector.detect('少先队员因该为老人让坐')
print(idx_errors)
output:
[['因该', 4, 6, 'word'], ['坐', 10, 11, 'char']]
返回类型是
list
,[error_word, begin_pos, end_pos, error_type]
,pos
索引位置以0开始。
import pycorrector
error_sentence_1 = '我的喉咙发炎了要买点阿莫细林吃'
correct_sent = pycorrector.correct(error_sentence_1)
print(correct_sent)
output:
'我的喉咙发炎了要买点阿莫西林吉', [['细林', '西林', 12, 14], ['吃', '吉', 14, 15]]
上例中吃
发生误纠,如下代码关闭字粒度纠错:
import pycorrector
error_sentence_1 = '我的喉咙发炎了要买点阿莫细林吃'
pycorrector.enable_char_error(enable=False)
correct_sent = pycorrector.correct(error_sentence_1)
print(correct_sent)
output:
'我的喉咙发炎了要买点阿莫西林吃', [['细林', '西林', 12, 14]]
默认字粒度、词粒度的纠错都打开,一般情况下单字错误发生较少,而且字粒度纠错准确率较低。关闭字粒度纠错,这样可以提高纠错准确率,提高纠错速度。
默认
enable_char_error
方法的enable
参数为True
,即打开错字纠正,这种方式可以召回字粒度错误,但是整体准确率会低;
如果追求准确率而不追求召回率的话,建议将
enable
设为False
,仅使用错词纠正。
通过加载自定义混淆集,支持用户纠正已知的错误,包括两方面功能:1)错误补召回;2)误杀加白。
import pycorrector
pycorrector.set_log_level('INFO')
error_sentences = [
'买iPhone差,要多少钱',
'共同实际控制人萧华、霍荣铨、张旗康',
]
for line in error_sentences:
print(pycorrector.correct(line))
print('*' * 53)
pycorrector.set_custom_confusion_dict(path='./my_custom_confusion.txt')
for line in error_sentences:
print(pycorrector.correct(line))
output:
('买iPhone差,要多少钱', []) # "iPhone差"漏召,应该是"iphoneX"
('共同实际控制人萧华、霍荣铨、张启康', [['张旗康', '张启康', 14, 17]]) # "张启康"误杀,应该不用纠
*****************************************************
('买iPhoneX,要多少钱', [['iPhone差', 'iPhoneX', 1, 8]])
('共同实际控制人萧华、霍荣铨、张旗康', [])
具体demo见example/use_custom_confusion.py,其中./my_custom_confusion.txt
的内容格式如下,以空格间隔:
iPhone差 iPhoneX 100
张旗康 张旗康
set_custom_confusion_dict
方法的path
参数为用户自定义混淆集文件路径。
默认提供下载并使用的kenlm语言模型zh_giga.no_cna_cmn.prune01244.klm
文件是2.8G,内存较小的电脑使用pycorrector
程序可能会吃力些。
支持用户加载自己训练的kenlm语言模型,或使用2014版人民日报数据训练的模型,模型小(20M),准确率低些。
from pycorrector import Corrector
pwd_path = os.path.abspath(os.path.dirname(__file__))
lm_path = os.path.join(pwd_path, './people_chars_lm.klm')
model = Corrector(language_model_path=lm_path)
corrected_sent, detail = model.correct('少先队员因该为老人让坐')
print(corrected_sent, detail)
output:
少先队员应该为老人让座 [[('因该', '应该', 4, 6)], [('坐', '座', 10, 11)]]
具体demo见example/load_custom_language_model.py,其中./people_chars_lm.klm
是自定义语言模型文件。
支持英文单词的拼写错误纠正。
import pycorrector
sent_lst = ['what', 'hapenning', 'how', 'to', 'speling', 'it', 'you', 'can', 'gorrect', 'it']
for i in sent_lst:
print(i, '=>', pycorrector.en_correct(i))
output:
what => what
hapenning => happening
how => how
to => to
speling => spelling
it => it
you => you
can => can
gorrect => correct
it => it
支持中文繁体到简体的转换,和简体到繁体的转换。
import pycorrector
traditional_sentence = '憂郁的臺灣烏龜'
simplified_sentence = pycorrector.traditional2simplified(traditional_sentence)
print(traditional_sentence, '=>', simplified_sentence)
simplified_sentence = '忧郁的台湾乌龟'
traditional_sentence = pycorrector.simplified2traditional(simplified_sentence)
print(simplified_sentence, '=>', traditional_sentence)
output:
憂郁的臺灣烏龜 => 忧郁的台湾乌龟
忧郁的台湾乌龟 => 憂郁的臺灣烏龜
支持批量文本纠错。
python -m pycorrector -h
usage: __main__.py [-h] -o OUTPUT [-n] [-d] input
@description:
positional arguments:
input the input file path, file encode need utf-8.
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
the output file path.
-n, --no_char disable char detect mode.
-d, --detail print detail info
case:
python -m pycorrector input.txt -o out.txt -n -d
输入文件:
input.txt
;输出文件:out.txt
;关闭字粒度纠错;打印详细纠错信息;纠错结果以\t
间隔
提供评估脚本pycorrector/utils/eval.py,该脚本有两个功能:
执行该脚本后得到,规则方法纠错效果评估如下:
看来还有比较大的提升空间,误杀和漏召回的都有。
pip install -r requirements-dev.txt
本项目的初衷之一是比对、共享各种文本纠错方法,抛砖引玉的作用,如果对大家在文本纠错任务上有一点小小的启发就是我莫大的荣幸了。
主要使用了多种深度模型应用于文本纠错任务,分别是前面模型
小节介绍的conv_seq2seq
、seq2seq_attention
、 transformer
、bert
、electra
,各模型方法内置于pycorrector
文件夹下,有README.md
详细指导,各模型可独立运行,相互之间无依赖。
各模型均可独立的预处理数据、训练、预测,下面以其中seq2seq_attention
为例:
seq2seq_attention 模型使用示例:
配置
通过修改config.py
。
数据预处理
cd seq2seq_attention
# 数据预处理
python preprocess.py
自动新建文件夹output,在output下生成train.txt
和test.txt
文件,以TAB("\t")间隔错误文本和纠正文本,文本以空格切分词,文件内容示例:
希 望 少 吸 烟 。 希 望 烟 民 们 少 吸 烟 。
以 前 , 包 括 中 国 , 我 国 也 是 。 以 前 , 不 仅 中 国 , 我 国 也 是 。
我 现 在 好 得 多 了 。 我 现 在 好 多 了 。
训练
python train.py
训练过程截图:
预测
python infer.py
预测输出效果样例:
input: 少先队员因该给老人让坐 output: 少先队员因该给老人让座
input: 少先队员应该给老人让坐 output: 少先队员应该给老人让座
input: 没有解决这个问题, output: 没有解决这个问题,,
input: 由我起开始做。 output: 由我起开始做
input: 由我起开始做 output: 由我开始做
PS:
语言模型对于纠错步骤至关重要,当前默认使用的是从千兆中文文本训练的中文语言模型zh_giga.no_cna_cmn.prune01244.klm(2.8G)。
大家可以用中文维基(繁体转简体,pycorrector.utils.text_utils下有此功能)等语料数据训练通用的语言模型,或者也可以用专业领域语料训练更专用的语言模型。更适用的语言模型,对于纠错效果会有比较好的提升。
人民日报2014版熟语料,网盘链接:https://pan.baidu.com/s/1971a5XLQsIpL0zL0zxuK2A 密码:uc11。尊重版权,传播请注明出处。
微信交流群,感兴趣的同学可以加入沟通NLP文本纠错相关技术,issues上回复不及时也可以在群里面提问。
PS: 由于微信群满100人了,扫码加不了。扫我微信二维码,或者搜索我微信号:xuming624, 备注:个人名称-NLP纠错 进群。
如果你在研究中使用了pycorrector,请按如下格式引用:
@software{pycorrector,
author = {Xu Ming},
title = {{pycorrector: Text Correction Tool}},
year = {2020},
url = {https://github.com/shibing624/pycorrector},
}
pycorrector 的授权协议为 Apache License 2.0,可免费用做商业用途。请在产品说明中附加pycorrector的链接和授权协议。pycorrector受版权法保护,侵权必究。
Chinese text error correction tool.
pycorrector Use the language model to detect errors, pinyin feature and shape feature to correct chinese text error, it can be used for Chinese Pinyin and stroke input method.
input:
import pycorrector
corrected_sent, detail = pycorrector.correct('少先队员因该为老人让坐')
print(corrected_sent, detail)
output:
少先队员应该为老人让座 [[('因该', '应该', 4, 6)], [('坐', '座', 10, 11)]]
P(c), the language model. We could create a better language model by collecting more data, and perhaps by using a little English morphology (such as adding "ility" or "able" to the end of a word).
P(w|c), the error model. So far, the error model has been trivial: the smaller the edit distance, the smaller the error. Clearly we could use a better model of the cost of edits. get a corpus of spelling errors, and count how likely it is to make each insertion, deletion, or alteration, given the surrounding characters.
It turns out that in many cases it is difficult to make a decision based only on a single word. This is most obvious when there is a word that appears in the dictionary, but the test set says it should be corrected to another word anyway: correction('where') => 'where' (123); expected 'were' (452) We can't possibly know that correction('where') should be 'were' in at least one case, but should remain 'where' in other cases. But if the query had been correction('They where going') then it seems likely that "where" should be corrected to "were".
Finally, we could improve the implementation by making it much faster, without changing the results. We could re-implement in a compiled language rather than an interpreted one. We could cache the results of computations so that we don't have to repeat them multiple times. One word of advice: before attempting any speed optimizations, profile carefully to see where the time is actually going.