一,概述
在自然語言生成的任務中,大部分是基於seq2seq模型實現的(除此之外,還有語言模型,GAN等也能做文本生成),例如生成式對話,機器翻譯,文本摘要等等,seq2seq模型是由encoder,decoder兩部分組成的,其標准結構如下:

原則上encoder,decoder可以由CNN,RNN,Transformer三種結構中的任意一種組合。但實際的應用過程中,encoder,decnoder的結構選擇基本是一樣的(即encoder選擇CNN,decoder也選擇CNN,如facebook的conv2conv)。因此本文我們也就介紹encoder,decoder是同種結構的三種模型,並對比其內部結構在編碼和解碼的不同之處。
二,模型介紹
1)基於RNN的seq2seq模型
在這里的encoder和decoder都采用RNN系列模型,一般是GRU,LSTM等。一般有兩種用法:即單向encoder-單向decoder;雙向encoder-單向decoder(在這里要保證encoder的hidden_size等於decoder的hidden_size,但是對於雙向encoder時,因為一般采用拼接來融合雙向信息,因此此時encoder的hidden_size一般為decoder的hidden_size的一半)。
基於RNN的encoder端和用RNN做分類問題基本一致,但在decoder端需要融入encoder端的信息,因此是有一些不一樣的,以GRU為例(LSTM同理):
encoder端:
$r_t = \sigma(W_r [h_{t-1}, x_t])$
$z_t = \sigma(W_z [h_{t-1}, x_t])$
$\hat{h_t} = tanh(W_{\hat{h}} [r_t * h_{t-1}, x_t])$
$h_t = (1 - z_t) * h_{t-1} + z_t * \hat{h_t}$
decoder端:需要融入attention后的encoder的編碼向量$c_t$
$r_t = \sigma(W_r [h_{t-1}, x_t, c_t])$
$z_t = \sigma(W_z [h_{t-1}, x_t, c_t])$
$\hat{h_t} = tanh(W_{\hat{h}} [r_t * h_{t-1}, x_t, c_t])$
$h_t = (1 - z_t) * h_{t-1} + z_t * \hat{h_t}$
注:在decoder中的矩陣$W_r, W_z, W_{\hat{h}}$和encoder中的維度是不同的,因為后面的$ [h_{t-1}, x_t, c_t]$是拼接操作,這里面的$ h_{t-1}, x_t, c_t$都對應一個映射矩陣,只是為了方便操作,將他們對應的矩陣也拼接在一起計算了。
2)基於conv的seq2seq模型
基於卷積的seq2seq模型好像使用范圍沒有那么廣,目前我見到的只有在機器翻譯和語法糾錯中有用到(當然肯定不排除在其他任務中有使用),但是基於卷積的seq2seq是引入了不少有意思的知識,首先引入了stacking conv來捕捉長距離的信息。主要圍繞facebook的Convolutional Sequence to Sequence Learning 來講解。
1)不采用池化,只采用卷積操作,並且通過padding使得每一層卷積后的序列長度不變(這種操作可以確保在多層conv中序列長度保持一致)。
2)對於輸入$x$,其維度為$n*d$,在這里假設kernel size的大小為$k$,則給定一個卷積的參數矩陣$W$,其維度為$2d*kd$(本質就是一個kernel size為k的一維卷積對序列做卷積操作,並且filter size為2d,這樣使得卷積后的token的向量的維度為2d),使得轉換后的$h$(x的隱層表示)的維度為$n*2d$。
3)引入GLU門機制激活函數,其表達式如下:
![]()
以上面得到的$h$為例,其前半段$h*d$置為A,其后半段$h*d$置為B,對B用sigmoid函數激活后類似於門機制,然后對$A$和$\sigma(B)$做元素對應相乘,這樣也保證了每一層卷積后的輸出維度和輸入維度一致(這就是為什么第2步要使得卷積后的token的向量維度為$2d$,這種門機制在很多地方都可以使用,用來取代激活函數,既可以做非線性轉換,又可以過濾重要的信息)。
4)采用了multi-step attention來連接encoder和decoder,即對decoder的每一層都單獨計算attention(至於為什么要這樣做,我猜可能是因為卷積是提取局部信息的,而每一層提取的局部信息都不一樣,因為每一層對encoder的結果的關注位置也是不一樣的,因此每一層對encoder的attention也應該是不一樣的)。
3)基於transformer的seq2seq模型
基於transformer的seq2seq模型來源於attention is all you need,具體的介紹可以見詳解Transformer模型(Atention is all you need)。
三,三種模型的對比
從encoder,decoder,attention三個部位來對比
encoder端:
1)RNN
RNN的encoder端和常見的用於分類的RNN模型沒有什么區別,輸入$x$,得到最后一層的隱層狀態,用於之后計算attention。
2)conv
在這里采用stacking conv來對輸入$x$編碼,作者認為這種stacking conv是可以捕獲到長距離的信息的,假設卷積的kernel size為3,第一層卷積能覆蓋的最大長度為3(對原始序列),第二層卷積能覆蓋的最大長度為$3^2$(對原始序列),依次類推,因此隨着卷積層的增長,在原始序列上能覆蓋的最大長度呈指數增長。同樣去最后一層的隱層狀態,用於之后計算attention。同時在每一層之間都引入了殘差連接和batch normalization。
3)transformer
transformer的encoder和之前介紹的用transformer做分類基本一致(文本分類實戰(八)—— Transformer模型)。整個結構由self-attention和feed forward層組合而成的,同樣將最后一層的隱層狀態用於之后計算attention。
attention端:
1)RNN
RNN的attention都是基於decoder中的目標詞和encoder的序列中的每一個詞計算點積(或者其他的計算方式,如MLP,conv等都可以),然后softmax得到一個概率分布,也就是attention的權值。然后對encoder的序列中的每個詞對應的向量做加權和得到最終的attention的結果。具體的如下圖:

2)conv
卷積中的attention的計算和RNN中的基本一致,但是最后在做加權和的時候引入了最初encoder中embedding的詞向量,其表達式如下:

上面式子中$\alpha_{ij}^l$是表示$l$解碼層對應的attention權重,$z_j^u$表示的是encoder最后的隱層結果,$e_j$表示的是encoder最初的embedding層的詞向量,$j$表示encoder中第$j$個詞。
3)transformer
transformer的attention計算有點不太一樣,在這里仍然使用了在做self-attention計算中的multi-attention和scaled-attention。因此這里雖然目標詞是來源於decoder,但是整個計算過程和transformer中的self-attention是一致的。
decoder端:
1)RNN
RNN在解碼時一般都是用單層,因為從左到右的這種單層模式也符合解碼的模式,dencoder的層數也一般和encoder保持一致。RNN的解碼如上面的GRU示例一樣,只是在計算的過程中引入了encoder的結果,其他的和encoder沒什么太大的差異。
2)conv
conv在解碼時主要是在序列的補全時和encoder不一樣,為了保持卷積后序列的長度不變,encoder時會在序列的兩端添加長度為$(kernel size - 1) / 2$的pad。而在decoder時會在序列的左端添加長度為$(kernel size - 1)$的pad(在這里kernel size一般取奇數,便於添加pad)。另外不同於RNN的是(RNN是將attention引入到了RNN結構中),conv在解碼時的卷積操作只是提取序列的特征,然后經過GLU操作到和encoder的隱層相同的向量維度之后再計算attention,最后將attention的結果和GLU的結果和卷積前的結果相加作為下一層的輸入。另外在解碼的每一層都引入了殘差連接和batch normalization。
3)transformer
transformer的decoder層其實和encoder層差不多,主要不同在加入了encoder的attention的結果,但這里和RNN,conv又優點不一樣,這里是先對decoder中的序列做self-attention提取特征,然后再做對encoder的attention,然后進入到feed forward層,因此在這里的操作是串行的。同樣再transformer中因為層數比較多,也引入了殘差連接和Layer normalization(在自然語言處理中很多layer normalization的用的比batch normalization,除非是卷積,不然一般不用batch normalization)。
除了上面的不同點之外,一般來說transformer和conv的層數都比較深,因此也就需要殘差連接和normalization來避免模型過擬合。此外在transformer和conv中都會引入位置向量來引入序列的位置信息,但是在RNN中,因為RNN的本質是從前往后又依賴關系的,因此位置信息在這種傳遞過程中已經存在了。
上述模型具體的代碼見 https://github.com/jiangxinyang227/NLP-Project/tree/master/dialogue_generator
參考文獻:
Convolutional Sequence to Sequence Learning
NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE
Attention Is All You Need
A Multilayer Convolutional Encoder-Decoder Neural Network for Grammatical Error Correction
