NLP Data Augmentation 常見方法


Posted by Mars.Su on 2020-10-26

Abstract

過往我們都知道當資料量不足時,硬著頭皮去訓練機器學習模型,反而會帶來不好的效果。所以後來有人提出了Data Augmentation的概念,為了就是應用於資料不足時,可以透過一些方法來將資料做增量的動作,進而能進一步的應用於模型的訓練。

過往如果在圖片的data augmentation,時常會利用旋轉、偏移、縮放等方式,進而增加資料。而data augmentation其實最普遍用在影像處理的領域,所以對於NLP的相關方法可說是少之又少,包含現在最新的NLP data Augmentaion方法的論文是Conditional Bert Contextual Augmentation(Xing et al., 2018),而這篇我也會在下一篇文章來進一步的說明。

其中主要參考了來源是一位國外的工程師Amit Chaudhary的分享,我也有加入一些簡中的作法進來,希望能幫助到大家

Introduction

這篇我會先以比較簡單且傳統的做法來做NLP Data Augmentation介紹,其中我會盡可能以『中文』來舉例說明,這樣對於中文語系的國家看到時也會比較直覺,常見方法如下:

一、相似詞替換

概念:
我想這個方法是大家最直覺想到的作法,就是利用相近意思的詞彙來做代替,如下圖

常見做法:

  1. 建立分詞WordNet
    如果是本身就有著大量的文字資料時,可以透過分詞(ex. Jieba, 中研院CKIP繁中斷詞)後的結果以及GraphDB(ex. Neo4J, Dgraph, AWS-Naptune)等相關工具來儲存,再利用一些演算法來計算相似詞之間的權重即可找出相似詞。

    當然如果採用這個方式,無論是建置或是維護的成本就會相對比較高一點,但卻是有機會可以建立自己產業know-how的WordNet。除此之外,如果是要做contextual的話,有些詞是一詞多義的,所以如果搭配上下文的話該方法會有一定的限制。

  2. 建立詞向量模型來計算相近詞
    該方法就可以利用像是Word2vec的model來計算(ex. gensim)來將詞匯入,其中內部會透過像是cosine-similarity方法來計算相近詞,再由自己決定要取Top N 的詞來替換原本的字詞做取代。下面是一個簡單的程式示意,如果有不熟悉gensim怎麼操作的話,可以參考這篇文件

from gensim.models import word2vec

model = word2vec.Word2Vec.load('word2vec.model')
for item in model.most_similar('帥氣'):
    print(item)
結果如下
('英俊', 0.7148515)
('酷帥', 0.7018151)
('俊朗', 0.6905148)

二、Back Translation(反向翻譯)

概念:
這個方法是透過將原本句子所屬的語言翻譯到另外一個語言,在轉回來取得句子。
簡單來說,今天有一句話"小明很帥氣"(中文),先翻譯到英文變成"Xiao Ming is handsome",然後再翻回來中文結果變成"小明很帥",我們就可以拿到意思一樣但表達不同的語句,所以可以自行決定要翻英文再回來中文、或翻其他國外語言再回來中文都可以。該方法的簡單示意圖如下:

這邊引用一下國外有一位工程師的作法,他就是將句子翻譯到多國語言再翻回來做資料增量,示意圖如下

常見做法:
這個方法最常見就是去呼叫一隻translate api(ex.google-translate-api)然後再將結果蒐集到原本的資料集當中,來進行資料增量。

三、Random Noise Injection

該方式透過加入noise的資料來加強,進而增加模型的robustness

概念:
接下來介紹的概念是來自Easy Data Augmentation(Wei et al., 2019),簡單來說就是新增刪除修改一些雜訊資料進來做訓練,簡中的範例github連結請點此

  1. Random Insert
    找一個相似詞隨機插入到句子中的隨機位置,如下圖
  2. Random Swap
    隨機交換句子中任兩個word的位置且重複n次,如下圖
  3. Random Delete
    依照一個機率P隨機刪除句子中某一個word,如下圖

四、Syntax-tree

概念:
其實這個方法概念不難,但是技術要做到的話可能會有點困難度,尤其是在中文的語系。簡單來說,他就是將主動的語法轉變成被動的語法,或是將被動轉換成主動的語法,以下面的示意圖呈現:

藉由上面的範例可以知道,即便將主詞與受詞做對掉(主動換被動),整體的句子語意不會因此而有所不一樣。

但這個方式實作上比較麻煩,第一並不是全部的語句可以這樣被轉換;第二,即便可以轉換在中文文字的轉換上會有點麻煩,我也相信這個方法可以做到一定程度的增量,所以也把他列出來讓大家知道它的原理。

五、Pretrained model MLM(Masked Language model)

概念:
接下來這邊開始會簡單說明一下關於pretrained model的作法,前面幾個作法通常只要搞定好整體架構的IPO(Input, Process, Ouput)就可以將新增的資料合併到原本的資料集來做到『增量』的效果。

但其實很多時候我們手邊並沒有太多的corpus或文字相關的資料,有時候在一些技術跟時間成本的考量會採用到事先訓練好的ML模型,像是Bert, AlBert等,透過此方法來適時的站在巨人的肩膀上來降低一點自己的門檻。

我們都知道以BERT來說,他會先經歷過兩個pre-train的方法,一個NSP(Next Setence Prediction)來預測這一句是否為上一句的下一句,以及另一個是 MLM(Masked Language model)透過前後鄰近的詞用來做被mask的詞預測。因此在這裡利用的MLM的特型把其中一個詞替換成[mask]來讓已經pretrain好的模型來做預測該詞。

實際做法:
關於怎麼做,我們可以自己找一個的詞,並將他替換成[mask],接著利用pretrain model來預測他有可能會出現的詞,可以利用HuggingFace這個套件來處理,它提供了許多NLP Pretrained model還有一些api的操作方法,相信使用起來並不會太難。簡單的程式範例如下:

from transformers import pipeline
nlp = pipeline('fill-mask')
nlp('小明 <mask> 帥氣')
結果示意如下
[{'score': 0.515411913394928,
  'sequence': '<s> 小明 非常 帥氣</s>',
  'token': 1256},
 {'score': 0.1166248694062233,
  'sequence': '<s> 小明 很 帥氣</s>',
  'token': 269},
 {'score': 0.07387523353099823,
  'sequence': '<s> 小明 超級 帥氣</s>',
  'token': 2422}
 ]

六、Conditional Pretrained model

這個方法來自Data Augmentation using Pre-trained Transformer Models(Kumar et al., 2020),簡單來說他將每一句的打上一個label,並且concat進入到transformer做訓練,示意圖如下

而這個方法的fine-tune就是文字生成,進而來生成新樣本,至於如何生成呢?可以透過指定前n個字詞,來讓model針對接下來的字詞做預測,示意如下:

以這個例子來說,就是給定好label(positiver)跟前三個字詞('it is very'),接著就可以讓pretrain model來做預測且生成句子,也能確保整體語句的意義不會不同。

Conclusion

當然從一些參考資料當中也有一些其他的簡單方式可以做到文字的data augmentation,這邊提出自己認為比較重要且用過的方式,以及認為比較適合在中文這個語系的做分享,之後若有機會用到其中幾個方法,像是Mixup等再來補充這篇文章的內容。

最後,近年來也有學者提出了幾篇論文來探討關於文字的Data Augmentaion,其連結如下供大家參考,接下來也會陸續讀完這幾篇論文來分享:

Reference


#AI #NLP #Data-Augmentation #Paper







Related Posts

MarkDown語法

MarkDown語法

JS 引擎如何運作:理解 Execution Context 與 Variable Object

JS 引擎如何運作:理解 Execution Context 與 Variable Object

系統架構

系統架構


Comments