最近因为相关项目需要考虑中文文本检错,然后就发现了爱奇艺发布的号称SOTA的FASPell已经开源代码,所以开始着手实现。

检错思想两步:一,掩码语言模型(MLM)产生候选字符;二,CSD过滤候选字符。

资源与数据文件

  开源代码中不包含任何处理好的数据,全部需要自己处理。训练和测试使用的SIGHAN数据没有问题。但是所需的char_meta.txt文件构建较为困难,其由字音和字形两部分特征构成。字音在unihan database可以检索到,但字形特征依照论文阐述是使用汉字的完整带结构笔画级分解,但其提供的kanji database中的结构信息有限,对于简单结构的汉字未做分解,也没有结构信息。虽然github中作者回应可以分解汉字为文件中出现过的字,递归直到无法分解,然后使用cjklib库对递归无法分解的汉字获取其笔画顺序。但这样虽然可以拆分笔画,但是缺少了笔画间的结构。我按照该方法制作了一个带部分结构的笔画级分解文件。

U+4EAC 京 jing1;ging1;KYENG;KYOU,KEI,KIN;kinh ⿳⿱㇔㇐㇑㇕㇐㇚㇒㇔
U+4EAD 亭 ting2;ting4;CENG;TEI,CHOU,CHIN;đình ⿱⿳⿱㇔㇐㇑㇕㇐㇔㇖⿱㇐㇚
U+4EAE 亮 liang4,liang2;loeng6;LYANG;RYOU;null ⿱⿳⿱㇔㇐㇑㇕㇐㇔㇖㇓㇈

模型训练

  模型训练步骤有三个:预训练掩码语言模型,微调训练掩码语言模型和训练CSD过滤器。在原作者github中讲述较为清楚,因此只简单叙述一下,不再复述细节。

  预训练掩码语言模型选择直接使用预训练好的中文BERT模型。然而,预训练模型进行随机mask的位置和实际的拼写错误位置有较大差异,因此需要使用拼写检错的训练集进行微调。微调完成之后的掩码语言模型就可以针对输入句子的每个位置计算出其置信度较高的topn候选集合判断是否存在拼写错误,再将这些候选送到CSD过滤器中过滤并确定修改的候选字。而对于候选集合的过滤方法,则是将其按照字音相似和字形相似分别评估相似度,将置信度和相似度结合进行过滤,因此,训练CSD过滤器的过程较为繁琐,耗时较长,且需要手动确定过滤线(对结果影响较大)。

  以上三个训练步骤完成之后,CSD过滤器训练会产生置信度-相似度散点图,根据散点图的分布来确定过滤曲线,然后使用一些切线来近似曲线。论文中阐述检测正确且纠正正确的样本通常分布在散点图的右上方,因此可以使用曲线对其进行过滤。训练CSD时我使用了大量的SIGHAN数据,产生的散点图并不如论文中那么完美,为了保证低误判,我仅仅考虑了检测和纠正都正确的case来划分过滤曲线。

实践的一些问题

  除了之前的char_meta.txt的问题之外,测试时还发现了对齐错误问题。

  经过排检,发现对齐问题的原因来自于句子中的数字。分词后,有些数字会被打包在一起作为一个token送到BERT中,因此产生了对齐偏差。虽然代码中考虑到了该问题,但仅仅针对两位数字的情况进行了处理,一旦3个以上数字被分为了一个token,句子必定出现对齐错误问题。因此extension()方法需要修改。

  此外,由于训练数据都是繁体字,进行微调之后模型对繁体字的偏好程度增加,这样训练出来的模型在测试时会出现把某个字更改为其繁体字形式的错误。之后我首先用zhconv将训练数据转为简体字,再进行训练测试结果没问题。但由于有些特殊的字的用法原因,如“着”和“著”,使得句子“...看着...”被改为了“...看著...”。对于这些特例,可以使用特殊过滤器进行过滤。

  我认为FASPell主要面向的还是字形相似(OCR)的错误,也的确优先检测这类错误。如果检测对象错误分布偏向于字音(语音识别、拼音输入)的话,可以仅仅开启字音相似检测,或者调整代码中的字音字形检测顺序和修改字音过滤线进行灵活适应。

相关链接

该项目的论文及github如下。

论文:https://www.aclweb.org/anthology/D19-5522.pdf

github:https://github.com/iqiyi/FASPell

文本检错——中文拼写检查工具FASPell的更多相关文章

  1. 如何写一个拼写检查器-by Peter Norvig

    本文原著:Peter Norvig  中文翻译:徐宥 上个星期, 我的两个朋友 Dean 和 Bill 分别告诉我说他们对 Google 的快速高质量的拼写检查工具感到惊奇. 比如说在搜索的时候键入 ...

  2. python 拼写检查代码(怎样写一个拼写检查器)

    原文:http://norvig.com/spell-correct.html 翻译:http://blog.youxu.info/spell-correct.html 怎样写一个拼写检查器 Pete ...

  3. Emacs中的拼写检查

    无论是在Emacs中写英文日记(diary).Org mode笔记,还是撰写程序的注释和文档,拼写检查都是一项提高工作效率.保证成果品质的必不可缺的工具.拼写检查对于常见的文字处理软件(如Word.L ...

  4. C#静态代码检查工具StyleCode

    C#静态代码检查工具StyleCode -- 初探 最近我们Advent Data Service (ADS) 在项目上需要按照代码规范进行代码的编写工作,以方便将来代码的阅读与维护. 但是人工检查起 ...

  5. 提高VS2010运行速度的技巧+关闭拼写检查

    任务管理器,CPU和内存都不高,为何?原因就是VS2010不停地读硬盘导致的; 写代码2/3的时间都耗在卡上了,太难受了; 研究发现,VS2010如果你装了VC等语言,那么它就会自动装SQL Serv ...

  6. 关闭英文拼写检查,关闭xml验证

    http://blog.sina.com.cn/s/blog_70b623e4010173ce.html eclipse里面的许多设置对于国内开发者日常使用不太适用,反而会成为干扰.既然是完全可配置的 ...

  7. Android 代码检查工具SonarQube

    http://blog.csdn.net/rain_butterfly/article/details/42170601 代码检查工具能帮我们检查一些隐藏的bug,代码检查工具中sonar是比较好的一 ...

  8. 【FLYabroad 】微软内部代码检查工具 (Microsoft Source Analysis for C#)[转]

    SourceAnalysis (StyleCop)的终极目标是让所有人都能写出优雅和一致的代码,因此这些代码具有很高的可读性. 早就听说了微软内部的静态代码检查和代码强制格式美化工具 StyleCop ...

  9. C/C++代码静态检查工具Cppcheck在VS2008开发环境中的安装配置和使用

    Cppcheck is an analysis tool for C/C++code. Unlike C/C++ compilers and many other analysis tools, it ...

随机推荐

  1. 2、node-webkit运行web应用,node-webkit把web应用打包成桌面应用

    下面我通过一个简单的demo来介绍怎么样把一个web应用打包成一个可执行文件(这里只介绍windows环境) 首先新建一个index.html文件,作为我们这个demo的入口页面,我们暂且就把这个页面 ...

  2. leetcode 数组 (python)

    1.题目描述 给定一个范围在  1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间没有出现在数组中的数 ...

  3. VS2012下std::function的BUG解决办法

    VS2012版本下std::function存在问题,链接:https://stackoverflow.com/questions/13096162/stdfunction-not-compiling ...

  4. nohup后台运行

    1.信息输出 nohup java -jar xxxx.jar & 2.信息不输出 nohup java -jar xxxx.jar >/dev/null 2>&1 &am ...

  5. JSP———数据交互【2】

    内置对象application 实现用户之间的数据共享 与session 对象不同的是,所有客户的 application 对象是相同的一个,即所有的客户共享这个内置的 application 对象 ...

  6. FacertGrid()的使用

    查看数据的前五行 tips = sns.load_dataset("tips") tips.head() 引入数据,布置横向画布 g = sns.FacetGrid(tips, c ...

  7. docker安装mysql(Baas)

    Docker安装mysql 5.7版本 //拉取mysql镜像 docker pull mysql:5.7 下载完成后,在本地镜像列表里查到REPOSITORY为mysql,标签为5.7的镜像. do ...

  8. 第十一周总结 继承、this和super的区别和用法、方法的重写和重载

    一.继承 1.子类继承父类,通过一个关键字 extends 2.子类的对象可以调用父类中的(public protected)属性和方法 当作自己的来使用 3.子类可以添加自己独有的属性和方法 4.子 ...

  9. 【C语言--数据结构】线性表链式存储结构

    直接贴代码 头文件 #ifndef __LINKLIST_H__ #define __LINKLIST_H__ typedef void LinkList; typedef struct _tag_L ...

  10. Luogu P1084 [NOIP2012]疫情控制

    题目 首先我们二分一下答案. 然后我们用倍增让军队往上跳,最多先跳到根的子节点. 如果当前军队可以到达根节点,那么记录一下它的编号和它到达根节点后还可以走的时间. 并且我们记录根节点的叶子节点上到根节 ...