Ana içeriğe geç

Orta11 dk

Transformer mimarisi: bütün resim

Önkoşul:GPT ile "Attention is All You Need" farkı

Kanca

  1. dersten beri, bir Transformer’ın parçalarını tek tek inceledik: attention, çoklu başlık, pozisyonel kodlama, layer norm, FFN, encoder-decoder. Bu ders hiçbir yeni parça eklemiyor — sadece hepsini, gerçekten eğitilmiş tek bir modelde bir araya getiriyor.

Sezgi

Aşağıdaki boru hattı, gerçekten eğitilmiş (kayıp 0.0001’e inmiş) bir mini-GPT’nin “ABCAB” girdisini işleyişini gösteriyor — her sayı, gerçek bir ileri geçişten yakalandı, elle tasarlanmadı. Bir aşamaya tıkla ilgili derse git; “Transformer Bloğu”na tıkla, içini aç ve gerçek dikkat matrisini gör.

Gerçekten eğitilmiş, 6.179 parametrelik bir mini-GPT'nin "ABCAB" girdisini işleyişi (eğitim kaybı: 0.000091). Bir aşamaya tıkla, ilgili derse git; Transformer Bloğu'na tıkla, içini aç.

Girdi metni
ABCAB
↓
TokenizationGömme + Pozisyonel Kodlama
↓
Transformer Bloğu × 2▼ içini aç
↓
Son Layer NormLinear + Softmax
↓
Kelime dağarcığı olasılıkları
A
0.000
B
0.000
C
1.000

Model'in tahmini: "C"

Mekanizma

Bu tam model, 9-18. derste kurduğumuz her parçayı birleştiriyor:

Tam mimari: tüm parçalar bir arada

# Bu ders, 9-18. derste tek tek kurduğumuz her parçayı, N blok üst üste yığarak
# birleştiriyor: gömme + pozisyonel kodlama (13. ders) -> N x [maskeli self-attention
# (11. ders) -> artık bağlantı + layer norm (14. ders) -> FFN (15. ders) -> artık
# bağlantı + layer norm] -> son layer norm -> çıktı projeksiyonu (dil modeli başlığı).
class TransformerBlogu(nn.Module):
    def __init__(self, d_model):
        super().__init__()
        self.Wq = nn.Linear(d_model, d_model, bias=False)
        self.Wk = nn.Linear(d_model, d_model, bias=False)
        self.Wv = nn.Linear(d_model, d_model, bias=False)
        self.norm1 = nn.LayerNorm(d_model)
        self.ffn = nn.Sequential(nn.Linear(d_model, 4 * d_model), nn.GELU(), nn.Linear(4 * d_model, d_model))
        self.norm2 = nn.LayerNorm(d_model)

    def forward(self, h, maske):
        Q, K, Vv = self.Wq(h), self.Wk(h), self.Wv(h)
        puanlar = (Q @ K.transpose(-2, -1)) / (h.shape[-1] ** 0.5)
        puanlar = puanlar.masked_fill(maske == 0, float("-inf"))
        agirliklar = F.softmax(puanlar, dim=-1)
        h = self.norm1(h + agirliklar @ Vv)
        h = self.norm2(h + self.ffn(h))
        return h, agirliklar

class MiniGPT(nn.Module):
    def __init__(self, vocab_size, d_model, pencere, n_blok):
        super().__init__()
        self.gomme = nn.Embedding(vocab_size, d_model)
        self.pos = nn.Embedding(pencere, d_model)
        self.bloklar = nn.ModuleList([TransformerBlogu(d_model) for _ in range(n_blok)])
        self.son_norm = nn.LayerNorm(d_model)
        self.cikis = nn.Linear(d_model, vocab_size)

    def forward(self, x_ids):
        B, T = x_ids.shape
        h = self.gomme(x_ids) + self.pos(torch.arange(T))
        tum_agirliklar = []
        maske = torch.tril(torch.ones(T, T))
        for blok in self.bloklar:
            h, agirliklar = blok(h, maske)
            tum_agirliklar.append(agirliklar)
        h = self.son_norm(h)
        logit = self.cikis(h)
        return logit, tum_agirliklar

model = MiniGPT(V, D, PENCERE, N_BLOK)
parametre_sayisi = sum(p.numel() for p in model.parameters())
print(f"MiniGPT: {N_BLOK} blok, d_model={D}, toplam parametre: {parametre_sayisi:,}")
print("Mimari: Gömme+PozKodlama -> [Maskeli Self-Attn -> Add&Norm -> FFN -> Add&Norm] x 2 -> Son Norm -> Çıktı")
MiniGPT: 2 blok, d_model=16, toplam parametre: 6,179
Mimari: Gömme+PozKodlama -> [Maskeli Self-Attn -> Add&Norm -> FFN -> Add&Norm] x 2 -> Son Norm -> Çıktı

Gerçek eğitim: kayıp 0.0001'e iniyor

optimize_edici = torch.optim.Adam(model.parameters(), lr=0.01)
for adim in range(400):
    baslangic = torch.randint(0, len(ids) - PENCERE - 1, (8,))
    girdi = torch.stack([ids[b:b + PENCERE] for b in baslangic])
    hedef = torch.stack([ids[b + 1:b + PENCERE + 1] for b in baslangic])
    logit, _ = model(girdi)
    kayip = F.cross_entropy(logit.reshape(-1, V), hedef.reshape(-1))
    optimize_edici.zero_grad()
    kayip.backward()
    optimize_edici.step()
print(f"400 adım sonra kayıp: {kayip.item():.6f}")
400 adım sonra kayıp: 0.000091

Şimdi bu eğitilmiş modeli, tek bir örnekten geçirip tüm ara çıktıları yakalayalım:

'ABCAB' girdisi, uçtan uca

# Şimdi tek bir örneği, tüm boru hattından (pipeline) geçirip, her aşamada ne
# olduğunu yakalayalım -- bu veri, sayfadaki TransformerBoruHatti bileşenini besleyecek.
model.eval()
ORNEK_METIN = "ABCAB"
ornek_ids = torch.tensor([[stoi[c] for c in ORNEK_METIN]])
with torch.no_grad():
    logit, tum_agirliklar = model(ornek_ids)
    olasiliklar = F.softmax(logit[0, -1], dim=-1)

print(f"\nGirdi: '{ORNEK_METIN}' ({len(ORNEK_METIN)} token)")
print(f"Blok 1 dikkat matrisi şekli: {tuple(tum_agirliklar[0][0].shape)}")
print(f"Blok 2 dikkat matrisi şekli: {tuple(tum_agirliklar[1][0].shape)}")
print(f"\nSon token'dan sonraki kelime dağarcığı olasılıkları:")
for tok, p in zip(VOCAB, olasiliklar.tolist()):
    print(f"  {tok:<4} {p:.4f}")
tahmin = VOCAB[olasiliklar.argmax().item()]
print(f"\nModel '{ORNEK_METIN}'den sonra '{tahmin}' geleceğini tahmin ediyor -- örüntüye ({ORNEK_METIN} -> C) uyumlu.")

Girdi: 'ABCAB' (5 token)
Blok 1 dikkat matrisi şekli: (5, 5)
Blok 2 dikkat matrisi şekli: (5, 5)

Son token'dan sonraki kelime dağarcığı olasılıkları:
  A    0.0000
  B    0.0000
  C    0.9999

Model 'ABCAB'den sonra 'C' geleceğini tahmin ediyor -- örüntüye (ABCAB -> C) uyumlu.

Matematik

Tam boru hattı, tek formülde
h0=Go¨mme(x)+PozKodlama(x)h_0 = \text{Gömme}(x) + \text{PozKodlama}(x)hi=TransformerBlog˘ui(hi−1)i=1,…,N\begin{gathered} h_i = \text{TransformerBloğu}_i(h_{i-1}) \\ i = 1, \dots, N \end{gathered}P(sonraki token)=softmax(Linear(LayerNorm(hN)))\begin{aligned} &P(\text{sonraki token}) = \\ &\quad \text{softmax}(\text{Linear}(\text{LayerNorm}(h_N))) \end{aligned}
SembolAnlamı
xxGirdi token dizisi
NNBlok sayısı (bu modelde 2; GPT-3’te 96)
TransformerBlog˘ui\text{TransformerBloğu}_iMaskeli self-attention + Add&Norm + FFN + Add&Norm (10-15. ders)

Her TransformerBlog˘u\text{TransformerBloğu} aynı yapıyı taşır ama kendi ağırlıklarını öğrenir — bu yüzden Blok 1 ve Blok 2’nin dikkat matrisleri (yukarıdaki bileşende inceleyebileceğin gibi) farklı örüntüler gösterebilir.

Kod

Modelin “ABCAB”den sonra ne geleceğini nasıl bu kadar emin tahmin ettiğine bak: yukarıdaki bileşenin altındaki “Kelime dağarcığı olasılıkları” panelinde, kelime dağarcığındaki 3 token üzerinde bir olasılık dağılımı görüyorsun — “C” %99.99 ile açık ara önde, çünkü eğitim verisindeki “ABC” örüntüsü tutarlı şekilde tekrarlanıyordu. Bloklardan birine tıklayıp içini açtığında, o bloğun “AB” bağlamını nasıl işlediğini gerçek sayılarla görebilirsin.

Nerede işe yarar

Bu ders, teoriyle pratik arasındaki köprüyü tamamladı:

  • Gerçek büyük dil modelleri, aynı mimariyi (bu dersteki 2 blok yerine) 32-120 blokla, (16 boyut yerine) 4096-12288 boyutla çalıştırır — yapı aynı, sadece ölçek farklı.
  • “Tahmin” kelimesi burada yanıltıcı olabilir: model bir sonraki token’ı seçmiyor, tüm kelime dağarcığı üzerinde bir olasılık dağılımı üretiyor — 22. ders bu dağılımdan nasıl örnekleme yapıldığını (her zaman en olası olanı seçmek yerine) ele alacak.
  • Bu boru hattı, dil modelinin (20. ders) çekirdeğidir — “dil modeli nedir” sorusunun cevabı, tam olarak burada gördüğün mekanizmadır: bir dizi verildiğinde, bir sonraki token üzerinde bir olasılık dağılımı üretmek.

Bu 2 hatayı yaparsın:

  1. Her Transformer bloğunun aynı çıktıyı ürettiğini sanmak — hayır, her blok kendi ağırlıklarını öğrenir, bu yüzden dikkat örüntüleri bloktan bloğa değişebilir (12. dersteki çoklu başlık uzmanlaşmasına benzer şekilde).
  2. Bu ders “yeni” bir şey öğrettiğini düşünmek — hayır, bu ders sadece 9-18. dersin parçalarını birleştirdi; hiçbir yeni matematik yok, sadece bütün resim.

Kendini test et

1. Bu derste gösterilen TransformerBoruHatti bileşenindeki sayılar nasıl üretildi?
  1. Elle, öğretici amaçlı tasarlandı (9-16. dersteki gibi)
  2. Gerçekten eğitilmiş (gradyan inişiyle, 400 adım) bir mini-GPT modelinin 'ABCAB' girdisi üzerindeki gerçek bir ileri geçişinden yakalandı -- ilk kez bu kategoride, hiçbir vektör elle tasarlanmadı (doğru cevap)
  3. Rastgele üretildi, gerçek bir anlamı yok
  4. İnternetten indirilen bir modelden alındı

Neden: egitim bloğunda model 400 adımda gerçekten eğitiliyor (kayıp 0.000091); tek-ornek-akisi bloğu bu eğitilmiş modelin gerçek bir forward pass'inden veri yakalıyor -- 9-18. dersteki hand-crafted örneklerden farklı olarak.

2. Notebook'ta model 'ABCAB' girdisinden sonra 'C' token'ını %99.99 olasılıkla tahmin ediyor. Bu nereden geliyor?
  1. Rastgele bir tesadüf
  2. Eğitim verisi ('ABC' tekrar eden bir örüntü) tutarlı olduğu için, model gradyan inişiyle bu örüntüyü öğrendi -- 'AB'den sonra her zaman 'C' geldiğini gördüğü için, softmax çıktısı bu token'da neredeyse 1'e yakınsıyor (doğru cevap)
  3. Model rastgele tahmin yapıyor
  4. 'C' harfi alfabetik olarak son sırada olduğu için

Neden: egitim bloğunda kayıp 0.000091'e kadar düşüyor -- bu, modelin eğitim örüntüsünü neredeyse mükemmel öğrendiğini gösterir; tek-ornek-akisi bloğunda C olasılığı 0.9999 bu öğrenmenin doğrudan sonucudur.

3. İki Transformer bloğu (Blok 1, Blok 2) aynı mimariyi paylaşıyor. Bileşende ikisinin dikkat matrisi farklı görünebilir mi?
  1. Hayır, mimari aynı olduğu için matrisler de her zaman özdeştir
  2. Evet -- her blok kendi Wq/Wk/Wv ağırlıklarını bağımsız öğrenir (12. dersteki çoklu başlık uzmanlaşmasına benzer şekilde), bu yüzden farklı katmanlar farklı örüntüler yakalayabilir (doğru cevap)
  3. Sadece ilk blok dikkat matrisi üretir
  4. Bloklar sırayla değil, paralel çalışır, bu yüzden karşılaştırılamaz

Neden: tam-model bloğunda her TransformerBlogu kendi Wq/Wk/Wv parametrelerine sahip; MathBox'ta belirtildiği gibi aynı yapı ama farklı öğrenilmiş ağırlıklar taşırlar, bu da bileşende Blok 1/Blok 2 arasında geçiş yaparak gözlemlenebilir.

Özet

Özet

  • Bu ders, 9-18. derste tek tek kurduğumuz tüm parçaları (attention, FFN, layer norm, artık bağlantı) birleştirip gerçekten eğitti.
  • Boru hattı: Gömme+PozKodlama -> N x [Maskeli Self-Attention -> Add&Norm -> FFN -> Add&Norm] -> Son Norm -> Linear+Softmax.
  • Model, 'ABCAB' girdisinden sonra 'C'yi %99.99 olasılıkla tahmin etti -- eğitim verisindeki tutarlı örüntüyü gerçekten öğrendiğinin kanıtı.
  • Her Transformer bloğu aynı yapıyı paylaşır ama kendi ağırlıklarını öğrenir -- bloktan bloğa farklı dikkat örüntüleri ortaya çıkabilir.
  • Gerçek büyük dil modelleri aynı mimariyi çok daha büyük ölçekte (32-120 blok, binlerce boyut) çalıştırır.
Sonraki adım: Dil modeli nedir, ne yapar →