NLP中的数据增强技术

在图像领域,数据增强(data augmentation)是很常见的技术,而NLP领域则不是,主要是因为一个图像你把它旋转一下或者变成灰度图并不会改变原有图像属性,这种语义不变的变换在图像研究领域成为了一项基础操作。而在NLP领域这种语义不变的变换相对来说难找一些。

那么是否有方法开发一个针对NLP领域的数据增强的工具集呢?在这篇文章中将会总结一些NLP领域的数据增强技术。


方法1 词汇替换

这个方法主要思路是不改变语义的情况下替换句子中的一些单词,方法有以下几种:

a. 基于词典的替换(thesaurus-based substitution)

在这种技术里,我们从句子里面随便找一个单词,然后用它的同义词对它进行替换即可,前提是得准备好一个同义词库,比较常用的是wordnet和hownet,它们是人工维护的词关系数据库。

Zhang et al. 曾经在2015年的论文“Character-level Convolutional Networks for Text Classification”使用过这项技术,Mueller et al. 曾经用相似的方法生成了额外的1w条训练集用于句子相似度模型。

NLTK提供了一个简便的方法去使用wordnet,你也可以用Textblob API或者PPDB。

b. 基于word embeddings的替换

这个方法我们使用预训练好的word embeddings作为文本替换的依据,预训练方法可以是Word2vec、GloVe、FastText、Sent2Vec等,然后利用embedding的最近邻去对句子中的词进行替换。Jiao et al. 在论文tinybert里就用了这种技术去增加下游任务的泛化性。Wang et al. 用这种方法去增强tweets去训练一个主题模型。

例如,你可以用3个最相近的词去获取三个句子的变种:

如果使用这种方法的话,用Gensim这个工具就会很方便获取预训练的wordvec的邻近单词。例如我们想获取“awesome”的最邻近的五个单词:

# pip install gensimimport gensim.downloader as api

model = api.load('glove-twitter-25')  
model.most_similar('awesome', topn=5)

它的返回值是这样的:

[('amazing', 0.9687871932983398),
('best', 0.9600659608840942),
('fun', 0.9331520795822144),
('fantastic', 0.9313924312591553),
('perfect', 0.9243415594100952)]

c. Masked语言模型

BERT、ROBERTA、ALBERT等类型的transformer模型已经针对大量文本训练了一个名叫“Masked Language Modeling”的语言模型,它可以预测缺失的词到底是什么。这种方法可以被用来做数据增强,例如,我们可以使用一个预训练的bert模型,然后mask掉一部分文本,之后我们用bert模型去预测那些文本到底是什么:

这样我们就可以获得一些变体。同之前的方法比较起来,它会更符合语言规范,因为它在预测的时候考虑了上下文。

这种方法实现起来也比较简单,直接用开源的Hugging Face即可,你可以用<mask>设置你想替换的词,然后去预测:

from transformers import pipeline
nlp = pipeline('fill-mask')
nlp('This is <mask> cool')
[{'score': 0.515411913394928,
  'sequence': '<s> This is pretty cool</s>',
  'token': 1256},
{'score': 0.1166248694062233,
  'sequence': '<s> This is really cool</s>',
  'token': 269},
{'score': 0.07387523353099823,
  'sequence': '<s> This is super cool</s>',
  'token': 2422},
{'score': 0.04272908344864845,
  'sequence': '<s> This is kinda cool</s>',
  'token': 24282},
{'score': 0.034715913236141205,
  'sequence': '<s> This is very cool</s>',
  'token': 182}]

然而这种方法的缺点在于不太好确定到底mask句子的哪一部分,必须使用一些启发式算法,否则生成的文本跟原来的文本意思可能不一样。

d. 基于TF-IDF的文本替换

这种增强方法是Xie et al.在论文Unsupervised Data Augmentation里提出的,基本思想是有比较低的tf-idf的分值是没什么重要信息的,所以是可以在不影响句子意思的情况下被替换的。

被替换的单词是具有低tf-idf分值的那些词,具体可以参考原始论文实现


方法2 回译

这种方法的主要思想是利用机器翻译去把原始句子翻译成另一种语言,然后在翻译回来。Xie et al. 用这种方法去增强无标签文本,然后用仅仅20个标注样本去学习一个半监督的模型,这种方法比之前的STOA的在2.5w样本上训练的模型性能还要好。

回译方法主要有以下几步:

  1. 找到一些句子(譬如英语)翻译成另一种语言(譬如汉语)

  2. 把汉语再翻译回英语

  3. 检查新的句子是否跟原始句子不同,如果是,那么我们就用新的句子作为增强之后的版本

也可以用回译方法翻译成不同语言来一次获取多个变种,如图,我们把原文一次翻译成法语、汉语、意大利语,然后再翻译回来,就获得了三个样本。

这种技术也同样被用于Kaggle竞赛“Toxic Comment Classification Challenge”的第一名解决方案,他们把这种技术不仅用在训练阶段,也用在预测阶段,他们把最后的多个增强句子的最终结果加权平均作为最终预测输出。

关于回译方法的实现可以用TextBlob,同样也可以使用Google的免费翻译服务。


方法3 正则替换

可以用正则的方式替换句子的某些特征,Claude Coulombe在论文中有描述。

论文中给出了一个例子,如下图所示:

由于变换不应该改变句子意思,所以它有可能会出现模棱两可的局面,如图:

为了解决这个问题,论文的解决方法是禁止歧义变换:

你可以在这里找到一些英文变换。


方法4 随机噪音注入

思路就是对文本注入一些随机噪声使得模型更鲁棒。

a. 拼写错误注入

这种方法就是替换一些字母成随机单词造成拼写错误。

b. 键盘错误注入

这种方法就是模拟人在输入的时候容易造成的错误,错误的主要依据就是键与键之间的距离。

c. unigram噪声

这种方法主要就是针对unigram的出现次数进行替换

d. 空格噪声

这种方法主要思想是将句子中的一些单词变成下划线字符,它可以有效避免过拟合。

e. 打乱顺序

主要就是将句子顺序打乱来获得增强效果。


方法5 实例交叉增强

这种方法是Luque在TASS 2019的论文中提出的,主要思路是将相同label的两个句子分别分成两部分,然后分别交叉它们的前半部分和后半部分,这样即使新句子不再语义通顺,它们依然保持语义极性(positive、negative)。

这种方法对准确率没什么影响但是对F1有正面影响。


方法6 语法树增强

这种方法首先是针对原始句子构建一棵语法树,然后用语法规则去产生新的句子。如下所示:


方法7 文本混合

混合技术是一个比较简单而且成功的图像数据增强技术,主要就是将两幅图通过加权的方式叠加起来:

在NLP领域我们需要对混合技术进行修改,主要有两种方法:

a. wordMixup:

方法将mini-batch的两个随机的句子先进行0padding,然后进行word embedding的逐个相加,后面就是普通的模型,最后在计算loss的时候也是加权的loss。

b. sentMixup:

与wordMixup不同的是它不是在word embedding维度进行相加,而是在最终的向量输出进行相加,然后loss的处理也是跟wordMixup一样。


实现

python的nlpaug库和textattack库实现了上述的方法,它们使用方便,可以很容易集成到现有项目中。


总结

这些数据增强技术很对是任务相关的,针对自己的任务挑选适合任务的数据增强技术还是能对任务产生不少正向收益的。


链接地址: https://amitness.com/2020/05/data-augmentation-for-nlp/

©2020 by EasyCSTech. Special thanks to IPinfo​ and EasyNote.