seq2seq和Transformer
簡單而言,seq2seq由兩個RNN組成,一個是編碼器(encoder),一個是解碼器(decoder).以MT為例,將源語言“我愛中國”譯為“I love China”,則定義序列:
\[ X=(x_0,x_1,x_2,x_3)\\ 其中,x_0=“我”,x_1=“愛”,x_2=“中”,x_3=“國” \]
另外目標序列:
\[ Y=(y_0,y_1,y_2)="I\ love\ China" \]
通過編碼器將\(X=(x_0,x_1,x_2,x_3)\)映射為隱層狀態\(h\),再經由解碼器將\(h\)映射為\(Y=(y_0,y_1,y_2)\)
通常使用\(h?\)表示編碼器的隱狀態;用\(s?\)表示解碼器的隱狀態
注意:編碼器輸入和解碼器輸出向量的維度可以不同,最后將預測T和真實目標序列T‘做loss(通常是交叉熵)訓練網絡。
注意力機制
通過編碼器,把\(X=(x_1,x_2,x_3,x_4)\)映射為一個隱層狀態\(H=(h_0,h_1,h_2,h_3)\),解碼器將\(H=(h_0,h_1,h_2,h_3)\)映射為\(Y=(y_0,y_1,y_2)\)。在帶注意力機制的編解碼器中,\(Y\)中的每一個元素都與\(H\)中的所有元素相連,而解碼器的每個元素通過不同的權值給予編碼器輸出\(Y\)不同的貢獻。
解碼器輸出有3個:
上一解碼步的隱狀態(\(s_{t-1}\))
上一解碼步的輸出(\(y_{t-1}\))
注意力輸出(編碼器輸出的加權和,context,是編碼器端發給解碼器信息的地方,由所有的編碼器輸出得到一個定長的向量,代表輸入序列的全局信息,作為當前解碼步的上下文),計算方法為:
\[ c_i=\sum_{j=1}^{T_x}\alpha_{ij}h_j \]
其中,\(\alpha_{ij}\)是權重(\(\alpha_{ij}\)是標量,\(\alpha\)是二階張量),又稱作alignment;\(h\)是編碼器所有時間步上的隱狀態,又稱作value或memory;\(i\)表示解碼步,\(j\)表示編碼步,輸出\(c_i\)是和\(h_j\)同樣大小的向量。在時間\(i\)上,
\[ c_i=\sum_{j=1}^{T_x}\alpha_{ij}h_j=\alpha_{i,1}h_1+\alpha_{i,2}h_2+...+\alpha_{i,T_x}h_{T_x} \]
其中,\(c_i\)是與編碼器輸出\(h_j\)等大的向量;\(j\)為編碼步;\(i\)為解碼步;\(\alpha_{ij}\)為標量,計算方式:
\[ \alpha_{ij}=\frac{exp(e_{ij})}{\sum_{k=1}^{T_x}exp(e_{ik})} \]
其中,\(e_{ij}=a(s_{i-1,j},h_j)\),表征\(s_{i-1}\)和\(h_j\)的相關程度,即對于某個給定的解碼步,計算上一解碼步的隱狀態和所有編碼步輸出的相關程度,并且用softmax做歸一化。這樣,與上一解碼步狀態相關度大的編碼器輸出\(h\)的權重就大,在本解碼步的整個上下文里面所占的比重就多,解碼器在本時間步上解碼時就越依賴這個編碼器的輸出\(h\).\(e_{ij}\)又被稱作能量函數,\(a(·)\)的計算方法:
- 對\(s_{i-1}\)做線性映射,得到向量作為query(解碼器上一時間步隱狀態作為“查詢”),記作\(q_i\)
- 對\(h_j\)做線性映射,得到向量作為key(編碼器每一個時間步上的結果作為key待查),記作\(k_j\)
- \(e_{ij}=v^T(q_i+k_j)\),\(q_i\)和\(k_j\)的維度必須相同,同為d維;\(v\)是一個d×1的向量,從而得到的\(e_{ij}\)是一個標量
- 3中query和key做加法,之后通過一個權重變為標量。這被稱作“加性注意力”,相應的,可以做元素乘,被稱作“乘性注意力”
- location-sensitive,認為相鄰\(\alpha_{ij}\)之間的關系會相對較大,為了捕獲這種關系對alignment進行了卷積。
- query有多種,不僅僅有上一解碼步的隱狀態;也有當前解碼步的隱狀態;還有將上一解碼步上的隱狀態和上一解碼步的輸出拼接作為query。但在TTS中,將上一解碼步的隱狀態和輸出拼接作為query并不好,原因可能是可能兩者不在同一空間,因此要具體問題具體分析。
1、2中的線性映射都是待訓練的,3中的\(v\)也是待訓練的。
對query和key求相關性從而獲得權重(alignment),用該權重對value加權和從而得到上下文送入解碼器。
小結
Transformer
左右分別是編碼器和解碼器
編碼器和解碼器的底部都是embedding,而embedding又分為兩部分:input embedding和positional embedding,其中input embedding就是NLP中常見的詞嵌入。因為Transformer中只有attention,對于一對(query, key),無論這對query-key處在什么位置,其計算都是相同的。不像CNN或RNN有一個位置或時序的差異:CNN框住的是一塊區域,隨著卷積核的移動,卷積核邊緣的點也隨著有序變化;RNN則更為明顯,不同時序的\(h_t\)和\(s_t\)不同,而且是隨著輸入順序(正/倒序)而不同。
因此Transformer為了體現出時序或者序列中的位置差異,要對input加入一定的位置信息,這即是position embedding。求位置id為pos的位置編碼向量:
\[ \left\{\begin{matrix} PE(pos,i)=sin(\frac{pos}{10000^{\frac{i}{d_{model}}}}),\ 若i為奇數 \\ PE(pos,i)=cos(\frac{pos}{10000^{\frac{i}{d_{model}}}})\ 若i為偶數 \end{matrix}\right. PE向量第i維的求解方法 \]
編碼器和解碼器輸入序列shape: \([T,d_{model}]\),即每個時刻的\(x_i\)都是\(d_{model}\)維的,因此\(pos\in [0,T]\),\(i\in[0,d_{model}]\)。即對于輸入的\([T,d_{model}]\)的一個張量,其中的每一個標量都對應一個獨特的編碼結果,可以理解為給embedding一個低頻信號,讓其周期性波動,而且每個維度波動都不相同,以表征其id信息。編碼器和解碼器的中部分別是兩個塊,分別輸入一個序列,輸出一個序列,這兩個塊重復N次。編碼器的每個塊里有兩個子網,分別為Multi-Head Attention和Feed Forward Network(FFN);解碼器的每個塊里有三個子網,分別是2個Multi-Head Attention和一個FFN。這些子網之后都跟一個add & norm,就是像ResNet那樣做一個殘差,然后加一個layer normalization。
解碼器最后還有個linear和softmax
FFN
FFN就是對一個輸入序列\(X=(x_0,x_1,...,x_T)\),對每一個\(x_i\)都進行一次channel的重組:512 -> 2048 -> 512,可以理解為對每個\(x_i\)進行兩次線性映射,也可以對整個序列進行1×1卷積。
Multi-Head Attention
原始的attention就是一個query(Q)和一組key(K)算相似度,然后對一組value(V)做加權和。假如每個Q和K都是512維的向量,就相當于在512維的空間里比較兩個向量的相似度。而Multi-Head相當于加過于512維的空間人為拆分為多個子空間,如head number=8就是將高維空間拆分為8個子空間,相應地V也要分為8個head,然后在這8個子空間中分別計算Q和K的相似度,再組合V。這樣能使attention從不同角度捕獲序列關系。
編碼器
\[ sub\_layer\_output=LayerNorm(x+SubLayer(x))\\ head_i=Attention(QW_i^Q,KW_i^K,VW_i^K)\\ MultiHead(Q,K,V)=concat(head_1,head_2,...,head_h)W^O \]
self-attention時,Q、K、V相同解碼器
輸入:編碼器的輸出 & 對應i-1時刻的解碼器輸出(i-1步的hidden state和i-1步的輸出)
注意:在解碼器中間的attention不是self-attention,其K、V來自編碼器,Q來自上一時刻的解碼器輸出
輸出:i時刻的輸出詞的概率分布
解碼:編碼可以并行,一次性全部編碼出來(在編碼時,各個計算互不依賴)。但解碼不是一次把所有序列解出來,而是如同RNN一樣,一個一個解出來,因為要用到上一解碼步的隱狀態作為attention的query。解碼器端最先的Multi-Head是Masked,這是因為訓練時輸入是ground truth,這樣確保預測第i個位置時,遮蔽掉該位置及其之后的信息,不會接觸未來的信息。
Transformer優缺點
優點
并行計算,這主要體現在編解碼器都放棄了RNN,下一個時間步的計算不必等待之前的計算完全展開
直接的長距離依賴
原來的RNN中,第一幀要和第十幀發生關系,必須通過第二~九幀傳遞,進而產生兩者的計算。而在這個過程中,第一幀的信息有可能已經產生了偏差,準確性和速度都難以保證。在Transformer中,由于self-attention的存在,任意兩幀都有直接的交互,建立直接依賴。
缺點
仍然是自回歸模型,任意一幀的輸出都依賴于它之前的所有輸出。比如輸入abc,本次的輸出實際是bcd,每輸入一個序列,其實序列的末端都只是前進了一幀,因此要生成abcdefg仍然要循環6次。
轉載于:https://www.cnblogs.com/mengnan/p/9871665.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的seq2seq和Transformer的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js数组随机排序
- 下一篇: centos 7 Chrony 集群同步