CodeBlanks Logo Icon CodeBlanks

Attention katmanı

Multi-head attention katmanı eklersin.

Gömme ve dikkat katmanı

Kimlikler, bir gömme tablosundan (sözlük boyutu × d) satır seçilerek vektöre çevrilir. Ardından yığın hâlinde ölçekli dikkat uygulanır; şekiller (yığın, n, d) olur:

E = rng.normal(size=(len(sozluk), d)) * 0.5
H = E[X]                                 # (5, 5, d)
skor = Q @ K.transpose(0, 2, 1) / np.sqrt(d)   # (5, 5, 5)

NumPy'da E[X], X'in her kimliği için E'nin o satırını alır: bu, nn.Embedding'in yaptığı işin aynısıdır.

Dolguyu maskelemek

Maske, anahtar (sütun) eksenine uygulanır: pad[:, None, :] şekli (yığın, 1, n) olur ve tüm sorgu satırlarına yayılır. Dolgu sütunlarının skoru −1e9 yapılınca ağırlıkları sıfırlanır:

def dikkat(Q, K, V, pad):
    d = Q.shape[-1]
    skor = Q @ K.transpose(0, 2, 1) / np.sqrt(d)
    skor = np.where(pad[:, None, :], -1e9, skor)
    A = softmax(skor)
    return A @ V, A

−∞ yerine −1e9 kullanmak, tamamen dolgu olan bir satırda NaN çıkmasını önler.

Uygulama Maskeli dikkat katmanı

Verilen dikkat şablonunu tamamla (maskeyi uygula). Gömme H = E[X] ile Q, K, V'yi hesaplayıp dikkati uygula. Çıktının ve ağırlıkların şeklini aynı satırda yazdır. Ardından üçüncü cümlenin ("iyi") ağırlık satırlarından ilkini np.round(..., 3) ile ve dolgu sütunlarına giden toplam ağırlığı round(..., 6) ile yazdır.

Başlangıç kodu

model.py
import numpy as np

def softmax(z, eksen=-1):
    e = np.exp(z - z.max(axis=eksen, keepdims=True))
    return e / e.sum(axis=eksen, keepdims=True)

metinler = ["film çok iyi", "çok kötü bir film", "iyi", "oyuncular iyi ama senaryo kötü", "kötü"]
sozluk = {"<pad>": 0}
for c in metinler:
    for k in c.split():
        sozluk.setdefault(k, len(sozluk))

def kodla(c, n=5):
    ids = [sozluk[k] for k in c.split()][:n]
    return ids + [0] * (n - len(ids))

X = np.array([kodla(c) for c in metinler])
pad = X == 0

rng = np.random.default_rng(0)
d = 8
E = rng.normal(size=(len(sozluk), d)) * 0.5
Wq, Wk, Wv = rng.normal(size=(3, d, d)) * 0.5

# buraya yaz

Örnek çözüm

model.py
import numpy as np

def softmax(z, eksen=-1):
    e = np.exp(z - z.max(axis=eksen, keepdims=True))
    return e / e.sum(axis=eksen, keepdims=True)

metinler = ["film çok iyi", "çok kötü bir film", "iyi", "oyuncular iyi ama senaryo kötü", "kötü"]
sozluk = {"<pad>": 0}
for c in metinler:
    for k in c.split():
        sozluk.setdefault(k, len(sozluk))

def kodla(c, n=5):
    ids = [sozluk[k] for k in c.split()][:n]
    return ids + [0] * (n - len(ids))

X = np.array([kodla(c) for c in metinler])
pad = X == 0

rng = np.random.default_rng(0)
d = 8
E = rng.normal(size=(len(sozluk), d)) * 0.5
Wq, Wk, Wv = rng.normal(size=(3, d, d)) * 0.5

def dikkat(Q, K, V, pad):
    skor = Q @ K.transpose(0, 2, 1) / np.sqrt(Q.shape[-1])
    skor = np.where(pad[:, None, :], -1e9, skor)
    A = softmax(skor)
    return A @ V, A

H = E[X]
Y, A = dikkat(H @ Wq, H @ Wk, H @ Wv, pad)
print(Y.shape, A.shape)
print(np.round(A[2, 0], 3))
print(round(float(A[pad[:, None, :].repeat(5, axis=1)].sum()), 6))

Beklenen çıktı

(5, 5, 8) (5, 5, 5)
[1. 0. 0. 0. 0.]
0.0

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 E (10, 8) ve X (5, 5) ise E[X]'in şekli nedir?

  • (5, 8)
  • (5, 5)
  • (5, 5, 8) Doğru cevap
  • (10, 8)

Açıklama: Her kimlik 8 boyutlu bir vektöre dönüşür.

2 Maskeyi anahtar eksenine yay.

Soru
skor = np.where(pad[:, ____, :], -1e9, skor)
Cevap
skor = np.where(pad[:, None, :], -1e9, skor)

Açıklama: None yeni bir eksen ekler: (yığın, 1, n).

3 Şekilleri eşleştir (yığın 5, n 5, d 8).

Kavram Anlamı
E[X] (5, 5, 8)
skor (5, 5, 5)
pad[:, None, :] (5, 1, 5)
E (9, 8)

Uzman bölümündeki tüm dersler