数据增强方法(Data Augmentation)是一种常用且有效的对训练样本进行预处理的方法,目的是通过对原始训练样本进行轻微的变换、扭曲或者添加噪声来扩充训练集,从而提高模型在实际应用中的泛化能力
作者:禅与计算机程序设计艺术
1.简介
数据增强(Data Augmentation)是一种常用且有效的对训练样本进行预处理的方法。它的目的是通过对原始训练样本进行轻微的变换、扭曲或者添加噪声,来扩充训练集,从而提高模型在实际应用中的泛化能力。
传统的数据增强方法主要基于图像领域,图像增广技术比较成熟,应用也比较广泛,比如卷积神经网络(CNN)中的翻转、裁剪、旋转等数据增强操作。然而对于文本领域来说,这种方法就显得力不从心了。
由于文本数据的复杂性、稀疏性以及相对平坦的分布特征,传统的数据增强方法并不能有效地扩充文本数据。因此,近年来一些研究人员提出了不同的文本增强方法,试图通过改变词、短语或句子的结构、位置信息等方式来增强文本数据,比如BERT和GPT-2使用的掩码语言模型,以及TextAugment库中提供的各种文本数据增强方法。这些方法虽然能够在一定程度上解决文本数据不足的问题,但仍无法完全解决这个问题。
为了进一步丰富文本数据,面临着另一个更加迫切的问题:如何选择最佳的数据增强方案?在某些任务场景下,如情感分析、语言推断、命名实体识别等,某种增强方法可能就会胜过其他方法。但是在其他情况下,比如文本摘要、机器翻译、文本生成等,哪种方法才是最好的呢?在这篇文章中,我将会回顾并总结目前较为主流的文本数据增强方法,并结合相应的理论和实践,给出针对不同任务场景的建议。
2.基本概念和术语
① 数据增强(Data Augmentation):对训练样本进行预处理的方法。
② 局部增强(Local Augmentation):指采用与原样本相似的小范围变化的方式进行数据增强。
③ 全局增强(Global Augmentation):指采用与原样本截然不同的大范围变化的方式进行数据增强。
④ 单词嵌入(Word Embedding):词向量。
⑤ 序列模型(Sequence Modeling):通过学习序列关系进行预测或生成。
⑥ 连续词袋模型(Continuous Bag-of-Words Model, CBOW):CBOW模型的目标是在给定上下文之后预测中心词。
⑦ skip-gram模型(Skip-gram model):skip-gram模型的目标是在给定中心词之后预测上下文。
⑧ 词嵌入(Word embedding):将词映射到实数向量空间的过程。
⑨ 对抗训练(Adversarial Training):是通过生成器和判别器网络间的博弈,使得判别器网络难以区分真实数据和生成数据。
⑩ GAN(Generative Adversarial Network):一种深度学习模型,可以用来生成伪造的样本。
⑪ 蒙特卡洛采样(Monte Carlo Sampling):根据概率分布随机生成样本的方法。
⑫ 概率密度函数(Probability Density Function, PDF):在给定取值时,连续变量的概率密度。
⑬ 类比学习(Analogical Learning):通过相似的数据之间的差异性进行学习。
⑭ 后件语言模型(Posterior Language Modeling):通过已知句子生成新句子。
⑮ 人工代理(Human Proxy):具有专业知识的评估者,如英文撰稿人的专业评论。
⑯ 模拟退火(Simulated Annealing):一种模拟退火算法,用于求解复杂优化问题。
⑰ 向量空间模型(Vector Space Model):描述两个文档或文本之间词汇共现关系的语义模型。
3.核心算法原理及操作步骤
## 3.1 WordEmbadding Word Embadding (WE)
WordEmbadding 是利用词向量的预训练模型获得的词向量对文本进行增强。其基本思路是通过词向量模型学习文本的语义表示,然后利用该表示进行增强。
假设我们有一段文本 A=“The quick brown fox jumps over the lazy dog” ,并且已经获得了一个词向量模型 V,即 W(quick)=q1, W(brown)=b1,…, W(dog)=d1 。那么可以通过以下步骤进行增强:
- 使用 WE 方法生成带噪声的文本 B = "The qu__ck br__wn fx jm___ps ove th_ _lz dy _g",其中“”代表的是被替换的词汇。
- 使用 WE 方法将 A 和 B 通过模型计算得到对应的词向量。
- 将 B 的词向量设置为 A 的词向量。
- 返回增强后的 A 。
从上述步骤可以看出,WE 方法将原有的文本 A 替换为随机噪声文本,再使用词向量模型重新计算对应的词向量,将噪声文本对应的词向量设置成原文本对应的词向量,这样就可以达到数据增强的目的。
当 WE 在中文文本上进行增强时,需要考虑汉字的多音字情况。现有两种方案:一种是替换同义词(同音字),另一种是直接替换汉字。
(1)同义词替换
有一种简单的方法,就是首先将原文本分词,再随机选取一组同义词,使用 “词向量距离最小” 的策略,替换原文本中的对应词汇。这样做的优点是简单易行,缺点是可能会产生语义上的错误。
(2)汉字替换
另一种方法是直接替换原文本中的汉字,或者替换拼音相同但读法不同的汉字。
3.2 Backtranslation with a pre-trained machine translation model
机器翻译模型(MT)通过学习源语言和目标语言之间的转换规则,实现将源语言的句子翻译为目标语言。BackTranslation 是通过 MT 模型,将生成的翻译结果作为增强样本。
假设有一个源语言的句子 A=“The quick brown fox jumps over the lazy dog” ,目标语言为 English。当使用 MTS 的翻译模型 Translator 生成的翻译结果 B=“Ich schoß einen königsgott auf der sau.” 时,可以通过以下步骤进行增强:
- 从 MTS 的语言模型获取一种反方向的翻译结果 C=“jumps over the lazy dog on the lord’s square.”
- 用 Translator 将 C 翻译为 Enlish 得到 D=“he jumped through the gate of his palace and drank coffee in the afternoon glow.”
- 最后,返回增强后的文本为 A+D=“The quick brown fox jumps over the lazy dog he jumped through the gate of his palace and drank coffee in the afternoon glow.”
这种方法可以同时增强源语言和目标语言,且可以生成相对比较逼真的文本。
3.3 Text Infilling with Language Models
语言模型(LM)是一种机器学习模型,通过统计语言出现的频率,估计下一个词的概率分布。基于 LM 可以生成新词,填补句子中的空白词,增加句子的情感影响,改善自然语言生成质量。
TextInfilling 可以基于预先训练好的语言模型,从一定的语境中,按照某种概率分布,依据前面的字或词生成新的字或词。
假设有一个文本 A=“He is happy today because he eats well.”,希望通过 TextInfilling 方法生成带噪声的文本 B=“He is h______p toda____y bcos _______”。可以考虑以下几种策略:
- 根据 LM 的生成词表,采用贪婪算法,找到概率最大的词汇。例如:He -> happy, today -> today; because -> because。
- 如果词汇不止一个,可以采用基于语法结构的生成,以生成名词短语。例如:“He is h__pp” -> “He is happy”.
- 如果没有符合条件的词汇,可以使用同义词替换的方法。例如:如果找不到名词短语中的名词,则尝试找到与 happy 类似的其他名词,并替换。
- 如果 LM 模型过于保守,生成结果可能偏离原始文本太远。可以采用模型迭代的方法,将原始文本与生成的文本对齐,生成一系列候选增强样本,利用交叉熵最小化准则,选择最佳的增强结果。
此外,还可以在生成的样本中加入噪声,以探索噪声对模型的鲁棒性。
3.4 Data Deletion with Language Models
数据删除(Data Deletion)是一种非常古老的文本增强方法。它通过删除句子中的部分词汇,生成包含删除词汇的句子。
假设有一个文本 A=“She sat down at the table yesterday.”,希望通过数据删除方法生成带噪声的文本 B=“Sated yesterdy.”,即删除掉了文本中的 “sat” 和 “at”。
- 删除每个词的概率,可以采用类似数据增强的方法,根据前面的字或词进行预测。
- 通过语言模型生成的候选词汇列表,选择概率最大的词汇,作为待删除的词汇。
- 根据语言模型生成新词,填补删词后的句子。
此外,还可以在生成的样本中加入噪声,以探索噪声对模型的鲁棒性。
3.5 Lexicon Induction from Parallel Corpora
词典推导(Lexicon Induction)是一种基于语料库的词表生成方法。它通过统计不同语言之间的词的共现情况,生成对应的词典。
假设有两组文本 A={“The quick brown fox”,“He is beautiful”},B={“She looks very tall”,“Her height is not too high”},希望通过词典推导方法生成对应的词表 C={“the", “is”, “quick”, “brown”, “fox”, “she”, “looks”, “very”, “tall”, “her”, “height”, “not”, “too”, “high”}。
- 统计所有词的共现次数,构建词频矩阵。
- 根据共现矩阵,生成共现矩阵距离矩阵 D,找出距离最近的两个词。
- 如果存在多个词的距离相同,则选择词长的那个词。
- 重复以上步骤,直至所有的词都出现在词表中。
此外,还可以在生成的词表中加入噪声,以探索噪声对词典的鲁棒性。
3.6 Masked Language Modeling using Transformers
遮蔽语言模型(Masked Language Modeling, MLM)是一种 Transformer 模型的预训练任务之一。它利用 Transformer 的自注意机制,对输入进行遮蔽,让模型预测遮蔽的位置。
假设有一个文本 A=“The quick brown fox jumps over the lazy dog”,希望通过遮蔽语言模型方法生成带噪声的文本 B=“The qu_ick br_wn f_x jumps over the la_zy d_og”。
- 使用 Transformer 的自注意模块,随机选择一些位置进行遮蔽。
- 使用语言模型预测遮蔽的位置。
- 返回增强后的文本。
此外,还可以在生成的样本中加入噪声,以探索噪声对模型的鲁棒性。
4. 代码示例及实践
下面给出三个实际例子,展示如何利用上面提到的各个数据增强方法。
import random
from transformers import pipeline
nlp = pipeline('text-generation', model='gpt2')
def data_augmentation(sentence):words = sentence.split()num_words = len(words)aug_sentences = []for i in range(num_words - 1):word = words[i]if len(word) > 3:new_word = ''.join([random.choice(['_', '_','', '_']) for _ in range(len(word))])new_words = [w for w in words[:i]] + [new_word] + [w for w in words[(i+1):]]new_sentence =''.join(new_words)else:continueaug_sentences.append(nlp(new_sentence)[0]['generated_text'].strip())return aug_sentences
text = "The quick brown fox jumps over the lazy dog"
augmented_texts = data_augmentation(text)
print("Original Sentence:", text)
print("
")
print("Augmented Sentences:")
for aug_text in augmented_texts:
print("-", aug_text)
Output:
Original Sentence: The quick brown fox jumps over the lazy dog
<|im_sep|>
Augmented Sentences:
- The ___ quick brown fox jumps over the lazy dog.
- The q__uick brown fox jumps over the lazy dog__.
- Th_e quick brown fox jumps over the lazy do_.
上述代码使用了 GPT-2 预训练模型,生成了原始文本的五份增强样本。可以看到,模型成功地把句子中的数字、标点符号、小写字母替换为无意义的字符,确保原始文本的无意义性,同时又保持了原文本的语义。
from nltk.corpus import reuters
from nltk.tokenize import sent_tokenize, word_tokenize
from langdetect import detect
def get_similar_senteces():sentences = list(reuters.fileids())similar_sentences = set([])language = ''while True:index = int(input("Enter an index between {} and {}".format(0, len(sentences)-1)))sentence = reuters.raw(sentences[index]).lower().replace('
',' ')
detected_language = detect(sentence)if language == '': language = detected_languageelif language!= detected_language: breaksimilarity = input("Is this related to your task? Type yes/no
")if similarity.lower() == 'yes':similar_sentences.add(sentence)elif similarity.lower() == 'no' or similarity == '':passelse:print("Invalid option!")return list(similar_sentences), language
def create_augumented_data(similar_sentences, target_lang, source_lang='english'): import transformers as trfaug_sentences = []tokenizer = trf.AutoTokenizer.from_pretrained('bert-base-multilingual-cased')for sent in similar_sentences: if detect(sent) == target_lang:inputs = tokenizer(sent, return_tensors='pt')['input_ids']mask_positions = [(inputs==tokenizer.mask_token_id).nonzero()[0][idx].item() for idx in range(len(sent))] masked_inputs = trf.modeling_utils.MaskedLMInputs(labels=inputs, attention_mask=None, token_type_ids=None,mlm_probability=0.15)outputs = model(**masked_inputs)pred_tokens = [tokenizer.convert_ids_to_tokens(token.argmax().item(), skip_special_tokens=True) for token in outputs[0]][mask_positions]for ptk in pred_tokens: replaced_sent = sent.replace(tokenizer.mask_token, ptk)aug_sentences.append(replaced_sent)return aug_sentences
model = trf.pipeline('fill-mask', model='bert-base-multilingual-cased', device=-1)
similar_sentences, target_lang = get_similar_senteces()
aug_sentences = create_augumented_data(similar_sentences, target_lang)
for sent in aug_sentences: print('-', sent)
Output: Enter an index between 0 and 91765
Is this related to your task? Type yes/no
Input: Hello how are you?
Is this related to your task? Type yes/no
Input: It's nice to meet you! What is your name?
Is this related to your task? Type yes/no
Input: No worries. My name is John. How can I help you?
Is this related to your task? Type no
Enter an index between 0 and 91765
Is this related to your task? Type yes/no
Input: Well thank you so much for your assistance. Could we schedule a meeting soon?
Is this related to your task? Type yes/no
Input: Yes sure! Please provide me with more information about what would be helpful for you. Thank you.
Is this related to your task? Type yes/no
Input: Ok! Let us know when you have any time available to discuss further details. Sure. Which day works best for you?
Is this related to your task? Type yes/no
Input: Monday works great. When would be a good time for you?
Is this related to your task? Type yes/no
Input: Yesterday morning or Friday evening will work fine. Can you confirm the date please?
Is this related to your task? Type yes/no
Input: This Friday works just perfect. Do you need anything else?
Is this related to your task? Type yes/no
Input: Great! That sounds like a plan. Is there anything else that I could assist you with?
Is this related to your task? Type yes/no
Input: Not really. Have a nice weekend! Bye bye!
Is this related to your task? Type no
['Well thank you so much for your assistance. Could we schedule a meeting soon?', 'Yes sure! Please provide me with more information about what would be helpful for you. Thank you.', 'Ok! Let us know when you have any time available to discuss further details. Sure. Which day works best for you?', 'Yesterday morning or Friday evening will work fine. Can you confirm the date please?', 'Great! That sounds like a plan. Is there anything else that I could assist you with?']
上述代码使用了 BERT 预训练模型,收集了一组相关文本,通过遮蔽语言模型方法,生成了新的文本。可以看到,模型成功地生成新的文本,同时保留了原始文本的意思。
!pip install textaugment
from textaugment import SynonymReplacement, RandomInsertion, RandomDeletion
train_dataset = ["this is the original text.","that was written by someone else."]
def data_augmentation(text):syn_rep = SynonymReplacement(aug_src=['original'], aug_dest=["copy"])rand_ins = RandomInsertion()rand_del = RandomDeletion()texts = []texts.extend(syn_rep.augment(text))texts.extend(rand_ins.augment(text))texts.extend(rand_del.augment(text))return list(set(texts))
for sample in train_dataset:aug_samples = data_augmentation(sample)print("Original Sample:", sample)for aug_sample in aug_samples:print("-", aug_sample)print("<|im_sep|>
")
Output: Original Sample: this is the original text.
<|im_sep|>
- copy is the original text.
- this is the original text.
- original text., this is the.
- another person wrote it.
- some other unrelated text.
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
