Transformer的知識在哪裡:從FFN出發

ysngki發表於2024-06-11

前情提要:

前陣子,或許更早之前,筆者關於 MoE 的一些研究——如果稱得上是研究,而非民科的話——讓人不禁思考 Transformer 的知識到底存在哪裡?這個問題的價值不言而喻,用來打發時間也是個不錯的選擇。

可惜的是,目前我關於它的思考仍舊十分細碎,或許也稱不上有什麼新意,這裡只是做下暫且的梳理,一方面以作個人備忘,一方面也會考慮可讀性,希望能幫助看到此篇的人度過愉快的廁所時光。

矩陣乘法

最簡單的神經網路,或許就是矩陣 -> 啟用函式 -> 矩陣 -> 啟用函式的堆疊了吧。

假如這個網路的輸入是個向量,那麼在每一個矩陣層,進行的計算無非是一個向量和一個矩陣的乘法

即便以筆者匱乏的數學知識,也可以知道,向量和矩陣的乘法,可以看成是以向量為權重,對矩陣的所有行(或者列)進行加權求和。

從這個角度去理解的結果是什麼呢?我們可以輕鬆的把一個神經網路分為頭重腳輕的兩部分:權重生成器,和知識儲存器(其實就是個矩陣)。輸入經過好多好多層複雜的運算,為的就是把最後的一層混合起來。

(你或許想到了殘差連線這個反例,別急別急。)

那麼然後呢?這就有了一絲絲可解釋性了。假如我們可以評估知識儲存器裡的每個知識對於最終預測的影響,那麼我們就可以透過檢視權重,看看模型是否按照我們的理解在工作。

相關工作

好吧,口說無憑,還會被當成民科,這裡就擺出一篇相關論文:Backpack Language Models -- 23 ACL Outstanding Papers。

這篇文章的出發點是可解釋性。用我們剛才提出的視角,這篇文章的方法,完全可以看成是:權重生成器——一整個Transformer,和知識儲存器——一個矩陣。

背景知識:Transformer,或者說 decoder 的結構,我們可以看成是:

  • embedding layer
  • Transformer Blocks
  • embedding layer (decoding layer)

這篇的文章呢,在這裡面插了兩層,變成了:

  • embedding layer
  • Transformer Blocks
  • Attention Layer
  • Backpack Layer
  • embedding layer (decoding layer)

這插入的兩層被加粗了,名字是我隨便取的。

大家都知道, Transformer Blocks 的輸出是一個 token embedding 的序列。這裡假設有 N 個 token,每個 embedding 的維度是 d,那麼輸出就是個矩陣,維度是 N * d。

Attention Layer 做的工作,就是把這個矩陣拿過來,計算兩兩 token 之間的 k 個權重,最終得到一個 N * N * k 的矩陣。(為什麼是 k 個?怎麼得到 k 個權重?無視也行,完全不重要。做法很簡單,參考多頭注意力。)

通俗點理解,每個 token 都需要給出它對其它所有 token 的喜歡程度,而且還要用 k 個標準給出 k 個不同的分數。所以每個 token 的權重矩陣是 N * k 。

Backpack Layer 裡面,有一個預先準備好的矩陣。在這個矩陣裡,每個詞有 k 個向量。假設詞表大小是 V,那麼這個矩陣的大小就是 V * k * d——我們只需要用到一起出現的那些詞的向量,矩陣大小是 N * k * d。

對於一個 token,它根據權重,把 Backpack Layer 裡的那些向量混合,得到 token 最終的輸出向量。

繁瑣的細節終於解釋了,總結下!

Backpack Language model 裡,embedding layer + Tranformer Blocks + Attention Layer可以看成是一個活生生的權重生成器——非常重量級的權重生成器。然後,Backpack Layer 裡儲存的向量,就是所謂的知識啦。

梳理下模型的計算過程:給定一個輸入的向量,經過 Transformer 的計算,得到它對於某些向量(知識)的喜愛程度,然後根據這個喜愛程度,把知識混合起來。

這麼訓練的模型呢,也就具備了一點點可解釋性。具體還是看論文吧。

殘差連線

筆者呢,前些時日,發了個想法。根據我們提出的權重生成器知識儲存器這個角度,來理解殘差連線的作用。

殘差連線的直覺
如果有個神經網路,輸入是向量,輸出也是向量。

通常來說(或者假定),沒有殘差的情況下,最後一次的計算是向量 x 與一個矩陣相乘 A。比如:

y = xA。

那麼直觀點來看,這個操作就是將 A 的各行進行混合。

也就是說,我們可以把神經網路拆成兩部分。第一部分根據輸入得到一個權重,第二部分根據這個權重把 A 的各行進行混合。

如果我們假定模型裡有知識,那麼我們只能認為知識儲存在了A矩陣裡。多麼悲觀。

可是有了殘差就不一樣了。在模型裡進行的每一次矩陣乘法(每一次權重矩陣的混合)的結果都會被傳入到下一層。也就意味著每一層的權重或多或少都貢獻了知識。

如何驗證,殘差是否是按照上面的假設發揮作用的呢?

一個很簡單的做法,就是移除掉模型,比如Transformer,最後一層的殘差。僅僅把向量與矩陣相乘的結果作為輸出。

大意就是,模型的能力應該會受到最後面的知識儲存器的限制。而殘差連線,巧妙的把每一層都當做了知識儲存器。怎麼驗證這一點呢?

就是移除掉模型,比如Transformer,最後一層的殘差。僅僅把向量與矩陣相乘的結果作為輸出。

沒錯,Backpack Language Models 就是個驗證。當它把 k 設定為 1 時,模型的效能特別差。不無是個例證。

未完待續

什麼,你問我你看完了這個收穫了什麼?嘛,總該不是完全沒有收穫吧。

寫累了,祝大家吃好喝好,下次再見。

相關文章