---
# System prepended metadata

title: Transformer
tags: [論文筆記]

---

論文: [Attention Is All You Need](https://arxiv.org/abs/1706.03762)


## N-to-N Problem
大部分處理的資料都是一組向量（一張影像）對應到一個數值或類別的輸出；假設輸出不變，但輸入變成一排向量（一段聲音、一部影片、一個句子）呢? 例如: 處理一個句子，可以將每個詞轉為一個 One-hot encoding 向量，再去做 Word embedding；也有可能是一段聲音，透過 Sliding window 將固定長度訊號轉換為可用特徵（MFCC、SFFT...等）。

<div class="text-center">
    <img src="https://hackmd.io/_uploads/S1qbcCvUR.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/H1dzcAP8R.png" style="width: 355px; object-fit: cover;">
</div>

&nbsp;
在實際應用上可以分為
* N 排向量、N 個數值 / 類別
    * POS tagging: 輸入是一個詞向量、輸出是詞性
    * 異常偵測: 輸入是固定長度聲音訊號、輸出是類別或分數
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rJcHpCDLR.png" style="width: 480px; object-fit: cover;">
    </div>
* N 排向量、一個數值 / 類別
    * 語意分析: 輸入是一個句子（多個詞向量）、輸出是類別
    * 語者辨認: 輸入是一段聲音（多個固定長度聲音訊號）、輸出是類別
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rJxO6CvUC.png" style="width: 480px; object-fit: cover;">
    </div>
* N 排向量、M 排向量（Sequence to sequence）
    * 序列生成、機器翻譯: 輸入是一個句子、輸出是一個句子
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/BJNZ11_L0.png" style="width: 480px; object-fit: cover;">
    </div>

首先，著重在第一類 N-to-N 的問題，假設要處理 Sequence labeling，每一個詞向量都對應到一個標籤，可以透過 FC layer 搭配窗格考慮上下文的關係；然而，若想要考慮不僅僅是上下文，而是整個 Sequence，如果此時仍然使用 FC layer 去處理，必須將 Window size 開得很大，導致需要學習的參數量很多，容易造成 Overfitting:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HJoObJOI0.png" style="width: 600px; object-fit: cover;">
</div>


## Attention Mechanism
為了讓模型能夠考慮到上下文，注意力機制想在做的事情就是==先以 Self-attention 來處理全局資訊，此時每一排輸入向量依然會對應到一排輸出向量，接著再用 FC layer 對輸出向量再做一次局部資訊處理==，如左下圖所示，也可以疊多個 Self-attention 去處理資訊，如右下圖所示:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rkwZmkdLR.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/HJdFQkOUA.png" style="width: 355px; object-fit: cover;">
</div>

&nbsp;
==Attention block 實際在做的事情就是將每一排向量和其他排向量產生關聯==，舉例來說，$b^1$ 是考慮了 $a^1,a^2,a^3,a^4$ 所產生的，其中，$b^1$ 是如何產生的?

1. 根據 $a^1$，在很長的 Sequence 中找出和它相關的向量，並且計算一個分數 $\alpha$，用這個分數來決定哪些詞向量與 $a^1$ 強相關
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HyF5zbOLA.png" style="width: 480px; object-fit: cover;">
    </div>
    
    其中，計算分數的方式有二種: 點乘（Dot product）和點加（Additive）
    * 點乘: $\alpha=q \cdot k=(W^q a^q) \cdot (W^k a^k)$
    * 點加: $\alpha=W \cdot tanh(q+k)=W \cdot tanh(W^q a^q+W^k a^k)$
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SksGmWOU0.png" style="width: 480px; object-fit: cover;">
    </div>
    
2. 更詳細來說，我們會稱 Query $=a^1$、Key $=a^2,a^3,a^4$；Query 會和自己，以及所有的 Key 都計算一個分數，再經過 Softmax 輸出 Attention score:

    \begin{gathered}
    a_{1,1}=q^1 \cdot k^1 \\
    a_{1,2}=q^1 \cdot k^2 \\
    a_{1,3}=q^1 \cdot k^3 \\
    a_{1,4}=q^1 \cdot k^4 \\ a_{1,1}^\prime,a_{1,2}^\prime,a_{1,3}^\prime,a_{1,4}^\prime=softmax(a_{1,1},a_{1,2},a_{1,3},a_{1,4})
    \end{gathered}

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HJT-NbOL0.png" style="width: 480px; object-fit: cover;">
        <img src="https://hackmd.io/_uploads/r1mdVbuIC.png" style="width: 480px; object-fit: cover;">
    </div>

3. 最後，每一排詞向量都還會和各別矩陣相乘得到 Value，再由剛才計算出的分數來給予權重、分配資訊重要性，因此分數越高者，和 $a^1$ 的關聯性就會由它的向量來主導

    \begin{gathered}
    b^1=a_{1,1}^\prime v^1+a_{1,2}^\prime v^2+a_{1,3}^\prime v^3+a_{1,4}^\prime v^4
    \end{gathered}

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rJlEB-u8R.png" style="width: 480px; object-fit: cover;">
    </div>

其中，$b^1$ 到 $b^4$ 並不需要依序產生，是可以一次同時做計算:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/SJyfOE5LC.png" style="width: 600px; object-fit: cover;">
</div>
    
假設我們由 $q,k,v$ 三組向量的計算角度出發，$q^i=W^q a^i$ 其實都是共用一組 $W^q$，那麼矩陣運算可排列如下:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HJ6Wkrq8C.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/SJkhyrqIR.png" style="width: 355px; object-fit: cover;">
</div>

同理，$k^i=W^k a^i$、$v^i=W^v a^i$ 也都可以矩陣表示如下:

\begin{gathered}
\ [q^1~q^2~q^3~q^4]=W^q[a^1~a^2~a^3~a^4] \rightarrow Q=W^q I \\
\ [q^1~q^2~q^3~q^4]=W^k[a^1~a^2~a^3~a^4] \rightarrow K=W^k I \\
\ [q^1~q^2~q^3~q^4]=W^v[a^1~a^2~a^3~a^4] \rightarrow V=W^v I
\end{gathered}

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BJyEmS5IC.png" style="width: 600px; object-fit: cover;">
</div>

分數的部分，也可以將 $k^1,k^2,k^3,k^4$ 拼成一個矩陣，乘上 $q^1$ 向量去做計算:

\begin{gathered}
    \begin{bmatrix} 
    a_{1,1} \\ 
    a_{1,2} \\
    a_{1,3} \\
    a_{1,4}
    \end{bmatrix}=
    \begin{bmatrix} 
    k^1 \\ 
    k^2 \\
    k^3 \\
    k^4
    \end{bmatrix} q^1
\end{gathered}

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HkPQEH5IR.png" style="width: 600px; object-fit: cover;">
</div>

除了 $q^1$ 外，$q^2,q^3,q^4$ 也都要計算，讓他們排排站相乘後，就可以得到一個 Attention score 的矩陣；其中，不一定是取 $softmax(‧)$，其餘 Activation function 也都可以:

\begin{gathered}
    A^\prime=\begin{bmatrix} 
    a_{1,1}^\prime~~ a_{2,1}^\prime~~ a_{3,1}^\prime~~ a_{4,1}^\prime \\
    a_{1,2}^\prime~~ a_{2,2}^\prime~~ a_{3,2}^\prime~~ a_{4,2}^\prime \\
    a_{1,3}^\prime~~ a_{2,3}^\prime~~ a_{3,3}^\prime~~ a_{4,3}^\prime \\
    a_{1,4}^\prime~~ a_{2,4}^\prime~~ a_{3,4}^\prime~~ a_{4,4}^\prime
    \end{bmatrix} \xleftarrow{softmax}
    A=
    \begin{bmatrix} 
    a_{1,1}~~ a_{2,1}~~ a_{3,1}~~ a_{4,1} \\
    a_{1,2}~~ a_{2,2}~~ a_{3,2}~~ a_{4,2} \\
    a_{1,3}~~ a_{2,3}~~ a_{3,3}~~ a_{4,3} \\
    a_{1,4}~~ a_{2,4}~~ a_{3,4}~~ a_{4,4}
    \end{bmatrix}=
    \begin{bmatrix} 
    k^1 \\ 
    k^2 \\
    k^3 \\
    k^4
    \end{bmatrix} [q^1~q^2~q^3~q^4]
\end{gathered}

<div class="text-center">
    <img src="https://hackmd.io/_uploads/ByNxLHqI0.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/B1f6SH5U0.png" style="width: 355px; object-fit: cover;">
</div>

&nbsp;
最後，根據 Attention score 去分配 $v^i$ 的權重並輸出:

\begin{equation}
    \begin{cases}
    b^1=a_{1,1}^\prime v^1+a_{1,2}^\prime v^2+a_{1,3}^\prime v^3+a_{1,4}^\prime v^4 \\
    b^2=a_{2,1}^\prime v^1+a_{2,2}^\prime v^2+a_{2,3}^\prime v^3+a_{2,4}^\prime v^4 \\
    b^3=a_{3,1}^\prime v^1+a_{3,2}^\prime v^2+a_{3,3}^\prime v^3+a_{3,4}^\prime v^4 \\
    b^4=a_{4,1}^\prime v^1+a_{4,2}^\prime v^2+a_{4,3}^\prime v^3+a_{4,4}^\prime v^4
    \end{cases} \rightarrow
    O=
    \begin{array}
    \ [b^1~b^2~b^3~b^4]=[v^1~v^2~v^3~v^4]
        \begin{bmatrix} 
        a_{1,1}^\prime~~ a_{2,1}^\prime~~ a_{3,1}^\prime~~ a_{4,1}^\prime \\
        a_{1,2}^\prime~~ a_{2,2}^\prime~~ a_{3,2}^\prime~~ a_{4,2}^\prime \\
        a_{1,3}^\prime~~ a_{2,3}^\prime~~ a_{3,3}^\prime~~ a_{4,3}^\prime \\
        a_{1,4}^\prime~~ a_{2,4}^\prime~~ a_{3,4}^\prime~~ a_{4,4}^\prime
        \end{bmatrix}
    \end{array}
\end{equation}

<div class="text-center">
    <img src="https://hackmd.io/_uploads/SkDRhSq8R.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/Hkk-aHcUR.png" style="width: 355px; object-fit: cover;">
</div>

&nbsp;
整體矩陣運算流程如下圖，其中真正要訓練的只有權重矩陣 $W^q,W^k,W^v$:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rkWgD89IA.png" style="width: 600px; object-fit: cover;">
</div>


## Multihead Attention
上述介紹的都是單一 Head，通常在翻譯或語音辨識領域，多頭注意力機制會有比較好的表現，可以視為多個 $q$ 代表著多個種類的相關性計算，而要有幾個 Head 則是可以調整的超參數:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HkYjnNGDR.png" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
舉例來說，如果想要有二個 $q^{i,1},q^{i,2}$，則各自都會有自己的權重矩陣 $W^{q,1},W^{q,2}$，而在計算的時候，1 和 1 自己計算、2 和 2 自己計算:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rk61ANfDC.png" style="width: 355px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/rJyxANMDR.png" style="width: 355px; object-fit: cover;">
</div>

&nbsp;
而最後的輸出則是將 $b^{i,1}, b^{i,2}$ 向量排列後，乘上輸出矩陣 $W^o$ 即可:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/Sk207PGDA.png" style="width: 600px; object-fit: cover;">
</div>


## Encoder
上述為 Transformer 最主要計算的自注意力機制，而整個 Transformer 基本上是一組 Encoder 和 Decoder 的架構:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rkNxDKxW1g.png" style="width: 550px; object-fit: cover;">
</div>

&nbsp;
其實，Encoder 也可以是 CNN 或 RNN 的架構，端看藥用怎麼設計去達成上下文關聯，而 Transformer 用的是 Attention 機制:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rJ-UDFlZke.png" style="width: 550px; object-fit: cover;">
</div>

在上圖的 Encoder 中，$N\times$ 的意思代表含有多個 Attention block，每一個 Attention block 在做的事情包含以下:

* 將輸入送進 Self-attention -> 輸出 $a$
* Residual connection -> 輸出 $a+b$
* 對 $a+b$ 做 Layer normalization -> 輸出 $c$
* 將 $c$ 送進 FC layer -> 輸出 $d$
* Residual connection -> 輸出 $d+e$
* 對 $d+e$ 做 Layer normalization -> 輸出 $f$

<div class="text-center">
    <img src="https://hackmd.io/_uploads/H1FhoYeW1e.png" style="width: 550px; object-fit: cover;">
</div>

&nbsp;
再將上述的操作流程對照一下原始論文架構圖，而實際上再將輸入送進 Encoder 前還會加入 Positional encoding 讓向量間也學習到順序關係:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/r1pShFlWyl.png" style="width: 550px; object-fit: cover;">
</div>

<blockquote>
    
* Positional encoding
    Attention block 主要就是計算向量間的相似度關係，但並沒有順序或空間上的概念，因此實務上會在輸入向量 $a^i$ 前加入 $e^i$ 的位置向量，這個位置向量長度和 $a^i$ 相同，讓模型自己學習上下文之間的關聯:
    
<div class="text-center">
    <img src="https://hackmd.io/_uploads/BJdLhD6s0.png" style="width: 500px; object-fit: cover;">
</div>

* Layer normalization（平均數=0、標準差=1）
    模型中並不是使用一般的 BN，先用一般的二維資料來做說明，水平方向是不同的 Feature、垂直方向是資料筆數:
    * （藍色）BN 是針對每個 Feature，對所有資料正規化
    * （黃色）LN 是針對每筆資料，對所有 Feature 做正規化
    
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/B1Mnlh6eJl.png" style="width: 500px; object-fit: cover;">
    </div>

    而目前碰到的文字資料是屬於三維資料，水平方向是文字數量、垂直方向是資料筆數、入平面方向是不同的 Feature（每一個字詞都是一條向量）:
    * BN 是針對每個 Feature 做正規化，也就是在一個 Feature dimension 上切一個面
    * LN 是針對每筆資料做正規化，也就是在一筆資料上去切一個面

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/Sy0tM2pe1x.png" style="width: 500px; object-fit: cover;">
    </div>

    會這樣做的最主要原因是:
    * 每個句子的長度不同，通常會以最長的句子作為標準，而長度不足的地方就補零，假設今天句子長度變化較大、且又是小批量訓練的狀況下，==用 BN 算出的平均值和標準差會有明顯的震盪，有可造成訓練困難==
    * 在推論時會使用到學習的平均值和標準差，==假設今天預測的樣本是一個長度更長的句子，是在訓練上沒有看過的樣本長度，那麼訓練的平均值和標準差，在預設上就不會起到很好的效果==

    然而，在 LN 就沒有這種問題，因為訓練時是針對各別資料去做的，得到的平均值和標準差和長度的相依關係就沒那麼明顯。

* Scaled Dot-product
    實務上，在送入 Softmax 去得到 Attention score 前，還會除以 $\sqrt{(d_k)}$:
    * 樣本長度短的時候，有沒有除上這組係數沒有差別
    * 樣本長度長的時候，因為向量長度長，做點積運算後累積的值容易變得更大或更小，在 Softmax 函數終究會往二端跑，容易有 Gradient vanish 的問題

    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SkBCA3Tl1l.png" style="width: 650px; object-fit: cover;">
    </div>

</blockquote>


## Decoder - Masked Attention
接下來則是 Decoder 的部分，先再看一次架構圖:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HklAlo-Wke.png" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
假設我們將 Decoder 中間的 Multi-Head Attention 拿掉，其實 Decoder 和 Encoder 幾乎是一模一樣的結構:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BJN3loWb1g.png" style="width: 600px; object-fit: cover;">
</div> 

此外，Decoder 和 Encoder 有一個很大的差別，==在於 Encoder 的訓練是看全部的上下文去找出關聯，而常見的的 Decoder 是只看目前僅有的向量去推論下一個向量出現的機率，是有順序性的==，也就是採用 Autoregreesive 的方式。

此外，輸出的結果可以是一個單字、字母、字根或是其他組合，端看如何設計（假設是英文，輸出字母只有 26 個維度可能還行，但輸出單字可能就有趨近無限種可能）:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/ry1SPwTzkx.png" style="width: 600px; object-fit: cover;">
</div> 

除了訓練的資料外，也還會加入 BEGIN（Begin of sentence, BOS）和 END（End of sentence, EOS）這樣的 Token 去幫助模型得知開始和結束，整體訓練的狀況如下:

* 看到 [BOS]，預測 [機]
* 看到 [BOS, 機]，預測 [器]
* 看到 [BOS, 機, 器]，預測 [學]
* ...

<div class="text-center">
    <img src="https://hackmd.io/_uploads/SyDxIoZWJx.png" style="width: 320px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/Sywg8sbbyg.png" style="width: 320px; object-fit: cover;">
</div> 

&nbsp;
Decoder 看到的輸入，是自己在前一個時間點看到的輸出，==也就是 Decoder 會把自己的輸出當成接下來的輸入==，因此 Decoder 在推論時，是有可能看到錯誤的輸入，因為都是自己在前一個時間點輸出的，也就是一步錯步步錯的概念:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/HkSRSoWWkx.png" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
然而，訓練時如何讓 Decoder 按照順序去產生呢? 可以看到 Decoder 架構圖中的 Mask Multi-Head Attention，==在做前 N 個維度的輸出時，把包含 N+1 維度以後的輸出資訊都遮住==，也就是 Mask 的意思，只讓前 N 個維度的輸出和前 N 個維度做關聯:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BJN3loWb1g.png" style="width: 600px; object-fit: cover;">
</div> 

&nbsp;
也就是計算 Attetnion score 時參考的輸入向量不同，一般的 Attention 在任何階段都是參考全部的上下文，可以用到完整的 Input sequence 資訊，而 Masked attention 僅參考上文做下文的推論:

<center>
    
| | Attention | Masked attention|
| --- | --- | --- |
| $b^1$ | $[a^1,a^2,a^3,a^4]$ | $[a^1]$ |
| $b^2$ | $[a^1,a^2,a^3,a^4]$ | $[a^1,a^2]$ |
| $b^3$ | $[a^1,a^2,a^3,a^4]$ | $[a^1,a^2,a^3]$ |
| $b^4$ | $[a^1,a^2,a^3,a^4]$ | $[a^1,a^2,a^3,a^4]$ |

</center>

<div class="text-center">
    <img src="https://hackmd.io/_uploads/SyIIvsBZJg.png" style="width: 300px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/ByUUPjS-kg.png" style="width: 300px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/HkyhKoSW1g.png" style="width: 300px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/rJJ3FsrZke.png" style="width: 300px; object-fit: cover;">
</div> 

&nbsp;
上述的 Decoder 是屬於 Autoregressive（AT），也有另一種是 Non-autoregressive（NAT），它能夠一次將整個輸出都生成出來而非有順序性的生成，例如一次性吃四個 BEGIN 的 Token，再一次性得到四個輸出來組成一個 Sequence。然而，輸出的長度要如何控制呢? 要怎麼知道要輸入幾個 BEGIN 給 Decoder?
* 第一種作法，可能是另外學習一個 Predictor 吃 Encoder 的輸入，拿來預測輸出的長度
* 第二種作法，是先確認輸出長度不會大於多少，就丟這麼多 Token 給 Decoder，最後只拿 END 之前的輸出組成 Output sequence

NAT 的好處在於:
* 效率提升（平行計算）
* 能控制輸出的長度，例如想要用更少的句子去做文章摘要，將 Predictor 輸出數值除以二即可

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BksyhAcWyx.png" style="width: 600px; object-fit: cover;">
</div> 


## Decoder - Cross Attention
Cross Attention 發生在 Encoder 與 Decoder 之間。在 Decoder 在做完 Masked attention 後，會搭配 Encoder 的輸出做 Cross attention:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BkLO-1iW1l.png" style="width: 600px; object-fit: cover;">
</div> 

&nbsp;
以 AT Decoder 為例，操作步驟如下:
1. Encoder 吃一排輸入向量做 Attention 後輸出 $[a^1,a^2,a^3]$，再經過矩陣計算轉成一組 $Key$
2. Decoder 吃一個 BEGIN Token，經過 Masked attetion 和矩陣計算轉成一個 $q$
3. 拿 $q$ 和 $[k^1,k^2,k^3]$ 關聯並過 Softmax 去得到 Attention score，也就是 $[\alpha_1^\prime,\alpha_2^\prime,\alpha_3^\prime]$
4. 將 $[a^1,a^2,a^3]$ 經過矩陣計算轉成一組 $Value$
5. 依照 Attention score 去做權重得到 $v$
7. 後續會再將 $v$ 丟到一個 Fully connected network 去得到輸出

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rkJPK1oZ1x.png" style="width: 320px; object-fit: cover;">
    <img src="https://hackmd.io/_uploads/Sk8tSJsZ1g.png" style="width: 380px; object-fit: cover;">
</div>

&nbsp;
==上述步驟稱作 Cross attention，也就是 $q$ 來自 Decoder、$[k,v]$ 來自 Encoder，意即 Decoder 依照 $q$ 去 Encoder 當中抽取資訊出來==，假設 Decoder 第一步的輸出為「機」，第二步 Decoder 的輸入就會變為「BEGIN、機」，然後按照上述步驟再做 Cross attention:

<div class="text-center">
    <img src="https://hackmd.io/_uploads/rJveFyi-1x.png" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
在 Transformer 的原始設計中，Decoder 只使用了 Encoder 最後一層輸出，事實上，兩者之間的互動可以發生在不同層之間。

## Decoder - Training
Decoder 在訓練時的 Input 是吃 GT，而非自身按順序生成的前項結果，稱作是 Teacher forcing:
* 給 GT=[BOS]，輸出向量和 [機] 做 CE loss
* 給 GT=[BOS, 機]，輸出向量和 [器] 做 CE loss
* 給 GT=[BOS, 機, 器]，輸出向量和 [學] 做 CE loss
* ...

<div class="text-center">
    <img src="https://hackmd.io/_uploads/BJpD6Ppz1e.png" style="width: 600px; object-fit: cover;">
</div>

&nbsp;
然而，實際上在使用 Decoder 做推論的時候並沒有 GT 當作輸入，而是按自身順序生成的前項結果，顯然在訓練和推論上有輸入上的落差，因此在訓練時會加入一些技巧:

* Copy mechanism
    * Copy 原本輸入的一部分作為輸出，有些詞彙的出現次數不多或沒有特別意義，例如人名
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SJVpfpfXyg.png" style="width: 480px; object-fit: cover;">
    </div>

    * 或者在做文章摘要時，如何正確複製某段資訊也是很重要的事情
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/HJZAf6G7Jl.png" style="width: 480px; object-fit: cover;">
    </div>

* Guided attention
    * Attention 太過彈性，導致輸出結果不盡人意，可以加入一些限制，例如強迫 Attention 的權重峰值，落在相對應的位置
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rk6vXaz7kl.png" style="width: 480px; object-fit: cover;">
    </div>

* 修正 Decoder 產生序列輸出的方法
    * Brutal force
        * 計算所有可能輸出的機率，最後挑選機率最大的
        * 可得到最佳解，但是計算量太大，難以實現
    * Greedy
        * 只選擇當前機率最大的結果
        * 難以得到最佳解

    相較於一般 Greedy 不一定有機會找到最佳解，可以使用 Beam search 這樣的搜尋方式:
    * 保留幾個最佳的候選結果作後續計算，最後挑選機率最大的
    * 近似最佳解，計算量也可接受
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/B1q-r6Mmkl.png" style="width: 480px; object-fit: cover;">
    </div>
        
    另外，也可以使用 Sampling 的方法:
    * 根據輸出的概率，取樣得到輸出
    * 輸出帶有隨機性
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rk0zr6fmkx.png" style="width: 480px; object-fit: cover;">
    </div>
    
    其中，Beam search 和 Sampling 各有適合的應用場景，前者適合答案明確的任務，像是語音辨識或文件搜尋，而後者適合需要隨機性的任務，像是文本創作、TTS。
    
* 修改 Evaluation metric
    * 模型的訓練損失與評估，使用的是不同的衡量基準，可能造成模型優化的方向，不是以最大化 BLEU score，因此可以針對驗證集設計不同的 Evaluation 方式
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/Sk61Ppz71g.png" style="width: 480px; object-fit: cover;">
    </div>

* Exposure bias
    * 是由 Teacher forcing 中，訓練與推論不一致所產生，可以在 Teacher forcing 中加入一些雜訊（稱為 Schedule sampling）
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/SJtnDaMmkl.png" style="width: 480px; object-fit: cover;">
    </div>
    
    * Schedule sampling 的技巧最早被用於 RNN，但當用於 Transformer 時會降低其平行化的能力，因此有其他修改版本
    <div class="text-center">
        <img src="https://hackmd.io/_uploads/rytpwpMQke.png" style="width: 480px; object-fit: cover;">
    </div>


## Reference
* [Transformer论文逐段精读](https://www.youtube.com/watch?v=nzqlFIcCSWQ&ab_channel=%E8%B7%9F%E6%9D%8E%E6%B2%90%E5%AD%A6AI)
* [[課程筆記] 機器學習2021(李弘毅) L13. Transformer (下)](https://blog.csdn.net/JYLin_master/article/details/124699353)
* [【機器學習2021】Transformer (上)](https://www.youtube.com/watch?v=n9TlOhRjYoc&ab_channel=Hung-yiLee)
* [【機器學習2021】Transformer (下)](https://www.youtube.com/watch?v=N6aRv06iv2g&t=811s&ab_channel=Hung-yiLee)
* [【機器學習2021】自注意力機制 (Self-attention) (上)](https://www.youtube.com/watch?v=hYdO9CscNes&t=1375s&ab_channel=Hung-yiLee)
* [【機器學習2021】自注意力機制 (Self-attention) (下)](https://www.youtube.com/watch?v=gmsMY5kc-zw&ab_channel=Hung-yiLee)