繼前一篇我們將分詞可以轉為能對應到想要的維度 embedding,今天要進到 Transformer 中最有名的注意力機制。
前情提要
我們將 token 轉為某種數字,但這個數字還只是單純文字跟句子中的位置的數字,我們需要讓文字可以引含上下文的意義在其中 e.g. 「寫」來說,「寫」生是繪畫、「寫」作是文字創作,雖然都是「寫」,但實際上語意卻相去甚遠
為了知道每一個 token embedding 在上下文中的關係,我們需要讓每個字與各個字之間建立聯繫
import torch
inputs = torch.tensor(
[[0.43, 0.15, 0.89], # Your (x^1)
[0.55, 0.87, 0.66], # journey (x^2)
[0.57, 0.85, 0.64], # starts (x^3)
[0.22, 0.58, 0.33], # with (x^4)
[0.77, 0.25, 0.10], # one (x^5)
[0.05, 0.80, 0.55]] # step (x^6)
)
先建立一個 Your journey starts with one step 的矩陣,接著以第二個字為例,計算字與字之間的內積。
query = inputs[1] #取第二個字出來
attn_scores_2 = torch.empty(inputs.shape[0]) #建立第二個字的注意力分數
for i, x_i in enumerate(inputs):
attn_scores_2[i] = torch.dot(x_i, query) #計算數字二與所有文字各自的內積
最後將這些內積做 normalize,讓所有值可以加總起來為 1,這個機制設計是為了讓值與值之間可有可比性,就像是一個縮放機制。
在實務上,最常 normalize 的手法是 softmax,softmax 會投射出單純值(不會有負數),在處理值中如果有極端值分布時,會放大相對差距,讓整個梯度計算上更有利。
def softmax_naive(x):
return torch.exp(x) / torch.exp(x).sum(dim=0)
attn_weights_2_naive = softmax_naive(attn_scores_2)
To Be Continued