來源:Deephub Imba
本文約4200字,建議閱讀8分鐘
本篇文章將通過寫出矩陣來查看關(guān)于自動注意力中不同的掩碼的一些細(xì)節(jié)。
在研究自注意力時,有很多名詞需要我們著重關(guān)注,比如填充掩碼,前瞻掩碼等等,但網(wǎng)上沒有太多注意力掩碼的教程和它是如何工作的信息,另外還有以下的細(xì)節(jié)需要詳細(xì)的解釋:
所以本篇文章將通過寫出矩陣來查看這些問題的細(xì)節(jié)。這樣可以對掩碼的工作原理有更好的了解。除此以外還可以連接到線性層是如何跨二維工作的,這樣可以解決上面第三點的疑問。
讓我們從一個有 4 個單詞的矩陣 X 開始。當(dāng)這些詞被轉(zhuǎn)換成它們的令牌嵌入,每個令牌的嵌入大小將是 3 個值。例如下面是我們的句子:“a b c D”。
現(xiàn)在讓我們把這些詞變成令牌。
向量a b c D各有3個分量,這個序列本質(zhì)上是由4個令牌符號組成的。每個令牌是3個值的向量。我們把這些符號變成一個矩陣X。
X是由向量a、b、c和D組成的4 × 3矩陣這是我們想要用自注意力來轉(zhuǎn)化的矩陣。
為了準(zhǔn)備計算注意力,我們必須首先使用加權(quán)矩陣生成鍵K、查詢Q和值V。對于這個句子,我們想把它轉(zhuǎn)換成一個4 * 2矩陣。所以每個權(quán)重矩陣的形狀都是3或2。例如下面是Q的權(quán)值矩陣QW。
將X矩陣轉(zhuǎn)換為Q(查詢)矩陣的權(quán)重,下面是利用QW矩陣可以得到查詢矩陣Q。
計算的過程如下:
現(xiàn)在我們有了 Q 的表示。注意力結(jié)果矩陣中的每個向量不是所有其他令牌的線性組合。而每個向量都是其自身和一些權(quán)重的線性組合。第一個向量只是 a 的線性組合。第二個只是b的線性組合。這種轉(zhuǎn)換不會弄亂矩陣內(nèi)的序列順序。a 仍然在矩陣的頂部,而 D 仍然在矩陣的底部。對于未來的操作,我將使用最右邊的矩陣來表示 Q ,這樣輕松地可視化 a、b、c 和 D 的向量,并且也可以說明這些向量是沒有被轉(zhuǎn)換為彼此相結(jié)合的某種組合。
對于K和V也是類似的,所以我們得到了從X矩陣和相應(yīng)矩陣權(quán)重計算的K,Q,V。
現(xiàn)在我們來計算這個序列的注意力。
最原始的自注意力是用下面的公式來定義的
為了更容易地可視化發(fā)生了什么,我將刪除d?常數(shù)。《The Attention is All You Need 》的作者聲明,使用標(biāo)量d?是因為“我們懷疑對于d?的大值,點積的量級變大,將softmax函數(shù)推到具有非常小的梯度的區(qū)域“。所以d?只是一個幫助數(shù)值量級轉(zhuǎn)換的標(biāo)量,所以在本文中不用不關(guān)心它,那么可以使用下面的公式來代替,也就是把d?刪除了
但是本文中是討論的掩碼遮蔽,這時等式就有點不同了,我將在接下來的部分中解釋。
首先QK?矩陣計算如下。
看很復(fù)雜,但是這個其實是由Q和K轉(zhuǎn)置相乘得到的矩陣,我們可以把它化簡成向量積的形式。并且令牌行和列,這樣以幫助可視化矩陣表示的內(nèi)容。
這樣是不是就好很多了,每個值基本上都乘以另一個值,包括矩陣中的自己。這個值表示當(dāng)將V應(yīng)用到這個矩陣時V中的每個分量將得到多少權(quán)重。
在學(xué)習(xí)如何掩碼注意力之前,我們首先需要查看沒有掩碼的注意力是如何工作的。
計算序列注意力的下一步是對QK?矩陣應(yīng)用softmax函數(shù)。那么就出現(xiàn)了一個問題,softmax應(yīng)該應(yīng)用在什么維度上?在論文提出的自注意力中,softmax函數(shù)應(yīng)用于每一行。
在沒有掩碼的情況下,softmax函數(shù)只是一個歸一化函數(shù)。所以為了減少可視化的復(fù)雜度,我們可以不在這個矩陣中表示它。
現(xiàn)在只剩下最后一步了,將QK?矩陣乘以V矩陣。QK?矩陣與V矩陣乘積就得到了子注意力計算的結(jié)果。
矩陣中的每個編碼是QK?矩陣中的值和權(quán)重的線性組合。實際上得到的矩陣中的每一行都是QK?矩陣中的相應(yīng)行和V矩陣中的相應(yīng)列的線性組合。不帶掩碼的注意力模塊的輸出可以理解為讓每個令牌注意所有其他令牌。這意味著每一個令牌對所有其他令牌都有影響。
對得到的矩陣也重新格式化一下:
QK?矩陣與V矩陣乘積的向量表示,注意力轉(zhuǎn)換本質(zhì)上產(chǎn)生了一組新的向量,序列中的每個單詞對應(yīng)一個向量。
在使用填充掩碼(padding mask)計算注意力之前,我們需要將掩碼 M 添加到等式中:
我們已經(jīng)有了QK?和V,但是M是什么樣的呢?我們的序列是:' a b c D '。
用一個更實際的例子替換這些任意:
I like coffee <PAD>
注意這里有一個PAD令牌。這個令牌出現(xiàn)的原因是,句子的長度是變化的而矩陣并不能處理不同的大小。所以為了把很多句子放在一起作為一批處理,可以在較短句子中添加令牌,使所有句子的長度相同。
但是使用PAD令牌的一個問題是PAD成為句子中最頻繁出現(xiàn)的部分。而訓(xùn)練時模型會注意到這一點,并錯誤的認(rèn)為PAD是句子的基礎(chǔ),這樣就會產(chǎn)生很多問題。
為了防止模型對 PAD令牌進(jìn)行建模,我們可以通過找到 QK? 矩陣中PAD位置并進(jìn)行屏蔽的方法來實現(xiàn)。如上例所示,D 是一個PAD令牌,如果我們想要屏蔽它則需要使用與 QK? 具有相同維度的掩碼,并在表示在要掩碼的列上使用 -∞。M矩陣將如下所示:
填充掩碼的矩陣表示中 D? 列是被屏蔽的,但 DQ 行不是。下一步是將M添加到QK?
任何數(shù)值與-∞ 相加結(jié)果都變?yōu)?-∞,所以結(jié)果列 D? 是 -∞ 列。那么當(dāng) softmax 應(yīng)用于矩陣時會發(fā)生什么?
Softmax后D?都是0,基本上不會影響權(quán)重矩陣中其他值的權(quán)重。這里的D 不是其他行的一部分,而是僅在其自己的 DQ 行中。這里我們不會擔(dān)心非∞ 值的 softmax ,因為該函數(shù)只是起到歸一化的作用。最后讓我們看看將權(quán)重矩陣乘以 V 矩陣時得到的矩陣的樣子。
通過將屏蔽QK?矩陣與V矩陣相乘得到最終的自注意力結(jié)果,讓我們仔細(xì)看看最終的矩陣。
結(jié)果矩陣中的每一行如何沒有 D? 分量。所以D對任何其他元素都沒有影響,這意味著任何PAD令牌(這里的D)對序列的其余部分都沒有影響。這就是使用對填充進(jìn)行掩碼的原因:不希望它影響序列中的任何其他令牌。
那么DQ 呢,它仍然存在并且沒有被遮蔽掉。這是因為如果DQ 被屏蔽了,矩陣中的 DQ 向量將在應(yīng)用 softmax 變換后產(chǎn)生一個均勻值的向量,也就是說 DQ 將丟失它之前擁有的所有信息。而我們進(jìn)行掩碼遮蔽的目的不是完全去除 D 的所有信息而是讓它不影響其他令牌。所以在結(jié)果矩陣中仍然需要關(guān)于 D 的信息,也就是說我們要告訴模型的是那里有一個PAD令牌,我們只希望PAD令牌不與其他的令牌令牌產(chǎn)生影響,但是PAD令牌的位置和信息模型還是要知道的。
那么如果同時屏蔽了 DQ 和 D?,生成的矩陣將如下所示:
填充掩碼同時覆蓋DQ和D?時的結(jié)果可以看到,由于 DQ 和 D? 是常數(shù),因此它們不會對結(jié)果增加太多。但是矩陣最后一部分的結(jié)果向量只是 V 的 1/4 加權(quán)分量的組合。這會導(dǎo)致 D 丟失其自身的所有信息,這也意味著結(jié)果向量中 D 的新表示將是 D 的的一個糟糕的表示方式。
Look-ahead mask (前瞻掩碼)最初來自 Attention is All You Need的論文。使用前瞻掩碼的目的是一次在整個文本序列上訓(xùn)練模型而不是一次訓(xùn)練一個單詞。原始的 Transformer 模型就是所謂的自回歸模型,它僅使用過去的數(shù)據(jù)進(jìn)行預(yù)測。因為最初的Transformer 是為翻譯而制作的,所以這種類型的模型是有意義的。在預(yù)測翻譯后的句子時,模型會一次預(yù)測一個單詞。比如:“How are you”。
該模型一次將句子翻譯成西班牙語:
如果想讓模型學(xué)習(xí)這種翻譯怎么辦?如果一次輸入一個詞,則需要輸入三次并且做三次的預(yù)測,這個過程非常緩慢,因為它需要模型的 S(序列長度)個預(yù)測才能從模型中獲得單句翻譯。但是如果將整個句子“cómo estás <END> ...”提供給它,并使用巧妙的掩碼技巧,讓模型就不能向前看到未來的令牌,只能看到過去的令牌。這樣,只需要一個推理步驟就能從模型中獲得整個句子的翻譯。這就是Look-ahead mask 的由來,所以我們這里將他翻譯為前瞻掩碼。
使用前瞻掩碼進(jìn)行自注意力的公式與填充掩碼相同。唯一的變化與掩碼有關(guān)。
前瞻掩碼的矩陣在右上角有一個三角形 -∞,在其他地方是 0。讓我們看看這如何影響權(quán)重矩陣的 softmax。
使用前瞻掩碼的掩碼查詢鍵矩陣的 Softmax時,權(quán)重矩陣會得到一些有趣的結(jié)果。第一行 aQ 僅由自身 a? 加權(quán)。由于 a 是序列中的第一個令牌,因此它不應(yīng)受到序列中任何其他令牌的影響,沒有不存在其他令牌。
在第二行,b 同時受到 a 和 b 的影響。由于 b 是第二個令牌,它應(yīng)該只受第一個令牌 a 的影響。
同理在最后一行中,序列中的最后一個令牌 D 受到所有其他令牌的影響,因為它是序列中的最后一個令牌,應(yīng)該具有序列中所有其他令牌的上下文。
讓我們看看掩碼如何影響注意力函數(shù)的輸出。
使用前瞻掩碼時自注意力的最終結(jié)果,與權(quán)重矩陣類似,結(jié)果向量僅受該向量中表示的令牌之前的令牌的影響。a 的新令牌嵌入在結(jié)果向量的第一行。由于這個令牌只有它自己的上下文,它只會是它自己的組合。
第二個令牌 b 具有 a 的上下文,因此結(jié)果向量是 a 和 b 的組合。
最后一個令牌 D 具有所有其他令牌的上下文,因此結(jié)果向量是所有其他令牌的組合。
為了可視化生成的矩陣有何不同,我將他們放在一起,下圖是使用 no mask、padding mask 和 look-ahead mask 時的 self-attention 函數(shù)的最終結(jié)果
最后一點要說明的是為什么要在多層中使用相同的掩碼。如果你仔細(xì)看了矩陣就會發(fā)現(xiàn)。
首先注意力函數(shù)時可以總結(jié)為從矩陣X到矩陣a的一個單一變換。
矩陣間的自注意力變換
向量的向量之間的自注意力變換
上面已經(jīng)講過了,自注意力轉(zhuǎn)換保留了每個向量的上下文。輸出序列只是輸入序列的形式變換。
假設(shè)我們想要屏蔽所有PAD令牌,并且我們認(rèn)為上面問題定義中的D 是一個PAD令牌。那么輸出 D? 仍然是一個 PAD令牌,只是這個令牌已經(jīng)被表示為一個轉(zhuǎn)換后的嵌入了。所以任何正在進(jìn)行的自注意力都需要一個掩碼來確保 PAD令牌不會影響任何其他令牌。
我們甚至可以把一個transformer想象成一系列的self-attention函數(shù)。線性層和歸一化層不會弄亂令牌之間的序列關(guān)系,所以在本例中可以忽略不計。
向量的向量之間的多重自注意力轉(zhuǎn)換,由于保留了自注意力層之間的序列,每個自注意力函數(shù)都需要使用相同的掩碼。在填充掩碼的例子中,如果掩碼只用在第一個自注意力層上,那么序列將不受第一個自注意力層中的PAD令牌的影響。而在所有其他層中因為缺少掩碼序列將會受到PAD令牌的影響,這樣就會產(chǎn)生糟糕的結(jié)果。
注意力掩碼本質(zhì)上是一種阻止模型看我們不想讓它看的信息的方法。這不是一種非常復(fù)雜的方法,但是它卻非常有效。我希望這篇文章能讓你更好地理解掩碼在自注意力中的作用,希望以上的矩陣計算是正確的,如果有錯誤,歡迎指出。