---
# System prepended metadata

title: '第五章：自注意力機制 (Self-attention) '
tags: [機器學習]

---

# 第五章：自注意力機制 (Self-attention) 
>上課筆記
* 上課影片連結
    * ==[**自注意力機制 (Self-attention)(上)**](https://youtu.be/OP5HcXJg2Aw)==
    * ==[**自注意力機制 (Self-attention)(下)**](https://youtu.be/gmsMY5kc-zw)==

---

## 輸入：向量的集合 (Vector Set as Input)

傳統網路的輸入通常是單一向量，但許多複雜問題的輸入是**一系列的向量 (Sequence of Vectors)**，且向量的數量 (序列長度) 可能會改變。
### 例子：
*   **文字處理 (Natural Language Processing, NLP)**： 一個句子由多個詞彙組成，每個詞彙可表示為一個向量，句子的長度不一。
*   **詞彙向量化方法**：
    *   **One-Hot Encoding**： 為每個詞彙創建一個高維稀疏向量，向量長度等於詞彙表大小，只有對應詞彙的維度為 1，其餘為 0。
        *   **缺點**： 無法表示詞彙之間的語義關係。
    *   **Word Embedding**： 將每個詞彙映射到一個低維稠密向量，這些向量能捕捉詞彙之間的語義資訊。
        *   詞嵌入可從網路上下載。
        *   參考[2016上課影片](https://youtu.be/X7PH3NuYW0Q)
![image](https://hackmd.io/_uploads/r1G4KrHn1g.png)
*   **語音訊號**： 將一段聲音訊號切分成許多小的時間片段 (Window，如 25ms) ，每個片段提取特徵並表示為一個向量 (Frame) ，一段語音即為一系列的 Frame 向量。
    *   通常 Window 會以一定的步長 (如 10ms) 滑動。
    *   一秒鐘的語音可能包含 100 個 Frame 向量。
![image](https://hackmd.io/_uploads/BJ1PFrS3kg.png)
*   **圖 (Graph)**： 圖中的每個節點可以視為一個向量。
    *   節點的向量表示可以包含節點的屬性資訊。
    *   **例子**： 社群網路 (人是節點，關係是邊) 、分子結構 (原子是節點，化學鍵是邊) 。
        *   原子可以用 One-Hot 向量表示 (如氫、碳、氧) 。
![image](https://hackmd.io/_uploads/ByDBcBShJx.png)

---

## 輸出是什麼？

對於輸入為向量集合的模型，可能的輸出有三種:

1.  **每個向量都有一個對應的標籤 (Each vector has a label)**： 輸入幾個向量，就輸出幾個標籤，輸入與輸出**長度相同**。
    *   標籤可以是數值 (迴歸問題) 或類別 (分類問題) 。
    *   **應用範例**：
        *   **詞性標註 (POS Tagging)**： 為句子中的每個詞彙標註其詞性 (名詞、動詞等) 。
            *   例如：「I saw a saw」，第一個 "saw" 是動詞，第二個 "saw" 是名詞。
        *   **語音處理**： 為語音訊號的每個 Frame 向量決定其對應的音標 (Phonetic)。
        *   **社群網路**： 預測每個節點的特性 (如是否會購買某商品) 。
![image](https://hackmd.io/_uploads/HkJesHHhye.png)
2.  **整個序列有一個標籤 (The whole sequence has a label)**： 輸入一個向量序列，只輸出一個總體的標籤。
    *   **應用範例**：
        *   **情感分析 (Sentiment Analysis)**： 判斷一段文字是正面還是負面。
        *   **語者辨認**： 聽一段聲音判斷是誰說的。
        *   **分子性質預測**： 給定一個分子結構，預測其毒性或親水性。
![image](https://hackmd.io/_uploads/BJ4VjBrhJx.png)
3.  **模型決定標籤的數量 (Model decides the number of labels itself)**： 輸入 $N$ 個向量，輸出 $N'$ 個標籤，輸出長度由模型決定。
    *   這類任務稱為 **序列到序列 (Sequence to Sequence, seq2seq)**。
    *   **應用範例**：
        *   **翻譯 (Translation)**： 將一種語言的句子翻譯成另一種語言，輸入和輸出的詞彙數量通常不同。
        *   **語音辨識 (Speech Recognition)**： 輸入語音訊號，輸出對應的文字。
:::info
本次課程主要討論第一種類型：**序列標註 (Sequence Labeling)**，即輸入與輸出長度相同的狀況。
:::

---

## 序列標註 (Sequence Labeling)

目標是為輸入序列中的每一個向量都給予一個標籤。

### 直覺方法：完全連接網路 (Fully-Connected Network, FC) :x:

*   將序列中的每個向量獨立地輸入到 FC 網路中，各自產生輸出。
*   **缺點**： 無法考慮**上下文 (Context)** 的資訊。
    *   例如在詞性標註中，「I saw a saw」，兩個 "saw" 是相同的詞彙，FC 網路會輸出相同的詞性，但實際上它們的詞性不同。

### 考慮上下文：滑動視窗 (Window) :x:

*   將目標向量及其前後幾個向量串聯起來，作為 FC 網路的輸入。
*   **優點**： 可以讓 FC 網路考慮鄰近向量的資訊。
*   **缺點**：
    *   **視窗大小的限制**： 如果需要考慮整個序列的資訊，視窗需要足夠大以覆蓋整個序列。
    *   **序列長度可變**： 不同輸入序列的長度可能不同，若要覆蓋最長序列，視窗可能會非常大，導致 FC 網路參數過多，容易**過擬合 (Overfitting)**。
    *   難以考慮長距離的依賴關係。

### 自注意力機制 (Self-attention)：考慮整個序列的資訊 :heavy_check_mark:

*   Self-attention 能夠讀取整個輸入序列的資訊，並為每個輸入向量產生一個新的輸出向量，這個新的輸出向量**考慮了整個輸入序列的資訊**。
*   輸入幾個向量，就輸出幾個向量，但每個輸出向量都包含了全局的上下文資訊 (天涯若比鄰)。
*   Self-attention 的輸出可以再輸入到 FC 網路中進行標註。
*   可以**堆疊多個 Self-attention 層**，並與 FC 網路交替使用，以更深入地處理序列資訊。
*   **關鍵論文**： "[Attention is all you need.](https://arxiv.org/abs/1706.03762)" 提出了 **Transformer** 網路架構，其中最核心的模組就是 Self-attention。
    *   Transformer 又稱「變形金剛」。
    *   論文標題強調了 Attention 機制的重要性。
![image](https://hackmd.io/_uploads/rJaLhBHnJg.png)
*   雖然 "Attention is all you need." 使 Self-attention 發揚光大，但類似的架構在更早的論文中就已出現，可能稱為 Self-Matching 等。

---

## 自注意力機制的運作方式

*   **輸入**： 一個由向量組成的序列 $a_1, a_2, a_3, a_4$ (可以是網路的原始輸入或某個隱藏層的輸出)。
*   **輸出**： 另一個相同長度的向量序列 $b_1, b_2, b_3, b_4$，其中每個 $b_i$ 都考慮了所有輸入向量 $a_1$ 到 $a_4$ 的資訊。
*   **目標**： 對於每個輸入向量 $a_i$，找出序列中與其**相關**的其他向量。
    *   相關性用一個數值 $\alpha$ (attention score) 來表示。
![image](https://hackmd.io/_uploads/HJuVASBh1g.png)
![image](https://hackmd.io/_uploads/SJ9FRSS2kl.png)

### 計算注意力分數 (Calculating Attention Scores)

對於輸入向量 $a_i$，需要計算它與序列中所有其他向量 $a_j$ 的相關性 $\alpha_{ij}$。
*   **常用方法：點積 (Dot Product)**
    1.  對於每一個輸入向量 $a_i$，學習三個轉換矩陣 $W_q, W_k, W_v$ (query, key, value)。
    2.  將 $a_i$ 分別與這三個矩陣相乘，得到對應的：
        * query 向量 $q_i = W_q a_i$
        * key 向量 $k_i = W_k a_i$
        * value 向量 $v_i = W_v a_i$
    3.  計算 $a_i$ (其 query 為 $q_i$) 與 $a_j$ (其 key 為 $k_j$) 之間的注意力分數 $\alpha_{ij}$，通常使用點積：$$\alpha_{ij} = q_i \cdot k_j$$
        >[!Tip] 
        >*   $q_i$ 就像**搜尋的關鍵字**，而 $k_j$ 就像**被搜尋的內容**。
        >*   $\alpha_{ij}$ 表示 $a_i$ 和 $a_j$ 之間的**相關程度**。
    4.  對於 $a_1$，需要計算其與 $a_1, a_2, a_3, a_4$ 的注意力分數 $\alpha_{11}, \alpha_{12}, \alpha_{13}, \alpha_{14}$。

*   **其他計算注意力的方法**： 加法式 (Additive)
    *   將 $q_i$ 和 $k_j$ 串聯後通過一個函數 (如 tanh) 和一個線性轉換得到 $\alpha_{ij}$。
![image](https://hackmd.io/_uploads/HyO4U5ikxx.png)

### 產生輸出向量 (Generating Output Vectors)

1.  對計算出的注意力分數 $\alpha_{i1}, \alpha_{i2}, \cdots, \alpha_{in}$ 進行 **Softmax 正規化**，得到 $\alpha'_{i1}, \alpha'_{i2}, \cdots, \alpha'_{in}$。$$\alpha'_{ij} = \frac{\exp(\alpha_{ij})}{\sum_{k} \exp(\alpha_{ik})}$$
    *   Softmax 的作用是將注意力分數轉換為權重，使其總和為 1.
    *   **注意**： Softmax 不是唯一的選擇，ReLU 等其他激活函數也可能有效。
![image](https://hackmd.io/_uploads/rJJEJIH2kx.png)
2.  對於每個輸入位置 $i$，將所有 value 向量 $v_j$ 根據其對應的正規化注意力權重 $\alpha'_{ij}$ 進行**加權求和**，得到輸出向量 $b_i$：$$b_i = \sum_{j} \alpha'_{ij} v_j$$
    *   如果 $a_i$ 與 $a_j$ 的相關性很高 ($\alpha'_{ij}$ 很大) ，則 $v_j$ 在計算 $b_i$ 時的影響就越大。
    *   $b_i$ 可以看作是==根據序列中所有向量的相關性，從所有向量的 value 中提取出的資訊==。
![image](https://hackmd.io/_uploads/HkcBeUShJg.png)

### 矩陣表示 (Matrix Representation)

1.   將輸入序列 $a_1, a_2, a_3, a_4$ 堆疊成一個輸入矩陣 $I$ (每列或每欄代表一個向量)。
2.   計算所有的 query 向量、key 向量和 value 向量可以表示為矩陣乘法:
     *   $Q = I W_q$ (query 矩陣，每列/欄是一個 $q_i$)。
     *   $K = I W_k$ (key 矩陣，每列/欄是一個 $k_i$)。
     *   $V = I W_v$ (value 矩陣，每列/欄是一個 $v_i$)。
![image](https://hackmd.io/_uploads/Sk4RgIrnyl.png)
3.   計算所有注意力分數可以表示為矩陣乘法:
     * 注意力分數矩陣 $A = K^T Q$ (或 $Q K^T$)，其中 $A_{ij} = q_i \cdot k_j$。
4.   正規化注意力分數：$A' = \text{softmax}(A)$ (對 $A$ 的每一行/列進行 Softmax)。
![image](https://hackmd.io/_uploads/SkeSZIr3ye.png)
5.   計算輸出矩陣 $O$ (每列/欄是一個 $b_i$)：$O = V A'$ (或 $A'^T V$)。
![image](https://hackmd.io/_uploads/rJxoZIrnyx.png)
*   **Self-attention 層中唯一需要學習的參數是 $W_q, W_k, W_v$**。
![image](https://hackmd.io/_uploads/S1ubzLSn1e.png)

---

## 多頭注意力機制 (Multi-head Self-attention)

認為相關性有多種不同的形式，單一的注意力機制可能無法捕捉所有類型的相關性。
*   使用多個獨立的 **注意力頭 (Attention Heads)** 平行地進行 Self-attention 計算。
*   對於每個注意力頭 $i$，學習**不同的轉換矩陣** $W_{q,i}, W_{k,i}, W_{v,i}$。
*   輸入向量 $a$ 經過不同的轉換後得到多個 query 頭 ($q_{i,1}, q_{i,2}, \cdots$), key 頭 ($k_{i,1}, k_{i,2}, \cdots$), 和 value 頭 ($v_{i,1}, v_{i,2}, \cdots$)。
*   每個注意力頭獨立地計算注意力分數和輸出，例如:
    *   第一個頭只關注 $q_{i,1}$ 和 $k_{j,1}$，並根據 $v_{j,1}$ 計算輸出 $b_{i,1}$。
    *   第二個頭只關注 $q_{i,2}$ 和 $k_{j,2}$，並根據 $v_{j,2}$ 計算輸出 $b_{i,2}$。
*   將所有注意力頭的輸出**拼接 (Concatenate)** 在一起，然後通過一個線性轉換矩陣 $W_O$ 得到最終的輸出 $b_i$:
    *   $b_i = W_O [b_{i,1}; b_{i,2}; \cdots; b_{i,h}]$ (其中 $h$ 是注意力頭的數量)。
*   **優點**： 可以捕捉不同種類的相關性。
*   **注意力頭的數量** 是一個超參數，需要根據具體任務調整。
![image](https://hackmd.io/_uploads/SyE0MUB2Jl.png)

---

## 位置編碼 (Positional Encoding)

標準的 Self-attention 機制本身**沒有位置資訊**，它對輸入序列中向量的順序是不敏感的。(例如，對於 Self-attention 來說，$q_1$ 到 $q_4$ 的距離與 $q_2$ 到 $q_3$ 的距離沒有本質區別)。

但在許多任務中，**位置資訊非常重要** (例如，詞性標註中，動詞通常不會出現在句首)。

### 位置編碼 (Positional Encoding)
* **目的**：將序列中每個位置的資訊嵌入到向量表示中。
* **作法**：
    1. 為序列中的**每個位置** (例如，第一個位置、第二個位置等) 定義一個**獨特的位置向量 $e_i$**。
    2. 將位置向量 $e_i$ **加到** 對應的輸入向量 $a_i$ 上：$a'_i = a_i + e_i$。
![image](https://hackmd.io/_uploads/Hy3kEIHnye.png)
### 位置向量的生成方法：
*   **手工設計 (Hand-crafted)**： 例如，Transformer 論文中使用基於正弦和餘弦函數的方法生成位置向量。
    *   每個位置對應一個獨特的向量。
*   **從資料中學習 (Learned from data)**： 將位置向量作為網路的參數進行學習。
*   其他方法，如基於 RNN 或其他網路結構生成位置編碼。

位置編碼仍然是一個活躍的[研究](https://arxiv.org/abs/2003.09229)領域。

---

## 自注意力機制的應用

### 自然語言處理 (NLP)：
廣泛應用於各種 NLP 任務。
*   **[Transformer](https://arxiv.org/abs/1706.03762):** 基於 Self-attention 的網路架構，是許多現代 NLP 模型的基礎。
*   **[BERT](https://arxiv.org/abs/1810.04805):** 一個預訓練的 Transformer 模型，在多個 NLP 任務上取得了巨大成功。
### 語音處理 (Speech)：
*   **截斷自注意力 ([Truncated Self-attention](https://arxiv.org/abs/1910.12977))**： 由於語音序列通常很長，直接計算全局注意力計算量很大 ($O(L^2)$，L 為序列長度)。
*   截斷自注意力只在一個**有限的範圍**內計算注意力，以減少計算量。
*   這個範圍的大小可以根據對語音問題的理解來設定。
![image](https://hackmd.io/_uploads/rkT9VUSn1x.png)
### 圖像處理 (Image)：
*   可以將圖像視為一個向量的集合 (每個像素或圖像塊是一個向量)。
![image](https://hackmd.io/_uploads/rkVBBUS2Jg.png)
*   **[Self-Attention GAN](https://arxiv.org/abs/1805.08318)**： 將自注意力機制應用於生成對抗網路 (GAN) 中以生成圖像。
*   **[DEtection Transformer (DETR)](https://arxiv.org/abs/2005.12872)**： 使用 Transformer 進行目標檢測。
*   **[An Image is Worth 16x16 Words: Transformers for Image Recognition](https://arxiv.org/pdf/2010.11929.pdf)**： 將圖像分割成小的圖像塊 (patch)，將每個 patch 視為一個詞彙，然後使用 Transformer 進行圖像分類。

---

## [自注意力機制 vs. 卷積神經網路 (CNN)](https://arxiv.org/abs/1911.03584)

*   **CNN**： 每個神經元只關注其**感受野 (Receptive Field)** 內的資訊。
*   **Self-attention**： 在計算注意力時，可以考慮**整張圖像**的資訊。
*   **關係**：
    *   **CNN 可以看作是簡化版的 Self-attention**： CNN 的感受野是固定的，而 Self-attention 的注意力範圍是根據資料學習出來的。
    *   **Self-attention 可以看作是複雜化的 CNN**： Self-attention 具有**可學習的感受野**，網路可以自行決定哪些像素是相關的。
*   **彈性 (Flexibility)**： Self-attention 比 CNN 更具彈性。
*   **資料需求**：
    *   **資料量較少時**： CNN 可能表現更好，因為其限制較多，不容易過擬合。
    *   **資料量較大時**： Self-attention 可以從更多資料中獲益，通常能取得更好的效果。

---

## 自注意力機制 vs. 循環神經網路 (RNN)

*   **RNN**： 處理序列資料的另一種常見網路結構，通過**記憶向量 (Memory Vector)** 在時間步之間傳遞資訊。
*   **相似之處**： 兩者都用於處理輸入為序列的狀況，並產生一個輸出序列。
*   **不同之處**：
    *   **考慮上下文**： 傳統 RNN 在某個時間步的輸出只考慮了之前輸入的資訊 (單向 RNN)。雙向 RNN 可以同時考慮過去和未來的資訊。 Self-attention 的每個輸出向量都直接考慮了整個輸入序列的所有向量。
    *   **長距離依賴**： RNN 處理長序列時可能存在**遺忘問題**，難以捕捉長距離的依賴關係。 Self-attention 可以輕鬆地從序列中相距很遠的向量中提取資訊。
    *   **平行化**： **RNN 無法平行化處理序列**，必須按時間步依次計算。 **Self-attention 可以平行地計算所有位置的輸出**，因此在運算速度上更有效率。
*   **趨勢**： 許多應用中，RNN 的架構正逐漸被 Self-attention 取代。
![image](https://hackmd.io/_uploads/rJcSU8r3kg.png)
*   **[Transformers are RNNs](https://arxiv.org/abs/2006.16236)**： 一篇論文探討了 Self-attention 與 RNN 之間的關係，指出在加入某些機制後，Self-attention 可以轉化為 RNN。
*   參考[2017上課影片](https://youtu.be/xCGidAeyS4M)

---

## 自注意力機制用於圖 (Self-attention for Graph)

圖可以被視為一個向量的集合 (每個節點是一個向量)，因此，Self-attention 也可以應用於圖結構。
*   **圖的額外資訊：邊 (Edge)**。
    *   邊表示節點之間的連接和關係。
    *   在使用 Self-attention 處理圖時，可以**僅計算相連節點之間的注意力分數**，不相連的節點之間的注意力分數可以直接設為 0。
    *   這樣可以利用圖的結構資訊，避免計算不相關節點之間的注意力。
*   將 Self-attention 以這種方式應用於圖上，是**圖神經網路 (Graph Neural Network, GNN)** 的其中一種。
![image](https://hackmd.io/_uploads/HJ3GPIS3yg.png)
*   GNN 是一個複雜且深入的領域。
*   參考[2020上課影片](https://youtu.be/eybCCtNKwzA)

---

## 總結與展望

*   Self-attention 是一種強大的機制，能夠有效地處理序列資料並捕捉長距離的依賴關係，其核心思想是根據輸入序列中不同位置之間的相關性，對資訊進行加權聚合。
*   Transformer 架構的成功證明了 Self-attention 的有效性，並在 NLP 等領域取得了突破性進展。
*   Self-attention 也被廣泛應用於語音、圖像和圖等其他領域。
*   **效率問題**： 標準 Self-attention 的計算複雜度是序列長度的平方 ($O(L^2)$)，對於長序列而言計算量很大。
*   **高效 Transformer ([Efficient Transformers](https://arxiv.org/abs/2009.06732))**： 目前有許多研究致力於**減少 Self-attention 的計算量**，提出了各種不同的變形 (如 Linformer, Performer, Reformer 等)。
    *   這些高效 Transformer 通常在速度上有所提升，但可能犧牲一定的性能。
    *   如何設計出既高效又高性能的 Self-attention 機制仍然是一個重要的研究方向。
![image](https://hackmd.io/_uploads/BJLwPIr31g.png)

---

回[主目錄](https://hackmd.io/@Jaychao2099/aitothemoon/)