如何理解Transformers中矩陣點(diǎn)積計(jì)算詞向量的相似度
** 先聲明,下面的過(guò)程都是我自己的理解,可能不一定正確,大家參考,有不對(duì)的,歡迎評(píng)論區(qū)指正。**
最近在看Transformer的原理,其中通過(guò)點(diǎn)積計(jì)算詞向量相似度的邏輯優(yōu)點(diǎn)懵,思考了許久貌似開(kāi)竅了,先上計(jì)算相似度的代碼:
import torch
from math import sqrt
query = key = value = inputs_embeds
dim_k = key.size(-1) # 獲得最后一個(gè)維度的大小(768)
scores = torch.bmm(query, key.transpose(1,2)) / sqrt(dim_k)
scores.size()
torch.Size([1, 5, 5])
inputs_embeds是詞向量矩陣
inputs_embeds = token_emb(inputs.input_ids)
inputs_embeds.size()
torch.Size([1, 5, 768])
key.transpose(1,2) 做了矩陣的轉(zhuǎn)置,也就是把最后兩個(gè)維度互換了一下,相當(dāng)于列轉(zhuǎn)行
torch.bmm(query, key.transpose(1,2))是對(duì)兩個(gè)矩陣做點(diǎn)積,計(jì)算相似度,而最后除以sqrt(dim_k)則是進(jìn)行歸一化處理
最終這個(gè)Score實(shí)際上就是自注意力計(jì)算詞向量相似度的分?jǐn)?shù),最終得到一個(gè)5x5的矩陣,前面的1代表批次可以先不考慮。
那么為什么做個(gè)點(diǎn)積就可以計(jì)算相似度呢?我們先來(lái)看下向量點(diǎn)積的含義:
點(diǎn)積(Dot Product)是一種常見(jiàn)的計(jì)算兩個(gè)向量相似度的方法。當(dāng)兩個(gè)向量進(jìn)行點(diǎn)積操作時(shí),結(jié)果的大小可以反映兩個(gè)向量的相似性。這是因?yàn)辄c(diǎn)積操作考慮了向量的方向和大小。
假設(shè)我們有兩個(gè)向量 A 和 B,它們的點(diǎn)積定義為:
cssCopy code A . B = |A| * |B| * cos(θ)其中,|A| 和 |B| 分別是 A 和 B 的長(zhǎng)度,θ 是 A 和 B 之間的夾角。
可以看到,當(dāng) A 和 B 的方向相同時(shí)(即它們的夾角接近0),cos(θ) 接近 1,所以 A . B 較大。這表明 A 和 B 很相似。
反之,當(dāng) A 和 B 的方向相反時(shí)(即它們的夾角接近180度),cos(θ) 接近 -1,所以 A . B 較小,甚至為負(fù)。這表明 A 和 B 不相似。
當(dāng) A 和 B 互相垂直時(shí)(即它們的夾角為90度),cos(θ) 為 0,所以 A . B 為 0。這表明 A 和 B 沒(méi)有相似性。
因此,通過(guò)計(jì)算向量的點(diǎn)積,我們可以得到一個(gè)衡量?jī)蓚€(gè)向量相似性的標(biāo)量值。
在深度學(xué)習(xí)中,尤其是在自然語(yǔ)言處理和推薦系統(tǒng)中,我們經(jīng)常需要衡量和比較向量(例如,單詞嵌入或用戶和物品的嵌入)的相似性。在這些情況下,點(diǎn)積是一種簡(jiǎn)單且有效的方法。
因?yàn)樵~向量表示了一個(gè)詞的多個(gè)方面的屬性,比如上面例子中可以理解為每個(gè)詞定義了768個(gè)屬性,那么我們用一個(gè)例子來(lái)類比:
假設(shè)有三個(gè)人分別是小張、小明和小紅,他們有4個(gè)屬性,分別是:愛(ài)好、性別、年齡、籍貫;那么三個(gè)人的屬性如下
| 姓名 | 性別 | 年齡 | 籍貫 | 愛(ài)好 |
|---|---|---|---|---|
| 小張 | 男 | 青年 | 浙江 | 音樂(lè) |
| 小明 | 男 | 中年 | 湖北 | 繪畫 |
| 小紅 | 女 | 青年 | 江蘇 | 音樂(lè) |
那么,我們可以把上面的表格轉(zhuǎn)換為一個(gè)矩陣:
[
[男, 青年, 浙江, 音樂(lè)],
[男, 中年, 湖北, 繪畫],
[女, 青年, 江蘇, 音樂(lè)],
]
然后我們把這個(gè)矩陣轉(zhuǎn)置:
[
[男, 男, 女]
[青年, 中年, 青年]
[浙江, 湖北, 江蘇]
[音樂(lè), 繪畫, 音樂(lè)]
]
當(dāng)然,我們來(lái)看一個(gè)簡(jiǎn)單的例子,以更好地理解矩陣點(diǎn)積(矩陣乘法)的過(guò)程。
假設(shè)我們有以下兩個(gè)矩陣 A 和 B:
矩陣A:
Copy code1 2 3 4 5 6矩陣B:
Copy code7 8 9 10 11 12這里,矩陣A的形狀是(2,3),矩陣B的形狀是(3,2)。我們可以進(jìn)行矩陣乘法,因?yàn)锳的列數(shù)等于B的行數(shù)。結(jié)果矩陣C的形狀將會(huì)是(2,2)。
我們?nèi)绾斡?jì)算結(jié)果矩陣C的每個(gè)元素呢?我們來(lái)看一個(gè)具體的例子,計(jì)算結(jié)果矩陣C的第一個(gè)元素:
C[0,0] = A[0,0]B[0,0] + A[0,1]*B[1,0] + A[0,2]*B[2,0] = 1*7 + 2*9 + 311 = 58
同理,我們可以計(jì)算結(jié)果矩陣C的其他元素。最終,矩陣C將是:
58 64 139 154這就是矩陣乘法(或者說(shuō)矩陣點(diǎn)積)的過(guò)程。希望這個(gè)例子能幫助你理解矩陣乘法。
所以上面的矩陣點(diǎn)乘后,結(jié)果矩陣就變成:
[
[男 * 男 + 青年 * 青年 + 浙江 * 浙江 + 音樂(lè) * 音樂(lè),男 * 男 + 青年 * 中年 + 浙江 * 湖北 + 音樂(lè) * 繪畫,男 * 女 + 青年 * 青年 + 浙江 * 江蘇 + 音樂(lè) * 音樂(lè)],
[男 * 男 + 中年 * 青年 + 湖北 * 浙江 + 繪畫 * 音樂(lè),男 * 男 + 中年 * 中年 + 湖北 * 湖北 + 繪畫 * 繪畫,男 * 女 + 中年 * 青年 + 湖北 * 江蘇 + 繪畫 * 音樂(lè)],
[女 * 男 + 青年 * 青年 + 江蘇 * 浙江 + 音樂(lè) * 音樂(lè),女 * 男 + 青年 * 中年 + 江蘇 * 湖北 + 音樂(lè) * 繪畫,女 * 女 + 青年 * 青年 + 江蘇 * 江蘇 + 音樂(lè) * 音樂(lè)]
]
為了便于計(jì)算,我們將值相等的點(diǎn)積值設(shè)為1,不相等設(shè)為0,于是,整個(gè)矩陣就變成了:
[
[4, 1, 2]
[1, 4, 0]
[2, 0, 4]
]
顯然這就變成了3 x 3的了,我們可以認(rèn)為這個(gè)矩陣代表了,三個(gè)人之間兩兩的關(guān)聯(lián)度:
| 小張 | 小明 | 小紅 | |
|---|---|---|---|
| 小張 | 4 | 1 | 2 |
| 小明 | 1 | 4 | 0 |
| 小紅 | 2 | 0 | 4 |
于是,當(dāng)你遇到任何一個(gè)人,你都可以說(shuō)出來(lái)他和其他人的相似性。
詞向量和這個(gè)過(guò)程應(yīng)該是類似的,只不過(guò),它的屬性有768個(gè)之多。因此在后續(xù)的匹配當(dāng)中,每個(gè)詞都可以找到與之相似度分?jǐn)?shù)最高的一個(gè)關(guān)聯(lián)詞。但是,目前還有一個(gè)問(wèn)題,就是這個(gè)相似度評(píng)分無(wú)法解決同意詞的問(wèn)題,同樣是“繪畫”動(dòng)詞和名詞的相似度是一樣的。要解決這個(gè)問(wèn)題,就得要通過(guò)多層編碼器的神經(jīng)網(wǎng)絡(luò)來(lái)解決了,這也是編碼過(guò)程要解決的主要問(wèn)題。
代碼的最后把相似度除以了sqrt(dim_k),這一步是為了進(jìn)行歸一化,進(jìn)行的縮放處理:
/ sqrt(dim_k)
:這是一個(gè)縮放操作,將上述計(jì)算得到的張量除以 dim_k 的平方根。這是一種常見(jiàn)的歸一> 化手段,dim_k 通常是 key 的維度。在 "Scaled Dot-Product Attention" 中,這樣的縮放操> 作可以防止點(diǎn)積在維度很高時(shí)變得過(guò)大。
最后,對(duì)相似度進(jìn)行softmax處理,就轉(zhuǎn)換為了概率:
import torch.nn.functional as F
weights = F.softmax(scores, dim=-1)
weights.sum(dim=-1)
這樣就變成了A詞和B詞的相似度概率,找到和A詞最匹配的詞就是找概率對(duì)打的。