CodeBlanks Logo Icon CodeBlanks

Meydan okuma 2

Transformer encoder tanımlarsın.

Meydan okuma: maskeli encoder

Bu meydan okumada yığın hâlinde çalışan, dolgu maskeli, pre-LN bir encoder bloğu yazacaksın:

def encoder_blogu(H, pad):
    a = layer_norm(H)
    H = H + dikkat(a, pad)                 # pre-LN
    return H + ffn(layer_norm(H))

İyi bir encoder'ın sağlaması gereken özellik: dolgu bağımsızlığı. Bir cümlenin sonuna ne kadar dolgu eklenirse eklensin, gerçek konumların çıktısı değişmemelidir.

Uygulama Dolgu bağımsız encoder

Verilen yardımcılarla yığınlı dikkat(a, pad) (anahtar ekseninde maskeli) ve pre-LN encoder_blogu(H, pad) fonksiyonlarını yaz. Aynı 3 kelimelik cümleyi bir kez 3, bir kez 6 uzunluğunda (3 dolgu) ver. Çıktı şekillerini aynı satırda, ardından ilk üç konumun iki durumda aynı olduğunu np.allclose 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)

def layer_norm(x, eps=1e-5):
    return (x - x.mean(-1, keepdims=True)) / np.sqrt(x.var(-1, keepdims=True) + eps)

rng = np.random.default_rng(0)
d = 8
Wq, Wk, Wv = rng.normal(size=(3, d, d)) * 0.4
W1, W2 = rng.normal(size=(d, 4 * d)) * 0.3, rng.normal(size=(4 * d, d)) * 0.3
ffn = lambda a: np.maximum(0, a @ W1) @ W2

gercek = rng.normal(size=(1, 3, d))
H3, pad3 = gercek, np.zeros((1, 3), dtype=bool)
H6 = np.concatenate([gercek, rng.normal(size=(1, 3, d))], axis=1)
pad6 = np.array([[False] * 3 + [True] * 3])

# 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)

def layer_norm(x, eps=1e-5):
    return (x - x.mean(-1, keepdims=True)) / np.sqrt(x.var(-1, keepdims=True) + eps)

rng = np.random.default_rng(0)
d = 8
Wq, Wk, Wv = rng.normal(size=(3, d, d)) * 0.4
W1, W2 = rng.normal(size=(d, 4 * d)) * 0.3, rng.normal(size=(4 * d, d)) * 0.3
ffn = lambda a: np.maximum(0, a @ W1) @ W2

gercek = rng.normal(size=(1, 3, d))
H3, pad3 = gercek, np.zeros((1, 3), dtype=bool)
H6 = np.concatenate([gercek, rng.normal(size=(1, 3, d))], axis=1)
pad6 = np.array([[False] * 3 + [True] * 3])

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

def encoder_blogu(H, pad):
    H = H + dikkat(layer_norm(H), pad)
    return H + ffn(layer_norm(H))

Y3, Y6 = encoder_blogu(H3, pad3), encoder_blogu(H6, pad6)
print(Y3.shape, Y6.shape)
print(np.allclose(Y3[0], Y6[0, :3]))

Beklenen çıktı

(1, 3, 8) (1, 6, 8)
True

Uygulama Model boyutu hesaplayıcı

Bir encoder-only modelin parametre sayısını veren boyut(V, n_max, d, L, f) fonksiyonunu yaz: kelime + konum gömmesi, L katman (dikkat 4·(d²+d), FFN d·f+f+f·d+d, 2 LayerNorm 4d) ve son LayerNorm (2d). BERT-base'e yakın (30522, 512, 768, 12, 3072) ve küçük bir model (8000, 128, 256, 4, 1024) için sayıları aynı satırda yazdır. Ardından küçük modelde FFN boyutu 4d yerine 2d yapılınca parametrelerin kaçta kaçının kaldığını round(..., 3) ile yazdır.

Başlangıç kodu

model.py
# buraya yaz

Örnek çözüm

model.py
def boyut(V, n_max, d, L, f):
    gomme = (V + n_max) * d
    katman = 4 * (d * d + d) + (d * f + f + f * d + d) + 4 * d
    return gomme + L * katman + 2 * d

print(boyut(30522, 512, 768, 12, 3072), boyut(8000, 128, 256, 4, 1024))
print(round(boyut(8000, 128, 256, 4, 512) / boyut(8000, 128, 256, 4, 1024), 3))

Beklenen çıktı

108890112 5240320
0.8

Soru ve cevaplar

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

1 Pre-LN ile post-LN arasındaki fark nedir?

  • Pre-LN hiç normalleştirmez
  • Post-LN maske kullanmaz
  • Hiçbir fark yoktur
  • Pre-LN normalleştirmeyi alt katmandan önce, artık yolunun dışında yapar Doğru cevap

Açıklama: Pre-LN'de artık yol (H + ...) normalleştirilmeden akar; derin ağlarda daha kararlıdır.

2 Pre-LN artık bağlantısını yaz.

Soru
H = H + dikkat(____(H), pad)
Cevap
H = H + dikkat(layer_norm(H), pad)

Açıklama: Pre-LN'de alt katmanın girişi normalleştirilir.

3 Eşleştir.

Kavram Anlamı
post-LN LN(H + f(H))
pre-LN H + f(LN(H))
dolgu maskesi Anahtar sütunlarını kapatır
dolgu bağımsızlığı Gerçek çıktı değişmez

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