Skip to content

Positional Encoding Sinusoidal

1、劇場的座位與混亂的演員

想像你是一家大型劇院的導演,正在排練一齣重要的舞台劇。這齣劇有 10 位演員,他們需要在舞台上按照特定順序出場和說話。

今天來了新的舞台監督,他負責記錄每位演員的台詞和走位。但他有個特別的習慣:他不用座位編號來記錄演員,只記錄演員的臉。

「第一位上台的是小明的臉,第二位是小華的臉,第三位是小美的臉...」舞台監督這樣記錄著。

排練開始了。演員們上台,舞台監督看著他們的臉,開始唸出他們的台詞順序。

但問題來了。當小華和小明長得很像時,舞台監督會搞混:「咦?這個是小明還是小華?我該讓他說第一句還是第二句台詞?」

更糟的是,當演員們在台上移動時,舞台監督完全亂了:「剛才站在左邊的是誰?現在站在中間的又是誰?他們的台詞順序應該是什麼?」

整個排練陷入混亂,因為舞台監督只認得演員的臉,卻不知道他們在舞台上的「位置」和「出場順序」。

2、Transformer 的困境:沒有順序觀念的平行處理

這個劇場的故事,完美對應了 Transformer 模型在處理序列資料時遇到的根本問題。

在 Transformer 出現之前,處理序列資料的模型(如 RNN、LSTM)是逐個處理詞彙的: - 看完第一個詞,再看第二個詞,再看第三個詞... - 就像舞台監督按照出場順序一個個認識演員 - 這種方式很慢,但模型自然知道詞的順序

但 Transformer 革命性地採用了平行處理: - 一次看完所有詞彙 - 同時計算每個詞與其他詞的關係 - 就像舞台監督同時看到所有演員的臉

這帶來巨大的速度提升,但也產生了一個問題:當所有詞同時被輸入時,模型怎麼知道哪個詞在先、哪個詞在後?

\[ \text{輸入序列} = [\text{我}, \text{愛}, \text{你}] \]

對 Transformer 來說,如果不加任何處理,這個序列和 \([\text{你}, \text{愛}, \text{我}]\) 是完全一樣的。因為它只看詞的內容,不看詞的位置。

就像舞台監督只看到「小明、小華、小美」這三張臉,但不知道他們應該按照什麼順序說話。

痛點:Transformer 的平行處理架構喪失了序列的順序資訊,導致模型無法區分「我愛你」和「你愛我」這種詞相同但順序不同的句子。

3、傳統解法:用數字編號的困境

你可能會說:「那就給每個詞一個數字編號啊!第 1 個詞加 1,第 2 個詞加 2,第 3 個詞加 3,不就解決了嗎?」

這就像舞台監督終於想通了,開始給演員貼號碼牌: - 小明貼 1 號 - 小華貼 2 號 - 小美貼 3 號

這個方法乍看可行,但很快就出現新問題:

3-1、數字太大會淹沒詞義

假設句子很長,有 1000 個詞: - 第 1 個詞:\([0.5, 0.2, -0.1] + [1, 1, 1] = [1.5, 1.2, 0.9]\) - 第 500 個詞:\([0.5, 0.2, -0.1] + [500, 500, 500] = [500.5, 500.2, 499.9]\)

原本的詞義 \([0.5, 0.2, -0.1]\) 完全被巨大的位置數字淹沒了。就像演員的號碼牌太大,完全遮住了他們的臉,舞台監督只看得到號碼,認不出誰是誰。

3-2、數字沒有相對意義

另一個問題是:數字 1 和 2 的關係,與數字 100 和 101 的關係,在數學上是一樣的(都相差 1)。但在語言中,句子開頭的相鄰詞關係,和句子結尾的相鄰詞關係,應該要有某種相似性。

就像在舞台上,位置 1 和 2 的演員關係,應該類似於位置 101 和 102 的演員關係(都是相鄰的演員)。但用簡單的整數編號,無法體現這種模式。

痛點:簡單的整數編號會讓位置資訊壓過詞義資訊,且無法捕捉位置之間的相對關係模式。

4、Sinusoidal 位置編碼:用波紋定位的智慧

Google 的研究者在 "Attention Is All You Need" 論文中提出了一個優雅的解法:用正弦和餘弦函數來編碼位置

這就像在劇場的地板上畫上特殊的波紋圖案: - 每個位置有不同的波紋 - 波紋的形狀隨著位置有規律地變化 - 相鄰位置的波紋相似但不同 - 遠處位置的波紋完全不同

4-1、位置編碼的數學公式

對於位置 \(pos\) 的第 \(i\) 個維度,位置編碼的計算公式是:

\[ PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) \]
\[ PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) \]

其中: - \(pos\) 是詞在序列中的位置(0, 1, 2, ...) - \(i\) 是維度索引(0, 1, 2, ..., \(d_{model}/2 - 1\)) - \(d_{model}\) 是詞向量的維度

這個公式的巧妙之處在於:不同維度使用不同的頻率

4-2、用實際數字來感受

假設 \(d_{model} = 4\)(只有 4 維,方便理解),我們來計算幾個位置的編碼:

對於 \(i=0\): - 頻率分母:\(10000^{0/4} = 10000^0 = 1\) - 所以 \(\frac{pos}{1} = pos\)

對於 \(i=1\): - 頻率分母:\(10000^{1/4} = 10000^{0.25} \approx 10\) - 所以 \(\frac{pos}{10}\)

現在計算位置 0、1、2、3 的編碼:

位置 0 (\(pos=0\)): - \(PE_{(0,0)} = \sin(0/1) = \sin(0) = 0\) - \(PE_{(0,1)} = \cos(0/1) = \cos(0) = 1\) - \(PE_{(0,2)} = \sin(0/10) = \sin(0) = 0\) - \(PE_{(0,3)} = \cos(0/10) = \cos(0) = 1\)

\[ PE_0 = [0, 1, 0, 1] \]

位置 1 (\(pos=1\)): - \(PE_{(1,0)} = \sin(1/1) = \sin(1) \approx 0.84\) - \(PE_{(1,1)} = \cos(1/1) = \cos(1) \approx 0.54\) - \(PE_{(1,2)} = \sin(1/10) = \sin(0.1) \approx 0.10\) - \(PE_{(1,3)} = \cos(1/10) = \cos(0.1) \approx 0.995\)

\[ PE_1 \approx [0.84, 0.54, 0.10, 0.995] \]

位置 2 (\(pos=2\)): - \(PE_{(2,0)} = \sin(2/1) = \sin(2) \approx 0.91\) - \(PE_{(2,1)} = \cos(2/1) = \cos(2) \approx -0.42\) - \(PE_{(2,2)} = \sin(2/10) = \sin(0.2) \approx 0.20\) - \(PE_{(2,3)} = \cos(2/10) = \cos(0.2) \approx 0.98\)

\[ PE_2 \approx [0.91, -0.42, 0.20, 0.98] \]

位置 3 (\(pos=3\)): - \(PE_{(3,0)} = \sin(3/1) = \sin(3) \approx 0.14\) - \(PE_{(3,1)} = \cos(3/1) = \cos(3) \approx -0.99\) - \(PE_{(3,2)} = \sin(3/10) = \sin(0.3) \approx 0.30\) - \(PE_{(3,3)} = \cos(3/10) = \cos(0.3) \approx 0.955\)

\[ PE_3 \approx [0.14, -0.99, 0.30, 0.955] \]

4-3、把位置編碼加入詞向量

假設詞「我」的向量是 \([1, 0, 1, 0]\),那麼在位置 1 時:

\[ \text{最終向量} = \text{詞向量} + PE_1 \]
\[ = [1, 0, 1, 0] + [0.84, 0.54, 0.10, 0.995] \]
\[ = [1.84, 0.54, 1.10, 0.995] \]

如果「我」出現在位置 2:

\[ = [1, 0, 1, 0] + [0.91, -0.42, 0.20, 0.98] \]
\[ = [1.91, -0.42, 1.20, 0.98] \]

同一個詞「我」,在不同位置就有了不同的向量表示,模型就能區分它們。

痛點:Sinusoidal 位置編碼透過不同頻率的正弦餘弦函數,為每個位置產生唯一的向量,加到詞向量上,讓模型既能保留詞義又能知道詞的位置。

5、Sinusoidal 編碼的三大優勢

5-1、數值範圍固定,不會淹沒詞義

正弦和餘弦函數的值永遠在 \([-1, 1]\) 之間。無論位置多大:

\[ -1 \leq \sin(\cdot) \leq 1 \]
\[ -1 \leq \cos(\cdot) \leq 1 \]

所以: - 位置 1 的編碼:\([0.84, 0.54, 0.10, 0.995]\) - 位置 1000 的編碼:仍然是 \([-1, 1]\) 之間的值

詞向量不會被巨大的數字淹沒,詞義和位置資訊能完美共存。就像舞台上的波紋永遠是柔和的線條,不會遮住演員的臉。

痛點:固定範圍的數值確保位置資訊不會壓過詞義資訊,讓模型能同時兼顧「誰在說話」和「在第幾個位置說話」。

5-2、可以處理任意長度的序列

Sinusoidal 編碼是函數定義的,不是學習出來的: - 學習式編碼:只能處理訓練時見過的最大長度 - Sinusoidal 編碼:任何位置 \(pos\) 都能計算

就像舞台上的波紋圖案可以無限延伸,不管劇場有多大,都能畫出對應的波紋。

痛點:Sinusoidal 編碼讓模型在推論時能處理比訓練時更長的序列,具有外推能力。

5-3、可以捕捉相對位置關係

Sinusoidal 編碼有個優雅的數學性質:對於固定的偏移量 \(k\)\(PE_{pos+k}\) 可以表示為 \(PE_{pos}\) 的線性函數。

因為三角函數的和角公式:

\[ \sin(pos + k) = \sin(pos)\cos(k) + \cos(pos)\sin(k) \]
\[ \cos(pos + k) = \cos(pos)\cos(k) - \sin(pos)\sin(k) \]

這表示模型可以輕易學會「相對位置」的關係。就像舞台監督知道,不管演員在哪裡,「站在他右邊三公尺的人」都有固定的相對關係。

痛點:這個性質讓模型能有效捕捉詞與詞之間的相對距離關係,這對理解語言結構至關重要。

6、總結:Sinusoidal 的智慧

Sinusoidal 位置編碼就像在語言的河流中投入不同頻率的石子,激起一圈圈規律的波紋。每個詞都在自己的位置上,帶著獨特的波紋印記,但這些印記之間又有著和諧的數學關係。

它解決了 Transformer 的三大痛點: 1. 順序遺失:為每個詞加上位置指紋 2. 數值淹沒:固定範圍 \(-1\)\(1\),和諧共存 3. 長度限制:函數定義,無限延伸 4. 相對關係:三角函數性質,自然捕捉距離

這就像那位聰明的舞台監督,終於學會在地上畫波紋,讓每個位置都有獨特的印記,演員們無論怎麼移動,他都能知道他們應該在哪個位置、說什麼台詞。