天天看點

漫談ELMo

詞嵌入在很長一段時間内對NLP領域有很大的推動的作用,以至于embedding已經成為NLP任務中的一個标準操作。而研究人員卻發現,詞嵌入雖好,但弊端也明顯,于是乎,語言模型就上位了……如果說Word2Vec是NLP領域裡面的一個重要裡程碑,那麼ELMo的誕生應該可以算得上另外一個裡程碑了吧!最近我正是在學習ELMo,是以想整理一下跟大家探讨。

詞嵌入到底出了什麼問題?

詞嵌入(如想詳細了解可戳這裡)操作在NLP中已經成為正常操作,它也使得詞義可以通過稠密向量來表達。但人們開始發現這種操作雖然好,但是仍然有一些問題:

  1. 集外詞怎麼辦?統一使用UNK作為oov的token并不能區分各個集外詞的詞義。
  2. 多義詞怎麼辦?每個詞隻對應一個向量,對于多語義或者有多層意思的詞語而言這樣是不夠的。

第一個問題中,人們嘗試使用字元級的嵌入操作來代替,畢竟字元是可以有限數量的。但第二個問題就是詞嵌入的天然硬傷了,因為詞語無論出現在什麼場景,都隻有一個向量作為表示,舉個例子說,

spark

這個詞出現在日常對話裡面一般都是表示“星火”,但如果出現在一些資料科學技術文章中則可能表示spark這個并行計算平台。

這個問題歸根結底就是,詞向量隻在訓練過程考慮了訓練語料上下文賦予其語義,而在使用過程沒有考慮它在特定的語義環境中到底表達何種意思,是以預訓練的詞向量是“上下文獨立”(context-independent)的。

那麼我們在使用詞向量時進行fine-tune可以解決這個問題嗎?很遺憾,也是不行的,人類語言實在太複雜了,有時不僅僅像上面舉例的

spark

這種領域差別問題,更有可能是表達程度等方面的問題。

是以,我們必須賦予詞嵌入一些更大的彈性,即讓每個詞在特定的詞義環境中表達出它該有的意思,也即我們追求的是獲得“特定上下文”(context-specific)的表征。

ELMo誕生的前夕

等等,還記得語言模型嗎?語言模型每個時間步輸出的表征 h t = f ( x t − 1 , h t − 1 ) h_t = f(x_{t-1},h_{t-1}) ht​=f(xt−1​,ht−1​)不就正是綜合上下文的表征嗎?!于是乎,有人就拍案而起:就是你了!

TagLM大概是第一個使用這種想法的模型,咱們直接上圖

漫談ELMo

圖一 TagLM模型

咱們先看圖的右手邊。右手邊是一個bi-RNN實作的語言模型(我又要打廣告了!如果不了解語言模型請戳這裡,不了解RNN請戳這裡),即對前向RNN是用前文 [ x 1 , x 2 , . . . , x t − 1 ] [x_1,x_2,...,x_{t-1}] [x1​,x2​,...,xt−1​]預測 x t x_{t} xt​,而後向RNN用後文 [ x t + 1 , x t + 2 , . . . , x T ] [x_{t+1},x_{t+2},...,x_T] [xt+1​,xt+2​,...,xT​]預測 x t x_{t} xt​,每個詞 x t x_t xt​進入這個LM都會得到一個hidden state,咱們把它标記為 h t L M = [ h t f o r w a r d ; h t b a c k w a r d ] h_{t}^{LM} = [h_{t}^{forward};h_{t}^{backward}] htLM​=[htforward​;htbackward​]。這一部分是預訓練的,跟咱們使用Word2Vec預訓練詞向量一個道理。

再看左圖下方。每個輸入詞都會同時經過兩個嵌入操作,分别是char-level和word-level的嵌入,兩個嵌入操作得到的向量會拼接起來,作為網絡主體bi-RNN的input。

然後看左圖中部。詞向量通過一個L層的bi-RNN得到每個time step的hidden state,咱們标記為 h t , l h_{t,l} ht,l​,

l

表示所在的層标,

t

則表示輸入序列的時間步。以兩層的bi-RNN為例,第一層輸出的hidden state會拼接上預訓練的bi-LM得到的雙向隐藏特征,再進入下一層,最後用以NER等序列标注任務。

簡單來說,tagLM對之前單純使用預訓練詞向量的NLP任務做了簡單的優化,就是加上LM embedding,是以同時考慮了上下文獨立特征和特定上下文特征。

ELMo的降臨

受到TagLM的啟發,ELMo就應運而生,它的降臨将徹底改變之前的局面:詞嵌入不再是一個向量查找表,而是一個function!換句話說,以前咱們可以根據單個詞的index查找出對應的詞向量,但現在不一樣了,我們需要把整句話放進這個函數裡面,我們才能獲得每個詞的表征向量。而且以前同一個index查找出來的詞向量肯定是相同的,但現在每個詞在任何不同語境下都會有不同的表征。

老規矩先上圖

漫談ELMo

圖二 ELMo模型

這個大概是我能找到的最棒的動圖了。ELMo是在TagLM的基礎上進行了若幹的優化。

  1. 與TagLM隻采用頂層輸出不同,ELMo的representation使用了bi-LSTM所有層的hidden state的以及token的表征。以L=2為例,bi-LM輸出的表征為

    R k = { x k L M , h k , j f o r w a r d , h k , j b a c k w a r d ∣ j = 1 , 2 } = { h k , j L M ∣ j = 0 , 1 , 2 } \begin{aligned} R_k &=\{x_k^{LM},h_{k,j}^{forward},h_{k,j}^{backward}|j=1,2\}\\ &=\{h_{k,j}^{LM}|j=0,1,2\} \end{aligned} Rk​​={xkLM​,hk,jforward​,hk,jbackward​∣j=1,2}={hk,jLM​∣j=0,1,2}​

    當j=0時表示輸入token的表征,這一部分大體跟TagLM是一樣的。原論文作者指出,低層表征容易捕獲文法資訊,文法資訊在序列标注如POS、NER等任務中作用比較大,而高層表征卻更好地捕獲語義資訊,在機器翻譯、智能問答等任務裡面比較有用。為了綜合語義和文法資訊,最好的辦法就是将所有資訊彙總起來。

  2. 各表征的彙總方式是

    E L M o k t a s k = γ t a s k ∑ j = 0 L s j t a s k h k , j L M ELMo_{k}^{task} = {\gamma}^{task}\sum_{j=0}^{L}s_{j}^{task}h_{k,j}^{LM} ELMoktask​=γtaskj=0∑L​sjtask​hk,jLM​

    其中 γ t a s k \gamma^{task} γtask是一個可訓練單值參數,用于對特定任務場景下對表征向量的調整; s j t a s k s_{j}^{task} sjtask​是softmax正則化的參數。(原文沒有細說,經過查證,這個應該是一個用作權重平均各層表征的向量,即 s ∈ R 1 × L s{\in}R^{1{\times}L} s∈R1×L,隻是各層權重歸一化的方法是使用softmax)

    累加号要成立的話,那麼意味着各層的output都必須是相同次元的,對LSTM來說這個還是比較好操作的東西,畢竟輸出次元(即units)多少都是可以設定的,但是要求輸入token表征也是一樣的次元。原論文說每層units都是4096,但都會映射到512進行skip-connection(按原論文的描述,第一層與第二層的映射output應該相加,這個結構在上圖中沒有畫出來)。

  3. 最後一點,ELMo隻采用char-level的特征,就是每個詞采用多個kernel size一共2048個卷積核/層的CNN獲得字元序列特征,預設設定是兩層,這個CNN也使用了skip-connection,并同樣映射到512維,而且模型參數在每個時間步是共享的。

至此,ELMo的細節應該都摳完了。

ELMo咋用?

ELMo其實就是多層bi-LM,是以它需要在大規模unlabel語料中進行預訓練。在具體的NLP任務中,預訓練好的ELMo相當于一個函數,将輸入句子中每個詞映射成對應的實數向量,然後再将其feed到後續的模型裡面。

在具體NLP任務中,最簡單的做法是将ELMo的模型參數固定住,這樣梯度信号并不會backprop過來,整個ELMo唯一受影響的就是 γ \gamma γ參數和 s s s參數。但更通行的,也是效果更好的做法,就是在具體的NLP任務中做transfer learning,即對預訓練模型做fine-tune,就像在各種CV任務中一樣。

是以說ELMo開啟了NLP的新曆程,因為從這之後,NLP任務也可以像CV任務一樣,選擇一個合适的back bone,再針對自己需要解決任務去設計模型。

參考資料

  • https://www.analyticsvidhya.com/blog/2019/03/learn-to-use-elmo-to-extract-features-from-text/
  • https://arxiv.org/pdf/1802.05365.pdf
  • https://blog.csdn.net/sinat_29819401/article/details/90669304
  • https://blog.csdn.net/sinat_29819401/article/details/94015798
  • https://blog.csdn.net/sinat_29819401/article/details/94176245

繼續閱讀