什么是數(shù)據(jù)增強(qiáng)
數(shù)據(jù)增強(qiáng)可以簡(jiǎn)單理解為由少量數(shù)據(jù)生成大量數(shù)據(jù)的過(guò)程。一般比較成功的神經(jīng)網(wǎng)絡(luò)擁有大量參數(shù),使這些參數(shù)正確工作需要用大量的數(shù)據(jù)進(jìn)行訓(xùn)練,但實(shí)際情況中數(shù)據(jù)并沒(méi)有那么多,因此需要做數(shù)據(jù)增強(qiáng)芯杀。
數(shù)據(jù)增強(qiáng)的作用
- 增加訓(xùn)練的數(shù)據(jù)量,提高模型的泛化能力
- 增加噪聲數(shù)據(jù)雅潭,提升模型的魯棒性
- 解決數(shù)據(jù)不足或數(shù)據(jù)不均衡問(wèn)題
數(shù)據(jù)增強(qiáng)的分類(lèi)
根據(jù)數(shù)據(jù)增強(qiáng)的對(duì)象可以將增強(qiáng)研究分類(lèi)兩類(lèi):
- 面向文本表示的增強(qiáng)研究: 主要是對(duì)原始文本的特征表示進(jìn)行處理揭厚,比如在表示層注入隨機(jī)噪音等方法,來(lái)獲得增強(qiáng)后的文本表示扶供。增強(qiáng)后的表示可以再進(jìn)行解碼獲得增強(qiáng)文本或者直接用于訓(xùn)練模型筛圆。
- 面向原始文本的增強(qiáng)研究: 主要是通過(guò)對(duì)原始文本中的詞進(jìn)行同義詞替換或者刪除等操作來(lái)進(jìn)行增強(qiáng)。大部分研究都通過(guò)引入各種外部資源來(lái)提升增強(qiáng)效果椿浓。
本文針對(duì)于面向原始文本的增強(qiáng)研究太援,總結(jié)以下幾種方法闽晦。
EDA
ICLR 2019 workshop 論文《EDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasks》介紹了幾種NLP數(shù)據(jù)增強(qiáng)技術(shù),并推出了EDA github代碼提岔。EDA github repo提出了四種簡(jiǎn)單的操作來(lái)進(jìn)行數(shù)據(jù)增強(qiáng)仙蛉,以防止過(guò)擬合,并提高模型的泛化能力碱蒙。EDA 在個(gè)文本分類(lèi)問(wèn)題上帶來(lái)性能的提升荠瘪,但是其增強(qiáng)方式可能會(huì)破壞原始文本的句法結(jié)構(gòu)和通順性。
同義詞替換
不考慮 stopwords赛惩,在句子中隨機(jī)抽取n個(gè)詞哀墓,然后從同義詞詞典中隨機(jī)抽取同義詞,并進(jìn)行替換喷兼。關(guān)于同義詞可以使用開(kāi)源同義詞表+領(lǐng)域自定義詞表來(lái)建立篮绰。
def synonym_replacement(words, n):
new_words = words.copy()
random_word_list = list(set([word for word in words if word not in stop_words]))
random.shuffle(random_word_list)
num_replaced = 0
for random_word in random_word_list:
# get_synonyms 獲取某個(gè)單詞的同義詞列表
synonyms = get_synonyms(random_word)
if len(synonyms) >= 1:
synonym = random.choice(list(synonyms))
new_words = [synonym if word == random_word else word for word in new_words]
num_replaced += 1
if num_replaced >= n:
break
sentence = ' '.join(new_words)
new_words = sentence.split(' ')
return new_words
隨機(jī)刪除
句子中的每個(gè)詞,以概率p隨機(jī)刪除褒搔。有幾種極端情況需要考慮:
- 如果句子中只有一個(gè)單詞阶牍,則直接返回
- 如果句子中所有單詞都被刪掉,則隨機(jī)返回一個(gè)單詞星瘾。(這個(gè)策略可以根據(jù)自己項(xiàng)目進(jìn)行自定義。)
def random_deletion(words, p):
# obviously, if there's only one word, don't delete it
if len(words) == 1:
return words
# randomly delete words with probability p
new_words = []
for word in words:
r = random.uniform(0, 1)
if r > p:
new_words.append(word)
# if you end up deleting all words, just return a random word
if len(new_words) == 0:
rand_int = random.randint(0, len(words) - 1)
return [words[rand_int]]
return new_words
隨機(jī)交換
句子中惧辈,隨機(jī)選擇兩個(gè)詞琳状,位置交換。該過(guò)程可以重復(fù)n次盒齿。
(swap_word 函數(shù)中隨機(jī)產(chǎn)生兩個(gè)序列下標(biāo)念逞,如果相同最多重新生成三次。)
def random_swap(words, n):
new_words = words.copy()
for _ in range(n):
new_words = swap_word(new_words)
return new_words
def swap_word(new_words):
random_idx_1 = random.randint(0, len(new_words) - 1)
random_idx_2 = random_idx_1
counter = 0
while random_idx_2 == random_idx_1:
random_idx_2 = random.randint(0, len(new_words) - 1)
counter += 1
if counter > 3:
return new_words
new_words[random_idx_1], new_words[random_idx_2] = new_words[random_idx_2], new_words[random_idx_1]
return new_words
隨機(jī)插入
句子中的每個(gè)詞边翁,以概率p隨機(jī)刪除翎承。隨機(jī)插入的字符通過(guò)同義詞獲取。
def random_insertion(words, n):
new_words = words.copy()
for _ in range(n):
add_word(new_words)
return new_words
def add_word(new_words):
synonyms = []
counter = 0
while len(synonyms) < 1:
random_word = new_words[random.randint(0, len(new_words) - 1)]
synonyms = get_synonyms(random_word)
counter += 1
if counter >= 10:
return
random_synonym = synonyms[0]
random_idx = random.randint(0, len(new_words) - 1)
new_words.insert(random_idx, random_synonym)
模型預(yù)打標(biāo)
使用少量的數(shù)據(jù)訓(xùn)練一個(gè)模型或者將少量數(shù)據(jù)通過(guò) Bert finetune 訓(xùn)練一個(gè)模型符匾,在已有模型的基礎(chǔ)上對(duì)無(wú)監(jiān)督數(shù)據(jù)打標(biāo)叨咖,選擇置信度較高的數(shù)據(jù)作為偽標(biāo)簽(pseudo label)加入到已有數(shù)據(jù)中訓(xùn)練模型,循環(huán)迭代優(yōu)化模型啊胶。
回譯(Back Translation)
回譯(Back Translation)是機(jī)器翻譯中非常常用的數(shù)據(jù)增強(qiáng)的方式甸各,其主要的思想就是通過(guò)翻譯工具將一個(gè)句子翻譯為另一種語(yǔ)言,再把這翻譯的另一種語(yǔ)言再翻譯為原來(lái)的語(yǔ)言焰坪,最后得到一個(gè)意思相近但表達(dá)方式不同的句子趣倾。這種方式也是目前相對(duì)靠譜的方式,這種方式不僅有同義詞替換某饰,詞語(yǔ)增刪儒恋,還具有對(duì)句子結(jié)構(gòu)語(yǔ)序調(diào)整的效果善绎,并還能保持與原句子意思相近,是目前一種非常有效的文本數(shù)據(jù)增強(qiáng)方式诫尽。
反向翻譯的過(guò)程如下:
- 假設(shè)需要增強(qiáng)的數(shù)據(jù)是中文
- 借助第三方翻譯軟件禀酱,將中文翻譯為法文、日文等多種語(yǔ)言箱锐。
- 將翻譯的文本二次翻譯為中文(可以選取不同的翻譯接口)比勉。
- 如果二次翻譯的結(jié)果和原文本不一致,則加入到增強(qiáng)樣本中驹止。
我喜歡學(xué)習(xí)NLP浩聋,因?yàn)樗嬖跇O大的挑戰(zhàn)。
- 百度翻譯結(jié)果:I like learning NLP because it has great challenges.
- 將百度翻譯結(jié)果通過(guò)谷歌翻譯:我喜歡學(xué)習(xí) NLP臊恋,因?yàn)樗泻艽蟮奶魬?zhàn)衣洁。(與原句不同,則獲得增強(qiáng)數(shù)據(jù))
其他方法
- 加入無(wú)意義的詞語(yǔ):比如“忘記打卡怎么辦”抖仅,加入無(wú)意義的詞語(yǔ)“你好坊夫,忘記打卡怎么辦”
參考鏈接
關(guān)于我
dreampai(公眾號(hào),簡(jiǎn)書(shū)撤卢,知乎同名)环凿,專(zhuān)注于 NLP和金融。