文本纠错 N-gram 修改提示

版权声明:我是南七小僧,微信: to_my_love ,欢迎交流思想碰撞。 https://blog.csdn.net/qq_25439417/article/details/83111345

有幸参加研究生师兄的创新创业项目,一个和金融企业合作的对话文本分析与挖掘的项目。项目组从公司处获得语音识别后的客服对话文本,我们对文本进行纠错、情感分析与挖掘等并最终给公司反馈,让公司能够从客服对话文本中获得有效信息。我在项目中参与的部分是文本处理的第一步:文本检错纠错。这几个月中,在研究生师兄的带领下,我们基于机器学习构建了数个用于语音识别后文本的检错纠错模型,在此将主要的两个方法:n-gram+拼音相似度+词语搭配, 双向LSTM模型的整个构建过程进行总结。

本文介绍了我们采用的第一个方法:n-gram+拼音相似度+词语搭配。

整体分为四个部分:

  1. 错误文本分析,语料获取、处理与利用
  2. 错误检测
  3. 错误纠正
  4. 模型评估

Part 0 : 前置理论简述

n-gram

n-gram的思路非常简单易懂,即假设一个字或词出现仅与前n个词相关(n为人为给定),句子整体的概率等于所有词语搭配概率的乘积。常用的有2-gram(bi-gram)和3-gram(Tri-gram),词语概率的计算方法用到了概率论中的条件概率,此外用频数计算计算频率代替概率。人们通常用n-gram来评估一个句子是否合理。在这里,我们通过计算一个词语的n-gram分数来评估这个词语是否合理,以此检测错误词语。

依存句法

依存句法通过分析词语间的依存关系揭示句子的结构,它可以识别出句子中的主谓宾、定状补等语法成分并分析各个成分之间的关系。除了能够解析句子并划分结构之外,它还能够找到句子的核心词并且分析词语之间的语义距离。

编辑距离与最长公共子串(LCS)

编辑距离和LCS通常用于字符串的相似度匹配。

LCS的思想很简单,就是两个字符串共有的子串的最大长度。

编辑距离稍微复杂一点,编辑的方式分为三种:修改一个字符、增加一个字符、删去一个字符,第一个字符串通过应用以上三种编辑方式变成第二个字符串,所需要的最少的编辑次数(不限种类)称为编辑距离。

Part 1 : 错误文本分析,语料获取、处理与利用

语料利用

得到待测语料后,我们首先对文本进行观察,并结合这是语音识别后的前提,分析得到一下结果:

错误类型

我们通过对待测语料的观察发现,对话文本中的错误除了包括常用词语的错误外,还包括金融方面的错误。并且由于是语音识别后的文本,错误主要与拼音有关。

错误类型主要包括以下两大方面:

  1. 拼音相关:
  2. 错音
  3. 缺音
  4. 多音
  5. 拼音正确但词识别错误
  6. 说话者相关:
  7. 反复:因为对话发生在打电话中,而说话者在想要尽力表达自己的意思时常常会将某个词或某个短句重复数次。
  8. 倒装:与说话人的习惯以及对话情况有关。

错误原因分析

在观察得到有哪些错误之后,我们开始着手对错误背后的原因进行分析并试图给出解决方案。

语音识别方面:

​ 由于语音识别是使用较为通用的工具,而客服对话涉及到很多金融方面的名词尤其是该企业的特定产品,因此在名词方面容易发生拼音正确但词识别错误的情况。这类错误既然集中于名词,那么我们通过构建专有名词库再通过拼音相似度进行识别即可。

说话者方面:

​ 考虑到这是电话咨询中的对话,客服人员方面由于经过专门的筛选和训练,因此普通话较为标准且吐字清晰,说话音量合理且很少有外部噪音。而咨询者没有限定,其口音、音量等方面会对识别造成较大影响。

​ 此外,说话者的知识背景及成长环境会对其陈述的句子的语法结构有影响,可能会更倾向于使用倒装句。

​ 第三,说话过程中咨询者一方可能会有额外噪音或突发事件,这些噪音起码会导致语句无法被识别,还可能导致误识别,在文本中增加一些无用词。

​ 这方面的错误是识别错误的主体部分,我们打算采用的是基于统计的n-gram模型结合拼音的方案,通过n-gram找到说话者可能原本想说的词语,因为这是语音识别后的文本,因此在n-gram识别后再通过拼音相似度来纠正的正确率会很高。

语言方面:

​ 中文本身就极为复杂,多义性的句子比比皆是,拼音类似在不同的应用场景之下词语也不同,这类语义上的错误很难通过统计解决,如本文采用的n-gram模型,若要捕获长距离的句子依赖关系来对句子进行诊断,则需要构建不止2-gram、3-gram,那么模型对时间空间的消耗较大。而另一篇文章采用的双向LSTM则在这个问题的解决上会优于n-gram基于统计的方式。

训练语料获取

  1. 从网络上获取的搜狗通用新闻语料(数GB级)
  2. 网络获取的金融新闻语料(数百MB级)
  3. 人工从待测的句子中检测并纠正少部分句子(数MB级)

模型选择

在经过对错误类型和错误原因经过分析之后,我们打算初步使用n-gram模型进行低级错误识别。考虑到错误除了涉及通用领域外还有金融领域,以及该企业特有名词,那构造n-gram模型就得同时考虑到这几个方面,构造一个通用的n-gram以及一个专业领域的n-gram。

对于n的选择,考虑到对话主要是短文本,并且短句之间的联系并不大,因此我们将每个长句子都剪成短句子并以短句子为单位进行错误检测,因此构建2-gram与3-gram模型足够解决需要。

最终我们敲定的n-gram模型如下:

  1. 由通用语料训练的模型,分为2-gram和3-gram,用来识别通常对话中的错误。
  2. 由金融新闻以及人工纠正过的待测句子训练的专业模型,同样分为2-gram和3-gram,用于识别金融领域乃至该公司领域的错误。

预处理

在了解了目标和解决方向之后,就要实际开始处理语料了。

数据处理要点:

  1. 重新分词(语料和待纠句子)
  2. 数字变星号
  3. 长句剪断(全角转半角),根据逗号、句号、问号、感叹号裁剪句子

首先我要从项目的服务器上获取待纠错的文本数据,师兄先前已经做过一些工作,首先在java利用JDBC访问数据库,得到每份对话的id、分完词的对话。训练的通用语料以及专业语料则直接从服务器上下载。

之后对待测语料和训练语料统一进行处理,由于训练语料未经过分词,而待测语料的分词工具未知,分词又对检测的结果有很大的影响,因此我对待测文本重新用和训练语料一样的工具进行分词。

接下来我们将目光转向文本中的数字。文本中包含各种数字,但我们知道,它们虽然各异,但在不考虑数值差异的情况下基本相近,且前后可以连接的词也差不多。比如年月日,在给定格式的前提下里面只要是合理的数字即可,而在检错中我们并不需要考虑数字的合理性,因此对于待测语料和训练语料,我们统一将数字变成星号以去除不同数字相同模式的影响。去除方式也很简单粗暴,用正则表达式匹配替换即可。

再之后就是句子裁剪了。如上文所提,我们用n-gram捕获低级的句子错误,并且对话中句子关联度并不如文章句子那般大,而对话长距离的语义错误n-gram本身就无法捕获,因此我们直接根据逗号、句号、问号等明显分割句子的标点符号进行句子切分,将长句子划分成数个短句子,而后以短句子为单位检测错误。

模型构建

在对语料处理完之后,接下来进行n-gram模型的构建。在模型构建方面,我们利用berkeley提供的自然语言处理工具包 来生成n-gram模型,平滑(Smoothing)方面选用了工具包内置的较为优秀的平滑方法Kneser-Ney。

工具包会将导入的分好词的txt文件生成成.arpa模型文件保存下来,以后要用到计算好的模型时直接读取arpa模型文件而后将待检测的句子分好词逐几个喂进去检测概率即可。

在得到模型之后我自然要试试产生什么结果以及效果如何,在给出一个样例之后得到如下结果:

image

其中-100是给模型的设置参数,当在ngram中找不到类似的匹配对时会输出-100.

看到这结果有些让人疑惑,n-gram出来的不应该是概率吗?虽然在大规模语料中某个特定对的概率很低,但也应该分布在0和1之间呐,这负数又是怎么回事?在经过查阅和总结之后,我知道它采用的是log之后的概率,原因如下:

  1. n-gram的原理:一系列小于1的概率的乘积,当它们相乘之后可能会变得非常小以至于float无法放下,而使用了log之后将乘积放大。
  2. 便于求导和公式推导,套上log之后将概率的乘法变成了log的加法。
  3. 不改变大小关系,原本概率越大的句子在使用log之后的数值是负数,但更靠近0,原本的大小顺序没有被破坏。

由此,模型构建完成,接下来就要将文本导入模型进行错误检测了。

Part 2 : 错误检测

错误检测

模型的使用很简单,将待检测句子进行分词(在项目中我们的待测句子已经分好了词),而后扫描一遍句子获取词语对列表,对于2-gram则是从第二个词开始每个词语及其前面的词。如“ 系统 提示 查询 密码 不 正确”,那么2-gram的词语对列表就是: [系统,提示]、[提示,查询]、[查询,密码]、[密码,不]、[不,正确]。同理得到3-gram的词语对列表。

将词语对列表分别导入两个n-gram模型,得到两个模型的2-gram和3-gram分数,总共四个分数,若四个分数均低于某个阈值,则认为该词出错。阈值为人工选定的数字,在我们的项目中选定的阈值为-5.5。

在扫描过后,我们得到模型认为出错了的词语,为了在网页上进行标红以及之后的纠正处理,我们要将结果保存为JSON文件,文件以 中括号[] 嵌套的形式 记录每个大句子的id,大句子分割成的小句子的错误词语索引及词语本身,以及词语的2-gram,3-gram分数。

Part 3 : 错误纠正

错误纠正

在获得错误词语之后,接下来就要根据词语搭配和拼音相似度来纠正词语了。

首先要获取词语搭配,师兄已经通过依存句法在语料中提取了词语搭配,然而提取之后的顺序是乱序。这时候之前训练的2-gram就派上用场了,将词语搭配的两个顺序导入两个2-gram中,最后选择分数较高的作为词语顺序保存下来。

将词语搭配文件导入哈希表中,每个前驱词都对应一个备选词集,词集中的词是通常接在前驱词后面的词。

获得词语搭配之后,接下来就要获取拼音并计算相似度了。纠正步骤如下:

  1. 首先,通过hanlp获取待纠正词语以及词语搭配表的拼音
  2. 根据待检测语料以及错误词语的索引获取错误词语的前一个词,查询搭配表得到备选词集
  3. 将错误词语的拼音和备选词集每个词的拼音求 编辑距离和LCS 的加权分数,取超过阈值的前几个词语进行观察
  4. 将备选词替换疑似错误词并代回n-gram模型中进行分数比较,取分数高者保存。

分数的算法方面,第一想法是直接最长公共子串的匹配,但是在错误识别中有很多错音、多音、少音的例子,因为一个拼音而导致公共子串断裂,由此额外考虑编辑距离,两个算法都是用动态规划自行实现的。

选定算法之后,我们还需要结合两个算法的结果。

​ 对于最长公共子串,最终的结果是两个字符串最长公共子串的长度,越大则两个字符串匹配程度越高。考虑到越长的字符串最后的公共子串更可能越长,这对短字符串不公平,因此我将最终的最长子串长度除以第一个字符串(错误词语的拼音)的长度进行归一化。

​ 对于编辑距离,最终的分数是第一个字符串需要改动多少才能变到第二个字符串,越小说明两个字符串匹配程度越高。我将最终分数取倒数,考虑到分数可能是0(两个字符串完全相同),则先在最终结果上+1而后再取倒数,这样同样对编辑距离进行归一化并且匹配程度越高,分数越高。

​ 两个算法的分数结合方面,虽然两个算法有些相似但仍有不同点,我们更倾向于选择最长公共子串分数更高的,但是同样得考虑编辑距离,在经过观察与实验后选定最终分数为 0.5*编辑距离 + 0.8*LCS。这样,两个字符串在匹配的时候,既能以公共子串为主,又能考虑到少部分拼音出错的因素。

Part 4 : 模型简单评估

在构建模型之后,我们还对模型检测错误的效果进行一个简单的评估。评估从待测语料中挑选50条句子,每句扩成几个只有一处错误的句子,句子不涉及语义错误,和完全正确的句子放在一起给模型进行测试,共176个测试样本。

50条完全正确的句子,126个只含一处词语错误的句子,若模型给出的所有分数均低于阈值则模型认为这个句子完全完全正确。

最终结果如图:

image

TP :模型判断正确:模型认为句子中有错误并且正确指出错误词语

TN :模型判断正确:模型认为句子没错误,句子本身完全正确

FP :模型判断出错:模型认为句子有错误但其判断出错,分为两种情况:

  1. 句子本身完全正确,但模型认为有错
  2. 句子本身有错,但模型认为错误的词语与句子的错误词语不匹配

FN :模型判断出错:模型认为句子无错误,句子包含错误

总结

不足

n-gram模型在检测低级错误上表现良好,准确率颇高,但这个方案仍有不足之处。

1. 训练语料:

我们采用的搜狗通用语料是从新闻网页上爬取的结果,包含很多噪声文本,若要进行处理则需要花费较多额外功夫。

金融新闻方面亦如此,此外还有些问题。虽然语料有金融方面的知识,但和对话相比过于正式,对话通常使用口语化表述,和正式的新闻文本的匹配程度并不是很高。

除了语料本身的问题之外,在语料规模上也有待加强,n-gram这类基于统计的模型训练数据自然越多越好(噪声少的情况下),照目前结果来看,GB级的通用语料表现还不错,若要再加强一下效果还需要更多更好的训练数据,尤其是在金融方面以及对话方面的文本数据。

我们所要识别的是对话过程中的错误,因此若有大量正确的对话文本用于训练那是再好不过,然而受限于对话文本语料库的规模,我们额外加入的人工纠正的对话文本虽然噪声较少,但样本数过少且费时费力。

2. 模型缺陷

除了训练语料上的缺陷外,模型本身也并不完美。基于统计的模型并不能很好地捕获语义关联,长距离依赖以及上下句关联,若是试图将n扩展到4、5乃至更高,则会产生很多空值,平滑之后的分数大多很难低于阈值。因此,对于语义关联上的错误,我们打算采用双向LSTM检测,这就是后话了。

感悟

经过从目标分析、文本数据分析以及原因诊断,再到选择模型、获取语料,之后进行预处理、构建模型,最后实际使用模型以及评估模型,这么个基本完整的流程走下来之后,我对机器学习在项目中的实际应用有了进一步的理解。此外,在任务进行的过程中有多个小任务,如何又快又好地完成小任务也同样需要考虑,这需要多语言之间的协作,JAVA的快速,Python的易用与多功能,都在完成任务的过程中给予我很大帮助。

项目进行过程中同样也遇到了很多小问题,并且由于经验不足以及不像做题那般有答案可以对,时不时还会走下弯路,但最后还是靠着坚持和努力,比较好地完成了任务。

猜你喜欢

转载自blog.csdn.net/qq_25439417/article/details/83111345
今日推荐