一個注意力只能問一個問題
一個單一的注意力運算只學到一種「相關」的概念。但語言一次需要很多種。要解決它指什麼,你在意它指哪個名詞;要變化動詞,你在意主詞的單複數;要結束一個引號,你在意開引號在哪。逼一個注意力同時兼顧這一切,只會把它們糊在一起。
解法是多頭注意力(multi-head attention)。模型不用一個大注意力,而是平行跑好幾個小的——每一個是一個頭(head),有自己獨立的查詢、鍵、值矩陣。每個頭對同一份輸入,算自己的分數、自己的 softmax、自己的值混合。典型模型每層有 8 到 128 個頭不等。
圖示:查詢向量經過 softmax 與鍵向量比較,從而對值向量加權。
拆分、注意、再合併
- 拆分。 把詞向量分給各個頭——有 8 個頭時,每個頭在較小的一段維度上工作。總工作量和一個大頭差不多。
- 注意。 每個頭獨立做上一篇那整套自注意力(self-attention)流程,產生自己的脈絡混合輸出。
- 合併。 把各頭的輸出串接起來,再經過一個學到的矩陣,讓模型把各頭的發現融合成每個詞一個更新後的向量。
圖示:一個向量被切分到多個頭,各頭並行計算注意力,輸出拼接後再投影。
這些頭最後都在做什麼
沒有人告訴這些頭要專精什麼——它們在訓練中自行發現各自的角色(role)。研究者檢視訓練好的模型時,會看到重複出現的模式。有些頭是位置型的,主要注意前一兩個詞。有些是語法型的,把動詞連到主詞、把限定詞連到名詞。著名的一種是歸納頭(induction head),它認出重複的模式(「……鄧不利多說……鄧不利多」),把上次接在後面的東西複製過來——這是脈絡學習的關鍵成分。
我們可以把每個頭的注意力權重畫成方格,一軸放來源詞、一軸放目標詞、亮度代表權重,就能直接看到這些角色。這種注意力模式視覺化(attention pattern visualization)是研究者窺看模型內部真正在做什麼的主要窗口之一。
互動式自注意力演示:點擊一個詞元,高亮它所注意的詞。
單行道:因果遮罩
目前為止的一切藏著一個問題。語言模型被訓練來做下一個詞元預測(next-token prediction)——給定目前的詞,猜下一個。但單純的自注意力讓每個詞都能看到其他每個詞,包括它後面的詞。如果模型能偷看答案,它就什麼有用的東西都學不到。我們得把它的眼睛矇上。
因果遮罩(causal masking)做的正是這件事。在 softmax 之前,凡是一個詞會去注意未來詞的分數,都被設成負無限大。經過 softmax 後,那些位置的權重變成零——隱形。結果是一條嚴格的單行道:第 5 個位置可以注意第 1 到第 5 個位置,永遠看不到第 6 個以後。這正是讓這個架構成為僅解碼器(decoder-only)、自回歸(autoregressive)的原因:它一次生成一個詞元,每一個都只以它的過去為條件。
因果遮罩在 softmax 之前把所有未來位置加上 −∞,於是每個詞元只能注意到自己和過去。
# causal mask applied inside attention, before softmax scores = Q @ K.T / sqrt(d_k) # (seq_len, seq_len) # upper triangle = future positions -> forbid them scores = scores.masked_fill(future_positions, -infinity) weights = softmax(scores) # future positions now get weight 0 out = weights @ V