【算法】Attention is all you need


Transformer

最近看了Attention Is All You Need這篇經典論文。論文里有很多地方描述都很模糊,后來是看了參考文獻里其他人的源碼分析文章才算是打通整個流程。記錄一下。

Transformer整體結構

數據流梳理

符號含義速查

N: batch size
T: 一個句子的長度
E: embedding size
C: attention_size(num_units)
h: 多頭header的數量

1. 訓練

1.1 輸入數據預處理

翻譯前文本,翻譯后文本,做長度截斷或填充處理,使得所有語句長度都固定為T。
獲取翻譯前后語言的詞庫,對少出現詞做剔除處理,詞庫添加< PAD >, < UNK >, < Start >, < End >四個特殊字符。
翻譯前后文本根據詞庫,將文本轉為id。
設batch_size=N, 則轉換后翻譯前后數據的size為:X=(N, T), Y=(N, T)

1.2 Encoder

前面結構圖中Encoder的輸入Inputs就是1.1中轉換好的X。

1.2.1 Input Embedding
設輸入詞庫大小為vocab_in_size, embedding的維度為E,則先隨機初始化一個(vocab_in_size, E)大小的矩陣,根據embedding矩陣將X轉換為(N, T, E)大小的矩陣。

1.2.2 Positional encoding
Position embedding矩陣維度也是(N,T,E),不同batch上,在T維度上相同位置的值一樣。論文里用了三角函數sin和cos。
將Position embedding直接疊加到1.2.1的X上就是送入multi-head attention的輸入了。

1.2.3 Multi-Head Attention

線性變換
將輸入X=(N,T,E)通過線性變換,將特征維度轉換為C。經過轉換維度為X=(N,T,C)。

轉為多頭
沿特征方向平分為h份,在batch維度上拼接,方便后面計算。轉換后維度X=(h*N, T, C/h)

計算\(QK^T\)
這里query(Q)和key(K)都是前面的X,計算后維度out=(h*N,T,T)

Mask Key
將out矩陣中key方向上原始key信息為0的部分mask掉,另其為一個極大的負數。所謂信息為0是指文本中PAD的部分。最開始會將PAD的embedding設為全0矩陣。
Softmax
把上一步的輸入做softmax操作,變為歸一化權值。維度(h*N,T,T)

Mask Query
把query部分信息量為0對應的維度置0。即這一部分的權重為0。信息量為0同樣指PAD。

乘以value
self attention的value也就是上面的X(h*N, T, C/h),相乘后維度=(h*N, T, C/h)

reshape
將多頭的部分恢復原來的維度,處理后維度out=(N, T, C)

1.2.4 Add & Norm
殘差操作,out = out+X 維度(N, T, C)
layer norm歸一化,維度(N, T, C)

多個block
上面1.2.3和1.2.4操作重復多次,最后一層的輸出就是Encoder的最終輸出。記為Enc。

1.3 Decoder

這里大部分跟前面Encoder是一樣的。前面結構圖中Decoder的輸入Outputs就是1.1中轉換好的Y。

1.3.1 output Embedding
設輸入詞庫大小為vocab_out_size, embedding的維度為E,則先隨機初始化一個(vocab_out_size, E)大小的矩陣,根據embedding矩陣將Y轉換為(N, T, E)大小的矩陣。

1.3.2 Positional encoding
見1.2.2

1.3.3 Masked Multi-Head Attention
跟1.2.3基本相同,只是多了一個Mask步驟

線性變換
將輸入Y=(N,T,E)通過線性變換,將特征維度轉換為C。經過轉換維度為Y=(N,T,C)。

轉為多頭
沿特征方向平分為h份,在batch維度上拼接,方便后面計算。轉換后維度Y=(h*N, T, C/h)

計算\(QK^T\)
這里query(Q)和key(K)都是前面的Y,計算后維度out=(h*N,T,T)

Mask Key
將out矩陣中key方向上原始key信息為0的部分mask掉,另其為一個極大的負數。所謂信息為0是指文本中PAD的部分。最開始會將PAD的embedding設為全0矩陣。

Mask當前詞之后的詞
做這一步的原因是在解碼位置i的詞時,我們只知道位置0到i-1的信息,並不知道后面的信息。處理方式是將T_k>T_q部分置為一個極大的負數。T_k表示key方向維度,T_q表示query方向維度。

Softmax
把上一步的輸入做softmax操作,變為歸一化權值。維度(h*N,T,T)

Mask Query
把query部分信息量為0對應的維度置0。即這一部分的權重為0。信息量為0同樣指PAD。

乘以value
self attention的value也就是上面的X(h*N, T, C/h),相乘后維度=(h*N, T, C/h)

reshape
將多頭的部分恢復原來的維度,處理后維度out=(N, T, C)

1.3.4 Add & Norm
殘差操作,out = out+X 維度(N, T, C)
layer norm歸一化,維度(N, T, C)

1.3.5 Multi-Head Attention
跟之前的區別在於,以前是self attention,這里query是上面decode的輸出dec, key是encoder的輸出enc

轉為多頭
將dec沿特征方向平分為h份,在batch維度上拼接,方便后面計算。轉換后維度dec=(h*N, T, C/h)

計算\(QK^T\)
這里query(Q)=dec和key(K)=enc,計算后維度out=(h*N,T_q,T_k)

Mask Key
將out矩陣中key方向上原始key信息為0的部分mask掉,另其為一個極大的負數。所謂信息為0是指文本中PAD的部分。最開始會將PAD的embedding設為全0矩陣。
Softmax
把上一步的輸入做softmax操作,變為歸一化權值。維度(h*N,T_q,T_k)

Mask Query
把query部分信息量為0對應的維度置0。即這一部分的權重為0。信息量為0同樣指PAD。

乘以value
self attention的value也就是上面的enc(h*N, T, C/h),相乘后維度=(h*N, T_q, C/h)

reshape
將多頭的部分恢復原來的維度,處理后維度out=(N, T_q, C)

1.3.6 Add & Norm
殘差操作,out = out+dec 維度(N, T_q, C)
layer norm歸一化,維度(N, T_q, C)

多個block
上面1.3.3-1.3.6重復多次

全連接變換
將上面輸出結果(N, T_q, C)轉換為(N, T_q, vocab_out_size)維,softmax獲取每個位置輸出各個詞的概率。通過優化算法迭代更新參數。

2. 測試

測試時的Encoder部分比較好理解,跟訓練時處理一樣。只不過參數都是訓練好的,比如embedding矩陣直接使用前面訓練好的矩陣。
主要問題是在decoder的輸入上。
對於一個語句,decoder一開始輸入全0序列。表示什么信息也不知道(或者一個Start標簽,表示開始)。經過一次decoder后輸出一個長度為T的預測序列out1
第二次,輸入out1預測的第一個字符,后面是全0,表示知道一個詞了。經過decoder處理后,獲得長度為T的輸出預測序列out2
第三次,輸入out2預測的前兩個字符,后面是全0,表示知道2個詞了。
依次類推。
注意,訓練時decode結果是一次性獲取的。但是測試的時候一次只獲取一個詞。需要類似RNN一樣循環多次。

對於Position Embedding的理解

有些詞顛倒一下順序,含義是會變化的。
比如:奶牛 -> dairy cattle
如果沒有添加位置信息,顛倒后會翻譯成 牛奶 -> cattle dairy。
但這顯然是不對的,在顛倒順序后詞的含義改變了, 應該翻譯為 milk。
為了處理這種問題,所以需要加入位置信息。

參考文獻

  1. https://blog.csdn.net/mijiaoxiaosan/article/details/74909076
  2. https://github.com/Kyubyong/transformer
  3. 《Attention Is All You Need》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM