Transformer mimarisi: bütün resim
Önkoşul:GPT ile "Attention is All You Need" farkı
Kanca
- 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 HİÇBİR yeni parça eklemiyor — sadece HEPSİNİ, 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ç.
Model'in tahmini: "C"
Mekanizma
Bu tam model, 9-18. derste kurduğumuz HER PARÇAYI birleştiriyor:
Tam mimari: tüm parçalar bir arada
# Bu ders, 9-18. derste tek tek kurduğumuz HER PARÇAYI, N BLOK üst üste yığarak
# BİRLEŞTİRİYOR: 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 YAKALAYALIM -- 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
| Sembol | Anlamı |
|---|---|
| Girdi token dizisi | |
| Blok sayısı (bu modelde 2; GPT-3’te 96) | |
| Maskeli self-attention + Add&Norm + FFN + Add&Norm (10-15. ders) |
Her AYNI yapıyı taşır ama KENDİ ağırlıklarını öğrenir — bu yüzden Blok 1 ve Blok 2’nin dikkat matrisleri (yukarıdaki bileşende inceleyebileceğin gibi) FARKLI örüntüler gösterebilir.
Kod
Modelin “ABCAB”den sonra ne geleceğini NASIL bu kadar EMİN 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ü TUTARLI ş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 PRATİK arasındaki köprüyü tamamladı:
- GERÇEK büyük dil modelleri, AYNI mimariyi (bu dersteki 2 blok yerine) 32-120 blokla, (16 boyut yerine) 4096-12288 boyutla çalıştırır — yapı AYNI, sadece ÖLÇEK farklı.
- “Tahmin” kelimesi burada YANILTICI olabilir: model bir sonraki token’ı SEÇMİYOR, TÜM kelime dağarcığı üzerinde bir OLASILIK DAĞILIMI üretiyor — 22. ders bu dağılımdan NASIL örnekleme yapıldığını (her zaman en olası olanı seçmek yerine) ele alacak.
- Bu boru hattı, dil modelinin (20. ders) ÇEKİRDEĞİDİR — “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:
- Her Transformer bloğunun AYNI çıktıyı ürettiğini sanmak — HAYIR, her blok KENDİ 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).
- Bu ders “yeni” bir şey öğrettiğini düşünmek — HAYIR, bu ders SADECE 9-18. dersin parçalarını BİRLEŞTİRDİ; hiçbir yeni matematik yok, sadece BÜTÜN resim.
Kendini test et
1. Bu derste gösterilen TransformerBoruHatti bileşenindeki sayılar NASIL üretildi?
- Elle, öğretici amaçlı tasarlandı (9-16. dersteki gibi)
- 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)
- Rastgele üretildi, gerçek bir anlamı yok
- İ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 FARKLI olarak.
2. Notebook'ta model 'ABCAB' girdisinden sonra 'C' token'ını %99.99 olasılıkla tahmin ediyor. Bu NEREDEN geliyor?
- Rastgele bir tesadüf
- Eğitim verisi ('ABC' tekrar eden bir örüntü) TUTARLI olduğu için, model gradyan inişiyle bu örüntüyü ÖĞRENDİ -- '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)
- Model rastgele tahmin yapıyor
- '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) AYNI mimariyi paylaşıyor. Bileşende ikisinin dikkat matrisi FARKLI görünebilir mi?
- Hayır, mimari aynı olduğu için matrisler de her zaman özdeştir
- Evet -- her blok kendi Wq/Wk/Wv ağırlıklarını BAĞIMSIZ öğ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)
- Sadece ilk blok dikkat matrisi üretir
- Bloklar sırayla değil, paralel çalışır, bu yüzden karşılaştırılamaz
Neden: tam-model bloğunda her TransformerBlogu KENDİ Wq/Wk/Wv parametrelerine sahip; MathBox'ta belirtildiği gibi AYNI yapı ama FARKLI öğ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ı) BİRLEŞTİRİP 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 AYNI yapıyı paylaşır ama KENDİ ağırlıklarını öğrenir -- bloktan bloğa farklı dikkat örüntüleri ortaya çıkabilir.
- Gerçek büyük dil modelleri AYNI mimariyi çok daha büyük ölçekte (32-120 blok, binlerce boyut) çalıştırır.