# Transformer Note :::info 非文本內容的補充格式: 寫在文本翻譯之前 - 專有名詞、概念 1 [link](#) (此link for 大概念) - 敘述 1 [link](#)(此link for 單一概念) - 敘述 2 - 專有名詞、概念 2 [link](#) - 敘述 1 - ... ::: :::danger 有看不懂、有疑義的地方,請用 "::: danger" ":::" 包住,如此段 ::: ## 1 Introduction :::spoiler 補充 - short-term memory - 對於單一份data(example),可以記得序列前面的內容 - long-term memory - 可以記得不同份data內的內容(accross example) - 注意力機制 [link](https://medium.com/programming-with-data/28-%E6%B3%A8%E6%84%8F%E5%8A%9B%E6%A9%9F%E5%88%B6-attention-mechanism-f3937f289023) - 然後根據symbol向量與Question向量的相關度(點積值等等),決定與該symbol的權重 - 再把每個symbol的向量做加權相加(有時候會再除以向量數做平均)(避免RNN的位置問題,只與相關度有關) - RNN - ![image](https://hackmd.io/_uploads/SJappRSyA.png) ::: RNN跟GRU(優化記憶方式的RNN)已經有很大的發展,他們通常根據symbol位置來分解資料成sequence,用這種序列化的方式做輸入輸出 但這種方式因為不支援平行的輸入輸出,所以對於long-term memory很難有好表現(越遠的context權重越低,類似股票的KD線吧) 注意力機制可以不管資料在sequence中的位置 然而注意力機制通常仍是跟RNN一起使用(輸入或許有用到注意力,但輸出仍是遞迴方式考慮前一個輸出值)(所以transformer最大的改變,就是multihead且連輸出也用注意力) 這篇paper提出的Transformer避免使用像RNN的遞迴方式,也避免使用CNN的卷積方式,而是完全依賴注意力機制,可以達到更好的平行運算,也可以減少大量的訓練時間。 本篇paper的兩組翻譯實驗都有顯著的結果。 Transformer 能夠在僅僅使用八塊 P100 GPU ,且訓練 12 個小時的情況下就能達到翻譯質量的最新技術水平。 ## 2 Background 為了減少序列運算(避免遠處被忽略),有很多模型(見論文)被提出,但是這些模型還是會受到signal距離(N)的限制,運算量少到O(N),O(log(N))有少但不多 Transformer則可以直接把他變成O(1)的常數,雖然會因為平均注意力權重降低resolution效率就是了,但這問題在3.2會提到怎麼解決 自注意力(Self-attention)是對於sequence中的signal距離的注意力機制。 目前自注意力有成功被運用的例子有: * 閱讀理解 * 抽象摘要 Abstractive summarization * 文本蘊涵 * 學習與任務無關的句子表示 * ![image](https://hackmd.io/_uploads/H1V4EsL1C.png) 端到端記憶網路End-to-end memory networks(包含encode, memory, decoder)是基於遞迴注意力機制(把很多注意力機制疊在一起),而非序列遞迴(RNN那個)。在簡單語言問答和語言建模任務上都有良好的表現。 Transformer是第一個完全依賴注意來計算其輸入和輸出表示的轉換模型。 ## 3 Model Architecture :::spoiler 補充 - point-wise(逐點) - 一次只處理一個point,不與其他point相關 - 也可以指用1 * 1卷積核 ::: Encoder將符號表示的輸入序列(x1,…,xn)(離散的,ex: 字母)映射到連續表示的序列 z = (z1,…,zn)(映射到向量空間,所以連續) 給定 z,Decoder隨後生成一次生成一個符號的輸出序列(y1,…,ym)。 每一步,Transformer都是自我回歸的,也就是在生成下一個符號時,它會使用先前生成的符號作為additional input。 Transformer使用堆疊式(stacked)的自我注意力機制和point-wise的全連接層來遵循這種整體架構 ### 3.1 Encoder and Decoder Stacks :::spoiler 補充 - residual connection(殘差連接) [link](https://blog.csdn.net/weixin_42253689/article/details/110450298) - 假設一個layer輸入x輸出H(x), x -> H(x) - Residual殘差: F(x) = H(x) - x, 也就是輸出與輸入的差異 - 殘差連接的重點在於,H(x) = F(x) + x,讓layer學習到的東西是F(x),也就是學習殘差,然後再透過skip connection把輸入值x加回去 - 這是用來避免多層數下,梯度消失、梯度爆炸、網路退化的問題(詳見link) ::: ![image](https://hackmd.io/_uploads/SJWeVEJk0.png =70%x) #### Encoder: 左邊的部分,由N=6個identical layer疊在一起組成(stacked),每個區塊包含2個sublayer,一個multi-head self-attention layer(後面會講),一個point-wise全連接層(圖上的Feed Forward) 在sublayer之間有一個residual connection,為了讓殘差可以順利加上去,網路的輸入輸出都會固定在$d_{model}=512$的維度 Residual connection後還有layer normalization。這樣每一層sublayer的輸出會是 $LayerNorm(x+Sublayer(x))$ * $Sublayer(x)$ 是下一層(sublayer)使用的函數 $LayerNorm$就是把數字標準化,讓他服從常態分佈((x-mean)/SD) #### Decoder: 右邊的部分,也是N=6個identical layer,但是有三個sublayer。基本上跟左邊只差在第二sublayer(中間那個),跟第一層的一些 第二個sublayer,一樣是multi-head self-attention,不過吃了encoder的輸出作為輸入。 第一層則是把multi-head self-attention改成masked multi-head self-attention,其實就是讓輸出的位置移動1格,保證第i個只會參照<i的位置 ### 3.2 Attention Attention function是以query, set of pair(key,value)為參數,映射到output的函數 基本上是一種用於準確評估輸入序列的不同部分對於全局(global context)的重要性的一種機制 其中出現的變數都是向量 其中output的計算是藉由value乘上weight,而weight是由對應的key跟query算出來的 基本上就是用來計算query跟value關聯度,並給與加權的函數 可以讓計算時,相關度越高的signal(ex: 跟問題更相關的字詞),能有更高的權重 #### 3.2.1 Scaled Dot-Product Attention input: keys: ${d_k}$, querys: ${d_k}$, values: ${d_v}$代表著輸入進去的key, query, value的總量 這個算式的關鍵在於,拿k跟q向量做點積,求其在向量空間的相關度,再除以$\sqrt{d_k}$(有點像是取平均的概念,因為矩陣相乘會導致數值被放大),然後丟進softmax變成0~1,再做為value的權重 在實務上,key跟value很常是同個東西(以字詞來說,value本身就是字詞映射到向量空間的向量,本來就可以拿來直接點積求相關度) 基本上計算時,會平行進行計算,所以會把向量放在一起變成矩陣Q,K,V $K \in R^{tokens*d_k}$, $Q \in R^{tokens*d_k}$, $V \in R^{tokens*d_v}$ ![image](https://hackmd.io/_uploads/Sku27-lJC.png) 算式中,對於KQ做dot-product,利用他們在向量空間的的角度,來求他們的相似度 這裡的software對於矩陣中每個element做,出來的還是矩陣 soft-max得出的會是一個$R^{d_k * d_k}$的矩陣 ($d_{model}$即文字轉成向量的維度) :::info 所以這樣的計算結果下,$d_k$一定要等於$d_v$才能做計算??? 解決了,作者Ch6有提,如果不同的話,就不能用點積,而要用其他的更複雜的function,還有提到,讓他不同的話,效果會比較差 ::: 常用的attention function: addititive與dot-product,dot-product是相對適合的,因為dot-product可以用矩陣方式來加速,但是additive不行,在實務上會更慢 而再{d_k}小的情況,additive跟dot-product的效果差不多,但{d_k}一大,additive就會明顯較好,可能是因為dot-product再高維度會加得太快,所以作者引入了$/\sqrt{d_K}$來減緩這問題 ![image](https://hackmd.io/_uploads/SJrMytgyA.png) #### 3.2.2 Multi-Head Attention 比起把向量的維度全部設成$d_{model}$,作者發現經過線性投影(乘上一個權重,然後降維)之後會更好 作者對於向量做h次處理,每次稱為一個head 處理中,用學習過的線性投影(權重$W_i$來自於學習)成$d_k, d_v$會更好,接著,這些投影過後的向量,會輸出$d_v$的output,這樣 然後再把輸出串聯起來(concat),做最後一次線性投影,就會得到$維度d_{model}$的最終值 計算式如下: ![image](https://hackmd.io/_uploads/S1tYYV-kA.png) 每個head都是一個attention function,裡面包了乘上權重的三個向量矩陣 透過維度,可以看出,concat的方式,是把h個head($R^{d_v*d_v}$)橫向接起來,變成一個大的$R^{d_v*hd_v}$的矩陣,再去做最後一次線性投影成model中標準化的輸入輸出維度$d_{model}$ 論文使用了h=8個(h是超參數)平行attention layer(亦可稱為heads)。每一個head,使用了$d_k=d_v=\dfrac{d_{model}}{h}=64$ 因為每一個head的維度縮減,所以最後總運算時間(時間複雜度)和只使用一個head(也就是h=1)且完整維度的一樣,並且這h次會進行平行運算,可以讓運算效率比起直接算單個$d_{model}$head還高。 ![image](https://hackmd.io/_uploads/r1kE1KxyC.png) :::info 更正,這裡的W應該就是後面梯度下降要去學習的東西了 ::: #### 3.2.3 Applications of Attention in our Model Transformer有三種不同的使用Multi-head attention方式: ![image](https://hackmd.io/_uploads/SJWeVEJk0.png =70%x) 1. 在編碼器-解碼器注意力層(Encoder-Decoder Attention Layer): * decoder中的第二層 * 查詢(queries)來自前一個decoder layer * 記憶鍵(memory keys)和值(values)來自encoder的輸出 * 這使得解碼器中的每個位置都可以關注輸入序列中的所有位置 * 這模仿了序列到序列模型中的典型編碼器-解碼器注意力機制 3. 在編碼器中的自我注意力層: * 在自我注意力層中,所有的鍵、值和查詢都來自相同位置,也就是encoder中的前一層的輸出 * Encoder中的每個位置都可以關注(attend to)encoder輸入中的所有位置,讓輸出是參考過前後文的結果 * 主要目的是讓Decoder得到的輸入,每個位置其實都包含了全局的訊息 5. 在解碼器中的自我注意力層: * 自我注意力層允許decoder中的每個位置關注decoder中包括該位置在內的所有位置,讓輸出是參考過前後文的結果(對於第一個decoder部件可能沒啥用,但對於後面2~6個就會有很大用處) * 需要防止deocder中的左向信息流(sequence中,較後面(右)的資訊被較前面(左)的資訊使用到),以保持自回歸特性(auto-regressive property) * 論文的實作方式是:通過點積注意力遮罩(把不合法(左向資訊)的值改掉,將其設置為-∞) * ![image](https://hackmd.io/_uploads/S1dnqDZJC.png) ### 3.3 Position-wise Feed-Forward Networks 逐點的全連接層,可以看做1 * 1捲積核的捲積層 ![image](https://hackmd.io/_uploads/HkDE_sfyC.png) max(0,...)即ReLU,所以可以看出,全連接層做的事是,線性變換->ReLU->線性變換 算式中可以看到分成$W_1$, $W_2$,也就是不同的線性變化會有不同的參數,帶來不一樣的學習成果(feature channel中不同的部分會被強調出來) 然後兩次線性變換(全連接層裡的兩層)用的kneral數不同,第一層用2048個kernel,所以會輸出feature channel 2048的向量,第二層則是用512個kernel,輸出512 feature channel的向量 所以過程會是512(input) -> 2048 -> 512(output),保持了整個model都在$d_{model}$的維度 ### 3.4 Embeddings and Softmax [參考link](https://zhuanlan.zhihu.com/p/372279569) Embedding基本上,就是把資料變成可以輸入的向量,那一般來講方法會是讓字詞向量乘上一個學習過後的權重矩陣(就一般NLP那套) 在輸出成字詞的機率時,作者用的權重矩陣也是一樣的 基本上,這部分都是拿現成的東西來用,不過作者把那個現成的矩陣乘上了$\sqrt{d_{model}}$(蛤,這是為啥) :::danger 乘上$\sqrt{d_{model}}$是為了可以和Positional Encoding 後的向量做相加嗎? 乘了$\sqrt{d_{model}}$之後,值也會介於-1和1之間 ::: ### 3.5 Positional Encoding model內沒有遞迴(RNN那套)或捲積的概念,只有用注意力機制找字詞相關性,但是輸入之間的位置關係還是很重要的(像文章在同個段落內的內容,會比較有相關性) 所以在輸入時,作者使用了positional encoding [參考link](https://zhuanlan.zhihu.com/p/372279569) ![image](https://hackmd.io/_uploads/BypPHhzJA.png) 透過不同週期的sin, cos,來確保不同的位置,在所有維度上,都不會有相同值,也就因此納入了位置的訊息 ![image](https://hackmd.io/_uploads/r1Wtwnfy0.png) 這個positional encoding得到的值,是直接加在向量上的 作者也試過,用學習的方式來做positional encoding 不過發現,用function做跟用學習做得到的結果差不太多,所以選用了function,就可以適應更長的sequence 在輸入的資料,帶有位置的資訊之後,model就會自己去學習出他們的關係了 ## 4 Why Self-Attention 這章主要比較Self-Attention與recurrent、convolution方法之間,在對於sequence轉換的差別 比較的點有: 1. 每層的運算複雜度 2 可平行運算的數量(即找最少的序列運算) 3 long range depency的path length(即位置很遠時,要把它納入考量,需要的資源) 第3點是當時,其他sequence transduction模型最大的挑戰 以下是不同模型間的比較 ![image](https://hackmd.io/_uploads/SJWfT6GyC.png) Self-Attnetion(restrict)是只看附近r個position的資料,被限制後的模型 可以降低每層的運算量,但相對path len就會變長 除了這些,self-attention的可解釋性更高,可以看出不同的head學會了不同的任務,並且對於文句的文法、語意結構有有做出相關行為 剩下的不是很重要 ## 5 Training ### 5.1 Training Data and Batching WMT 2014 English-German dataset WMT 2014 English-French dataset ### 5.2 Hardware and Schedule one machine with 8 NVIDIA P100 GPUs 基本的model(用論文中提到的參數): each training step(一個batch做完): 0.4s train for 100,000 steps or 12 hours 大型model: each training step(一個batch做完): 1s train for 300,000 steps or 3.5 days ![image](https://hackmd.io/_uploads/rJXyWeVJC.png) ![image](https://hackmd.io/_uploads/HkKClgEyA.png) ### 5.3 Optimizer [關於各種optomizer](https://medium.com/%E9%9B%9E%E9%9B%9E%E8%88%87%E5%85%94%E5%85%94%E7%9A%84%E5%B7%A5%E7%A8%8B%E4%B8%96%E7%95%8C/%E6%A9%9F%E5%99%A8%E5%AD%B8%E7%BF%92ml-note-sgd-momentum-adagrad-adam-optimizer-f20568c968db) 使用adam optomizer(會自動調整學習率,並參考以前變化的向量的梯度下降) 以下是超參數($\beta_1, \beta_2, \epsilon, warmup_step$),以及學習率設定的數據 ![image](https://hackmd.io/_uploads/BJoXMgEJ0.png) 學習率會先漸升再漸降,受warmup決定學習率的波型 :::danger 為什麼需要乘-0.5次方和-1.5次方? by YouZhe: 我感覺這只是他們嘗試出來,結果比較好的,不然這個數字感覺不太能用數學去解釋 ::: ### 5.4 Regularization 每個sublayer都有加上dropout(殘差連接之後,normalization之前) enbedding跟positional encoding之後也有加上dropout 機率是$P_{dropout} = 0.1$ ## 6 Results ### 6.1 Machine Translation 總之就是自賣自誇環節,在WMT 2014 English-to-German translation task第一名 ### 6.2 Model Variations 在講調不同參數的結果,基本上就是圖呈現的(以英翻德為例) ![image](https://hackmd.io/_uploads/r10QUlVJA.png) [link](https://blog.csdn.net/vivi_cin/article/details/134808955) BLEU(bilingual evaluation understudy): 越接近大代表翻譯的越好,基於Precision,也就是輸出中,正確結果比重越高越好(越少錯辭、冗言贅字) 公式: ![image](https://hackmd.io/_uploads/HJEzOlEyR.png) [link](https://medium.com/nlp-tsupei/perplexity%E6%98%AF%E4%BB%80%E9%BA%BC-426f52897513) PPL(Perplexity): 困惑度,越小越好,代表對於model輸出結果的信心(機率多高),公式中的$l$其實就是cross-entropy function(把機率視為平等後的結果) 公式: ![image](https://hackmd.io/_uploads/HkN5uxEyC.png) ## 7 Conclusion 在翻譯方面,Transformer的訓練速度比基於循環或卷積層的架構要快得多。 在WMT 2014英德翻譯和WMT 2014英法翻譯任務中,Transformer都取得了新的技術水平。 作者打算將Transformer擴展到涉及文本以外的輸入和輸出模式的問題,並研究局部、受限的注意機制,以有效處理諸如圖像、音頻和視頻之類的大型輸入和輸出。 使生成變得不那麼順序化是他們的另一個研究目標。