L4.4 要看哪裡,能不能由內容決定,而不是由位置決定?
起點:鄰居是誰,可以事後才知道嗎
同一個東西換個位置出現,要怎麼讓模型知道那還是同一個東西? 和 一張圖裡同時有紋理、物件和整個場景,一個固定大小的核怎麼辦? 建立的整套機制,都建立在同一個決定上:要看誰,由位置決定。一個 的核看的永遠是周圍那 個鄰居,不管那些鄰居裡裝的是什麼。
對影像,這個決定大致是對的——相鄰的像素通常屬於同一個東西。但很多問題不是這樣:
- 「它」這個代名詞指的是哪個名詞?可能在三個字之前,也可能在三十個字之前。
- 這個像素屬於哪個物件?和它同色、同紋理的像素可能離它很遠。
- 這個分子裡的兩個原子會不會交互作用?取決於它們的種類,不是它們在序列裡的編號。
這些問題有一個共同的形狀:要看哪裡,必須先看過內容才知道。而一個事先畫好的鄰域,在定義上做不到這件事。
卷積的鄰域是寫程式的時候就畫好的,
可是「該看哪裡」常常要看過內容才知道——
能不能讓模型自己決定要看誰?
課堂提問Q1
造一個「由內容決定要看誰」的層。要求三件事:一,每個位置的輸出是所有位置的加權平均;二,權重由內容決定;三,權重非負且和為一(這樣輸出才和輸入在同一個尺度上)。寫出來之後,檢查它保留了什麼、丟掉了什麼。
先想一想,再展開看整理後的答案
三個要求幾乎把式子逼出來。
要「權重由內容決定」,就要有一個函數把一對位置 的內容映到一個分數。最省的做法是先各自做一次線性投影,再取內積:
兩個投影不共用權重,因為「我在找什麼」(query)和「我提供什麼」(key)是兩個不同的角色。分母那個 是本篇第三節的主題。
要「非負且和為一」,就用 softmax:。
最後,被平均的東西不必是 本身——再做一次投影,讓「拿來比對的內容」和「拿來傳遞的內容」分開:
三個投影、一個內積、一個 softmax,就是自注意力的全部。
保留了什麼。 每個位置都保留一個輸出,所以位置的數量和對應關係還在——它是一個序列到序列的映射,可以一層層疊。
丟掉了什麼——而這是這一篇的重點。 式子裡的每一個東西都只依賴 和 的內容,沒有任何地方用到 和 這兩個數字。所以如果把所有 token 重新排列,每一個 、每一個 都只是跟著換編號,輸出也只是跟著換編號:
這叫置換等變,而它比 同一個東西換個位置出現,要怎麼讓模型知道那還是同一個東西? 的平移等變強得多——平移是置換的一個很小的子集。
強的對稱性是強的假設。注意力宣告的是「位置完全不重要」,而那對文字、影像、時間序列都是錯的。所以位置一定要另外餵進去,而下一節就是量這件事。
它對位置真的一無所知
先確認那個對稱性不是「大致成立」。取一個隨機初始化的自注意力層,把 token 的順序用一個固定的排列打亂:
max |Attn(打亂 x) - 打亂 Attn(x)| = 6.661e-16
參考:輸出本身的量級 max|Attn(x)| = 3.3553
是浮點數的解析度,也就是精確為零。 和 同一個東西換個位置出現,要怎麼讓模型知道那還是同一個東西? 那個 一樣,這是結構性質而不是學出來的近似。
接一個平均池化之後,等變變成不變:
max |y(打亂 x) - y(x)| = 1.665e-16
所以一個不加位置資訊的注意力模型,計算出來的一定是輸入的一個「集合函數」——它看得到有哪些 token,看不到它們的順序。
這值多少錢? 造一個必須知道順序的任務: 個 token,每個是一個 維的隨機向量,標籤是「第 0 個位置的 token 的第 0 維是正還是負」。模型是一個學出來的 query 對這 個 token 做一次注意力池化,再接一個線性輸出。
先算一個基準:一個置換不變的模型能做到多好?它看得到的只有那個多重集,而多重集裡最接近答案的統計量是平均值;平均值和 的相關係數是 ,於是符號一致的機率是 。這是理論上限,不是實驗結果。
置換不變模型的理論上限 0.6150
無位置編碼 訓練 0.640 測試 0.580
正弦位置編碼 ×1 訓練 0.698 測試 0.671
正弦位置編碼 ×3 訓練 0.927 測試 0.932
第一列貼著那個上限(,訓練 )。模型沒有做錯任何事——它把能做的都做了,而能做的就只有這麼多。
第三列是加了位置編碼之後:。同一個架構、同一份資料、同一個訓練預算,差別只在輸入上加了一組和位置有關的常數向量。
而第二列是這張表最實用的一行。 標準的正弦編碼直接加上去,只到 ——比沒有好,但離 還很遠。把同一組編碼乘以三倍才真的有用。
理由是信噪比:注意力的 logit 是 ,裡面同時有位置的成分和內容的成分。內容是 的隨機向量,位置編碼的每個分量在 之間——兩者量級相當,於是位置訊號被內容的噪聲蓋掉。放大三倍之後它才壓得過。
位置編碼不是「加上去就有」,它要大聲到能在 logit 裡被聽見。
這件事在 同一台機器要依指令做不同的事,指令從哪裡餵進去? 已經以另一個形式出現過:一個純量 直接當成輸入的一維時,網路學不好( 對正弦嵌入的 )。兩次都是同一個教訓——要讓網路用到某個訊息,光是「有把它放進去」不夠,還要讓它在那一層的運算裡有足夠的份量。
那個 在防什麼
Q1 的式子裡有一個沒有解釋的分母。它看起來像一個美觀問題,實際上是一個會讓訓練整個停住的東西。
和 是 維的向量。如果它們的分量大致獨立、大致是 ,那麼 是 個獨立項的和,標準差是 。維度越高,logit 的散佈越大,而 softmax 對輸入的散佈極度敏感。
實測(每個 query 對 個 key,均勻分布的熵是 nats):
d= 4 不縮放 logit 標準差 1.779 注意力熵 1.8090 最大權重 0.4222
d= 4 除以 √d logit 標準差 0.889 注意力熵 2.4237 最大權重 0.2298
d= 16 不縮放 logit 標準差 4.101 注意力熵 0.8689 最大權重 0.6956
d= 16 除以 √d logit 標準差 1.025 注意力熵 2.3428 最大權重 0.2483
d= 64 不縮放 logit 標準差 7.759 注意力熵 0.4317 最大權重 0.8367
d= 64 除以 √d logit 標準差 0.970 注意力熵 2.3808 最大權重 0.2373
d= 256 不縮放 logit 標準差 15.789 注意力熵 0.2051 最大權重 0.9177
d= 256 除以 √d logit 標準差 0.987 注意力熵 2.3692 最大權重 0.2426
d=1024 不縮放 logit 標準差 32.126 注意力熵 0.0886 最大權重 0.9639
d=1024 除以 √d logit 標準差 1.004 注意力熵 2.3571 最大權重 0.2453
不縮放的那幾列,logit 標準差就是 (、、、)。而後果是注意力塌掉: 時熵只剩 nats(均勻是 ),最大權重 ——在隨機初始化時,每個 query 就已經幾乎只看一個 key 了。
為什麼這是災難。 softmax 在飽和的時候梯度趨近零:如果 ,那麼 的每一項都含有 這樣的因子,全部接近零。所以模型卡在它隨機猜的那個注意力模式上,而且沒有梯度可以爬出來。這和 差一度與差十度:損失函數是一種宣告 裡 sigmoid 飽和的情形是同一件事,只是換了一個地方。
除以 之後,右邊三欄在五個數量級的 上幾乎不動(標準差 –、熵 –、最大權重 –)。這正是一個好的縮放該有的樣子:它讓一個設計選擇(維度)不再影響另一個東西(初始的注意力有多集中)。
補充這也解釋了多頭為什麼要把維度切開
多頭注意力把 維切成 個 維的頭,各自做一次注意力再串接。常見的解釋是「不同的頭可以關注不同的東西」,那是對的但不完整。
從上表可以看到第二個理由:每個頭的 變小了。而 小的時候,即使有 ,logit 的分布也比較容易被學出來的權重塑形——一個 維的頭要學出「只看某一個 key」比一個 維的空間容易,因為它需要對齊的方向少得多。
還有第三個理由是純粹的算術: 個 維的頭,總計算量和一個 維的頭相同(),但你得到 組獨立的注意力模式。同樣的預算買到更多的模式,這是多頭幾乎沒有代價的原因。
要注意的是這三個理由都不保證「不同的頭真的學到不同的東西」。實務上有相當比例的頭是冗餘的,而那是另一個獨立的觀察。
代價:長度的二次式
注意力買到的是路徑長度。任意兩個位置在一層之內就互相看得到,不管它們相隔多遠。對照 一張圖裡同時有紋理、物件和整個場景,一個固定大小的核怎麼辦? 那張接受域的表:
要讓相隔 d 個位置互相影響:
d = 16 卷積(K=5) 需要 4 層 自注意力 1 層
d = 64 卷積(K=5) 需要 16 層 自注意力 1 層
d = 256 卷積(K=5) 需要 64 層 自注意力 1 層
d = 1024 卷積(K=5) 需要 256 層 自注意力 1 層
(降取樣可以把左欄降到對數,代價是 一張圖裡同時有紋理、物件和整個場景,一個固定大小的核怎麼辦? 量過的高頻損失。)
而賣掉的是計算量。 注意力要算出 個分數,所以它的成本是長度的二次式。實測(單頭、、batch ):
L = 64 0.88 ms 相對 1.0 (純 L² 的預測 1.0)
L = 128 2.34 ms 相對 2.6 (4.0)
L = 256 7.36 ms 相對 8.3 (16.0)
L = 512 33.29 ms 相對 37.6 (64.0)
L = 1024 105.15 ms 相對 118.8 (256.0)
L = 2048 348.42 ms 相對 393.8 (1024.0)
每把長度加倍,時間大約乘以 倍(純線性是 倍,純二次是 倍)。落在中間是因為有兩項成本:三個投影是 ,注意力本身是 。在 附近兩者相當, 再大時二次項才主導——這也是為什麼「注意力太貴」這個問題在短序列上根本感覺不到,而在長序列上會突然變成唯一的瓶頸。
這條曲線決定了很多架構決定。 為什麼影像要先切成 的 patch 再送進 Transformer?因為 個像素的注意力矩陣有 個元素,而切成 patch 之後 。切 patch 不是一個細節,它是讓這條曲線落在可負擔的區間裡的必要條件。
卷積用層數換距離,注意力用計算量換距離;哪一個划算,完全取決於你的 和你需要的距離。
內容決定看誰,位置另外餵
互動 demo:按「打亂順序」看置換等變誤差停在 10⁻¹⁶;關掉 1/√d 再把 d 拉大,熵一路掉向 0。
回到情境:它其實是這個 class 裡假設最少的架構
把 L4 的四個架構按「宣告了多少關於資料的事」排一次:
| 架構 | 宣告 |
|---|---|
| 卷積 | 有用的模式是局部的;一個模式在哪裡出現都算數 |
| U-Net | 以上,加上「資料有多個尺度,而細節要能繞過瓶頸」 |
| 自注意力 | 位置完全不重要(然後被位置編碼部分撤回) |
| MLP | 沒有任何關於輸入座標的宣告 |
注意力在這張表上靠近 MLP 那一端,不是靠近卷積那一端。 它的置換等變是一個很強的對稱性,而強的對稱性意味著很少的限制——一個對所有置換都等變的模型,能表達的東西比一個只對平移等變的模型多得多。
而 什麼都能擬合,那為什麼還需要別的架構? 已經說過這件事的另一面:在有限資料下,沒有偏置不是中性,是缺點。 候選函數越多,資料越難把它們分開,所以這正是 背考古題的學生:過擬合與欠擬合 那條 U 形右半邊的來源。
這解釋了一個常見的觀察:在中小規模的影像資料上,卷積網路通常勝過純 Transformer;資料規模夠大之後,順序才反過來。這不是誰「比較先進」的問題,它就是 bias–variance 換一個外衣——卷積用一個(大致正確的)假設換掉一部分需要用資料去學的東西,而那個交換在資料少的時候划算、在資料多的時候變成束縛。
這一切依賴什麼。
一,位置資訊要被真的餵進去而且夠大聲。第二節那個 對 就是「餵了但不夠大聲」的樣子,而這在自己的專案上是可以量的:把位置編碼的強度掃一遍,看指標有沒有平台。
二, 要在可負擔的範圍。第四節那條曲線是硬的;超過之後所有的變通(切 patch、稀疏注意力、線性近似)都在恢復某種局部性——也就是把卷積放棄掉的那個假設部分地加回來。
三,資料量要對得起這個假設空間的大小。這一點沒有捷徑,而 該收資料、換模型,還是多訓幾輪:學習曲線 那條曲線是判斷它的工具:如果學習曲線還在陡降,加資料比換架構有用;如果已經平了,換一個假設更強的架構才是對的方向。
先消化一下
參考文獻
- Vaswani, A. et al. Attention Is All You Need. NeurIPS 2017.(自注意力、多頭、 縮放與正弦位置編碼的出處。)
- Dosovitskiy, A. et al. An Image is Worth 16x16 Words. ICLR 2021.(把影像切成 patch 的理由,以及「資料量夠大之前卷積的歸納偏置仍然划算」的實證。)
- Tay, Y., Dehghani, M., Bahri, D. & Metzler, D. Efficient Transformers: A Survey. ACM Computing Surveys 55(6), 2022.(各種降低 成本的做法,以及它們各自恢復了哪一種局部性。)