Attention Is All You Need(Vaswani et al., 2017)是現代大語言模型的架構起點:論文本身處理的是機器翻譯這個 seq2seq 問題,提出完全捨棄遞迴(RNN)與卷積、只用 attention 機制堆疊出來的 Transformer。今天絕大多數大語言模型都是這個架構的變體,但多數是只保留 decoder、且在細節上做了不少調整的版本,跟原始論文本身並不完全相同。這篇文章先把原始論文的架構拆到最細,再說明現代 decoder-only LLM 具體改了哪些地方。

1. 為什麼要用 Attention 取代 RNN

RNN 處理序列時,每個時間步的計算都依賴前一步的隱藏狀態,本質上是串行的:處理第 tt 個詞元之前,必須先算完第 t1t-1 個。這代表 RNN 沒辦法在序列長度這個維度上並行,訓練長序列時 GPU 的平行運算能力用不上,也讓長距離依賴必須靠隱藏狀態一路傳遞,容易隨距離增加而衰減。

Transformer 的核心想法是:讓序列中任意兩個位置之間的資訊傳遞,都只需要一步 attention 計算,不需要沿著中間的位置逐步傳遞。訓練階段(有完整的目標序列可用時)所有位置的 attention 可以完全並行計算;序列變長也不會增加位置之間傳遞資訊所需的步數。代價是自注意力的計算量隨序列長度呈平方成長,這也是後續大量長序列優化工作要解決的問題,但不是這篇論文本身要處理的範圍。

2. Scaled Dot-Product Attention

2.1 Query、Key、Value 與張量形狀

Attention 的輸入是三組向量:Query(QQ)、Key(KK)、Value(VV)。單一個 attention head 裡,若序列長度為 nnQRn×dkQ\in\mathbb R^{n\times d_k}K,VRm×dkK,V\in\mathbb R^{m\times d_k}Rm×dv\mathbb R^{m\times d_v}mm 是被查詢的序列長度;self-attention 裡 m=nm=n,encoder-decoder cross-attention 裡 mm 是 encoder 輸出的序列長度)。計算公式是:

Attention(Q,K,V)=softmax(QKdk)V\operatorname{Attention}(Q,K,V)=\operatorname{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)V

QKQK^\top 算出每個 query 對每個 key 的相似度分數,形狀是 n×mn\times m;對每一行做 softmax,得到每個 query 位置對所有 key 位置的注意力權重;權重乘上 VV,等於用這組權重對 value 向量加權平均,輸出形狀是 n×dvn\times d_v

2.2 為什麼要除以 dk\sqrt{d_k}

Q,KQ,K 的每個分量都近似獨立、均值 0、變異數 1,QKQK^\top 裡每個內積是 dkd_k 項乘積的和,變異數會隨 dkd_k 線性成長。dkd_k 較大時,內積數值本身會變得很大,把 softmax 推進梯度極小的飽和區間,訓練會變得困難。除以 dk\sqrt{d_k} 把內積的變異數重新拉回常數量級,這是論文裡明確指出、也是「scaled」這個字的來源。

3. Multi-Head Attention

單一個 attention head 只能學到一種相似度度量方式。Multi-head attentionQ,K,VQ,K,V 各自用 hh 組不同的線性投影 WiQ,WiK,WiVW_i^Q,W_i^K,W_i^V 投影到較低維度,平行算出 hh 個 head 的 attention 輸出,再把 hh 個輸出串接起來,用另一個線性層 WOW^O 投影回原本的維度:

MultiHead(Q,K,V)=Concat(head1,,headh)WO,headi=Attention(QWiQ,KWiK,VWiV)\operatorname{MultiHead}(Q,K,V)=\operatorname{Concat}(\text{head}_1,\dots,\text{head}_h)W^O,\quad \text{head}_i=\operatorname{Attention}(QW_i^Q,KW_i^K,VW_i^V)

原始論文的 base model 用 dmodel=512d_{\text{model}}=512h=8h=8,每個 head 的 dk=dv=dmodel/h=64d_k=d_v=d_{\text{model}}/h=64。切成多個較窄的 head 而不是用一個寬 head,讓模型可以同時關注不同子空間裡不同種類的關係(例如某些 head 傾向捕捉語法結構、某些傾向捕捉指代關係),而總計算量跟單一個全寬度 head 大致相同。

4. Encoder 與 Decoder 的區塊結構

4.1 Encoder block:兩個子層

每個 encoder block 由兩個子層組成:self-attention,接著是 position-wise feed-forward network(見第 5 節)。每個子層外面都包一層殘差連接加上 Layer Normalization。原始論文用的是 post-LN:先計算子層本身,加回殘差,再做正規化,也就是 LayerNorm(x+Sublayer(x))\operatorname{LayerNorm}(x+\operatorname{Sublayer}(x)),順序是「子層 → 殘差相加 → LayerNorm」,正規化在殘差相加之後。base model 疊 6 層這樣的 encoder block。

4.2 Decoder block:三個子層,含 cross-attention

Decoder block 比 encoder 多一個子層,總共三個:第一個是加了 causal mask 的 self-attention(見 4.3),第二個是 encoder-decoder cross-attention——這個子層的 QQ 來自 decoder 上一個子層的輸出,KKVV 來自 encoder 最後一層的輸出,讓 decoder 每個位置都能查詢整個輸入序列——第三個是跟 encoder 相同的 FFN。三個子層同樣各自包一層殘差加 post-LN。

4.3 Causal mask:確保訓練和推論一致的因果性

Decoder 在生成第 tt 個詞元時,只能依賴第 11t1t-1 個已生成的詞元,不能看到未來的詞元。訓練時用 teacher forcing,一次把整個目標序列輸入,若不做任何處理,self-attention 會讓每個位置都看得到後面的詞元,等於作弊。解法是在 QKQK^\top 算完、做 softmax 之前,把上三角(對應「查詢位置早於被看的位置」)的分數設成 -\infty,softmax 之後這些位置的權重會變成 0,等於強制每個位置只能關注自己與更早的位置。這個機制讓訓練時的平行計算跟推論時「一次只能看到已生成部分」的限制維持一致。

5. Position-wise Feed-Forward Network

FFN 對序列中每個位置獨立且相同地套用同一組參數的兩層全連接:

FFN(x)=max(0,xW1+b1)W2+b2\operatorname{FFN}(x)=\max(0,xW_1+b_1)W_2+b_2

輸入輸出維度都是 dmodeld_{\text{model}},中間隱藏層維度 dffd_{ff} 通常遠大於 dmodeld_{\text{model}}(base model 用 dff=2048d_{ff}=2048,是 dmodel=512d_{\text{model}}=512 的 4 倍),啟用函數是 ReLU。FFN 不是把 attention 的 Q,K,VQ,K,V 轉換成輸出維度——attention 子層自己的輸出投影 WOW^O 才是做這件事——FFN 的角色是在每個位置上,對 attention 子層算出的結果做一次非線性的逐位置轉換,讓模型在混合了跨位置資訊之後,還有能力對單一位置的表示做更複雜的非線性處理。現代模型常把 ReLU 換成 GELU、SwiGLU 等變體,但「逐位置的兩層非線性轉換」這個角色沒有變。

6. Embedding 與位置編碼

6.1 輸入嵌入、權重縮放與輸出層共享權重

輸入詞元先查表轉成 dmodeld_{\text{model}} 維的嵌入向量,論文裡這個嵌入會再乘上 dmodel\sqrt{d_{\text{model}}},讓嵌入的數值量級跟後面加上去的位置編碼相當。輸出端把 decoder 最後的表示投影回詞表大小、再做 softmax 預測下一個詞元,這個投影矩陣跟輸入嵌入表共享同一組權重(weight tying),減少參數量,也讓輸入輸出的向量空間維持一致的幾何關係。

6.2 原始論文的正弦位置編碼

Self-attention 本身對輸入順序不敏感——打亂輸入位置,attention 算出來的加權平均結果不會變——所以需要額外注入位置資訊。原始論文用固定(不學習)的正弦函數:

PE(pos,2i)=sin ⁣(pos100002i/dmodel),PE(pos,2i+1)=cos ⁣(pos100002i/dmodel)PE_{(pos,2i)}=\sin\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right),\quad PE_{(pos,2i+1)}=\cos\!\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)

pospos 是序列中的位置,ii 是維度索引。這組編碼直接加到輸入嵌入上。選擇正弦函數的原因之一是它讓任意固定偏移量 kk 的位置編碼 PEpos+kPE_{pos+k},可以寫成 PEposPE_{pos} 的線性函數,理論上讓模型更容易學會依賴相對位置的模式,也讓模型有機會處理比訓練時看過的序列更長的輸入。

現代 decoder-only LLM 多半不用這種絕對位置編碼,改用 RoPE(旋轉位置編碼)ALiBi 之類的相對位置方法,直接把位置資訊算進 attention 分數本身,而不是加在輸入嵌入上;這類方法對長序列外推的效果通常優於原始論文的正弦編碼,是原始論文之後才發展出來的做法,並不是原始 Transformer 架構的一部分。

7. 訓練與推論的差異

原始論文的訓練用 teacher forcing(每一步都輸入真實的前文詞元,而不是模型自己上一步的預測)、Adam 優化器搭配一套先線性升溫再依步數衰減的學習率排程、對每個子層輸出和嵌入加總後做 dropout,以及 label smoothing(ϵls=0.1\epsilon_{ls}=0.1,讓目標分布不是硬性的 one-hot,避免模型對預測過度自信)。評估翻譯品質時使用 beam search。

推論階段沒有真實的目標序列可以參考,decoder 必須自回歸:每次只生成一個詞元,把它接到已生成的序列後面,再餵回模型生成下一個。原始論文的解碼方式只有貪心搜尋和 beam search;top-k、top-p(nucleus sampling)、temperature 這類取樣策略,是後來的研究(大致在 2018 年之後,隨開放式文本生成的需求發展出來)針對開放式生成任務提出的方法,不屬於 2017 年原始論文的內容,但是現代 decoder-only LLM 推論時的標準做法:temperature 縮放 logits 分布的尖銳程度,top-k 只在機率最高的 kk 個詞元裡取樣,top-p 則取機率總和達到 pp 的最小候選集合再取樣,貪心解碼(等於每次都選機率最高的詞元)可以看成 top-k=1 或 temperature 0\to0 的特例。

8. 從原始論文到現代 decoder-only LLM

現代大語言模型(GPT 系列及其後繼者)多半只保留 decoder,拿掉 encoder 和 cross-attention,靠 causal self-attention 同時處理輸入與生成,這也是「decoder-only」名稱的由來。除了架構的取捨,常見的具體差異還包括:把 post-LN 換成 pre-LN(LayerNorm 放在子層之前,殘差路徑上不經過正規化,x+Sublayer(LayerNorm(x))x+\operatorname{Sublayer}(\operatorname{LayerNorm}(x))),這讓深層模型的訓練穩定性明顯提升,是超大模型能疊到幾十甚至上百層的重要原因之一;位置編碼換成 RoPE 或 ALiBi;FFN 的啟用函數換成 GELU 或 SwiGLU。這些改動大多是 2017 年之後、為了訓練更深更大的模型而陸續提出的工程改良,理解原始論文的每個組件在做什麼,是判斷這些改良各自解決了什麼問題的前提。