Ana içeriğe geç

Orta10 dk

Encoder-decoder yapısı

Önkoşul:Position-wise feed-forward ağ

Kanca

Şimdiye kadar TEK bir cümle üzerinde çalıştık. Ama çeviri gibi görevlerde İKİ cümle var: kaynak (“Kedi masaya çıktı”) ve hedef (“The cat climbed…”). Model, hedefi ÜRETİRKEN kaynağa NASIL “bakıyor”?

Sezgi

Orijinal “Attention is All You Need” mimarisi İKİ parçadan oluşur: encoder (kaynağı OKUR) ve decoder (hedefi ÜRETİR). Decoder’ın YENİ bir silahı var: “çapraz dikkat” (cross-attention) — sorgu KENDİSİNDEN, ama anahtar/değer ENCODER’DAN gelir. Böylece decoder, her kelimeyi üretirken kaynak cümlenin İLGİLİ kısmına “bakabilir”.

Mekanizma

İki dizi: kaynak ve hedef

# 10-15. derste TEK bir dizi (cümle) üzerinde çalıştık. Ama çeviri gibi görevlerde
# İKİ dizi var: KAYNAK (encoder'a girer) ve HEDEF (decoder ÜRETİR). Örnek: Türkçe'den
# İngilizce'ye çeviri.
KAYNAK = ["Kedi", "masaya", "çıktı"]       # Türkçe (encoder girdisi)
HEDEF_SIMDIYE_KADAR = ["The", "cat"]        # İngilizce, ŞU ANA KADAR üretilen (decoder girdisi)
print(f"Kaynak dizi (Türkçe, encoder): {KAYNAK}")
print(f"Hedef dizi (İngilizce, decoder, şimdiye kadar üretilen): {HEDEF_SIMDIYE_KADAR}")
print("\nEncoder, KAYNAK diziyi TAMAMEN görebilir (bidirectional -- 10. dersteki self-attention gibi).")
print("Decoder ise HEDEF dizide SADECE kendinden ÖNCEKİLERİ görebilir (11. dersteki nedensel maske).")
Kaynak dizi (Türkçe, encoder): ['Kedi', 'masaya', 'çıktı']
Hedef dizi (İngilizce, decoder, şimdiye kadar üretilen): ['The', 'cat']

Encoder, KAYNAK diziyi TAMAMEN görebilir (bidirectional -- 10. dersteki self-attention gibi).
Decoder ise HEDEF dizide SADECE kendinden ÖNCEKİLERİ görebilir (11. dersteki nedensel maske).

Önce encoder’ı çalıştıralım — 10. dersteki AYNI self-attention, ama BU SEFER kaynak cümle üzerinde:

Encoder: kaynağı oku

# Encoder: KAYNAK dizi üzerinde SIRADAN self-attention (maskesiz, TÜM kaynak
# kelimeleri birbirini görebilir).
D = 4
X_kaynak = torch.tensor([
    [1.5, 0.0, 0.0, 0.0],   # Kedi
    [0.0, 1.5, 0.0, 0.0],   # masaya
    [0.3, 0.3, 1.2, 0.0],   # çıktı
])

torch.manual_seed(125)
Wq_enc, Wk_enc, Wv_enc = torch.randn(D, D) * 0.5, torch.randn(D, D) * 0.5, torch.randn(D, D) * 0.5
Q_enc, K_enc, V_enc = X_kaynak @ Wq_enc, X_kaynak @ Wk_enc, X_kaynak @ Wv_enc
encoder_ciktisi, _ = dikkat(Q_enc, K_enc, V_enc)
print(f"\nEncoder çıktısı şekli: {tuple(encoder_ciktisi.shape)} (= {len(KAYNAK)} kaynak token x {D} boyut)")
print("Bu çıktı, HER kaynak kelimenin, DİĞER TÜM kaynak kelimelerle 'zenginleştirilmiş' temsilidir --")
print("decoder, üretim boyunca BUNU kullanacak.")

Encoder çıktısı şekli: (3, 4) (= 3 kaynak token x 4 boyut)
Bu çıktı, HER kaynak kelimenin, DİĞER TÜM kaynak kelimelerle 'zenginleştirilmiş' temsilidir --
decoder, üretim boyunca BUNU kullanacak.

Şimdi YENİ mekanizma: çapraz dikkat. Decoder’ın sorgusu, encoder’ın çıktısındaki anahtar/değerlerle eşleşiyor:

Çapraz dikkat: decoder, encoder'a bakar

# Decoder'ın İKİNCİ (ve YENİ) dikkat türü: "çapraz dikkat" (cross-attention).
# Sorgu (Q) DECODER'DAN gelir, ama Anahtar/Değer (K, V) ENCODER çıktısından gelir --
# yani decoder, kaynak cümleye 'BAKAR'.
X_hedef = torch.tensor([
    [0.1, 0.1, 0.1, 1.0],   # "The" -- genel bir kelime, belirli bir kaynağa odaklanmaz
    [1.4, 0.0, 0.0, 0.1],   # "cat" -- 'Kedi'ye YAKIN tasarlandı
])

torch.manual_seed(10146)
Wq_dec, Wk_capraz = torch.randn(D, D) * 0.5, torch.randn(D, D) * 0.5

Q_dec = X_hedef @ Wq_dec          # sorgu: DECODER'DAN
K_capraz = encoder_ciktisi @ Wk_capraz   # anahtar: ENCODER çıktısından (V_capraz = encoder_ciktisi)
capraz_ciktisi, capraz_agirliklar = dikkat(Q_dec, K_capraz, encoder_ciktisi)

print(f"\nÇapraz dikkat matrisi şekli: {tuple(capraz_agirliklar.shape)} (= {len(HEDEF_SIMDIYE_KADAR)} hedef x {len(KAYNAK)} kaynak)")
print("DİKKAT: bu matris KARE DEĞİL -- 10. dersteki self-attention'ın N×N matrisinden FARKLI,")
print("çünkü sorgu ve anahtar/değer İKİ FARKLI diziden geliyor.")
for hedef_kelime, agirlik_satiri in zip(HEDEF_SIMDIYE_KADAR, capraz_agirliklar.tolist()):
    print(f"\n  '{hedef_kelime}' hangi kaynak kelimelere bakıyor?")
    for kaynak_kelime, a in zip(KAYNAK, agirlik_satiri):
        print(f"    {kaynak_kelime:<10} ağırlık={a:.3f}")

en_yuksek = KAYNAK[capraz_agirliklar[1].argmax().item()]
print(f"\n'cat' üretilirken, en çok '{en_yuksek}' kaynak kelimesine bakılıyor ({capraz_agirliklar[1].max().item():.3f}) --")
print("model, 'cat' kelimesinin KARŞILIĞININ kaynak cümlede 'Kedi' olduğunu, ÖĞRENİLMİŞ dikkat ile buluyor.")

Çapraz dikkat matrisi şekli: (2, 3) (= 2 hedef x 3 kaynak)
DİKKAT: bu matris KARE DEĞİL -- 10. dersteki self-attention'ın N×N matrisinden FARKLI,
çünkü sorgu ve anahtar/değer İKİ FARKLI diziden geliyor.

  'The' hangi kaynak kelimelere bakıyor?
    Kedi       ağırlık=0.476
    masaya     ağırlık=0.240
    çıktı      ağırlık=0.284

  'cat' hangi kaynak kelimelere bakıyor?
    Kedi       ağırlık=0.658
    masaya     ağırlık=0.138
    çıktı      ağırlık=0.204

'cat' üretilirken, en çok 'Kedi' kaynak kelimesine bakılıyor (0.658) --
model, 'cat' kelimesinin KARŞILIĞININ kaynak cümlede 'Kedi' olduğunu, ÖĞRENİLMİŞ dikkat ile buluyor.

“cat” üretilirken model, kaynak cümledeki “Kedi”ye 0.658 ağırlıkla bakıyor — çeviri karşılığını, hiçbir sözlük OLMADAN, ÖĞRENİLMİŞ dikkat ile buluyor.

Matematik

Üç dikkat türü, aynı formül
Attention(Q,K,V)=softmax(QKdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)V
Dikkat türüQQ neredenK,VK, V nereden
Encoder self-attentionencoderencoder
Decoder maskeli self-attentiondecoderdecoder
Decoder çapraz dikkatdecoderencoder

Formül HİÇ değişmiyor — 9-11. derste kurduğumuz AYNI dikkat() fonksiyonu. Değişen TEK şey, QQ, KK, VV‘nin HANGİ diziden geldiği. Çapraz dikkatte QQ ve KK FARKLI dizilerden geldiği için, dikkat matrisi KARE OLMAK ZORUNDA DEĞİLDİR.

Kod

Üç dikkat türünün karşılaştırması

# Özet karşılaştırma: encoder'daki self-attention, decoder'daki maskeli self-attention,
# ve decoder'daki çapraz dikkat -- ÜÇÜ de AYNI dikkat() fonksiyonunu kullanıyor, ama
# Q/K/V'nin NEREDEN geldiği DEĞİŞİYOR.
print(f"\n{'Dikkat türü':<28} {'Q nereden':<14} {'K, V nereden':<16} {'Matris şekli':<12}")
print(f"{'Encoder self-attention':<28} {'encoder':<14} {'encoder':<16} {'(3, 3)':<12}")
print(f"{'Decoder maskeli self-att.':<28} {'decoder':<14} {'decoder':<16} {'(2, 2)':<12}")
print(f"{'Decoder çapraz dikkat':<28} {'decoder':<14} {'ENCODER':<16} {'(2, 3)':<12}")
print("\nAYNI matematik (dikkat fonksiyonu), ÜÇ FARKLI 'nereden geliyor' kombinasyonu --")
print("bu üçü BİRLİKTE, bir Transformer encoder-decoder bloğunu oluşturuyor.")

Dikkat türü                  Q nereden      K, V nereden     Matris şekli
Encoder self-attention       encoder        encoder          (3, 3)      
Decoder maskeli self-att.    decoder        decoder          (2, 2)      
Decoder çapraz dikkat        decoder        ENCODER          (2, 3)      

AYNI matematik (dikkat fonksiyonu), ÜÇ FARKLI 'nereden geliyor' kombinasyonu --
bu üçü BİRLİKTE, bir Transformer encoder-decoder bloğunu oluşturuyor.
2 hedef kelime x 3 kaynak kelimelik, kare olmayan çapraz dikkat matrisini gösteren ısı haritası; 'cat' satırı 'Kedi' sütununda en koyu.
Çapraz dikkat matrisi KARE DEĞİL (2x3) -- 'cat' satırında en koyu hücre 'Kedi' sütununda, modelin çeviri karşılığını bulduğunu gösteriyor.

Nerede işe yarar

Encoder-decoder yapısı, orijinal 2017 Transformer’ının TAM MİMARİSİ — ama tek kullanım şekli DEĞİL:

  • Makine çevirisi, özetleme, soru-cevaplama gibi “bir diziyi başka bir diziye dönüştürme” görevleri encoder-decoder kullanır — kaynak ve hedef FARKLI uzunlukta, FARKLI dillerde/formatlarda olabilir.
  • GPT gibi modeller SADECE decoder kullanır (18. ders) — çapraz dikkat YOKTUR, sadece maskeli self-attention; BERT gibi modeller SADECE encoder kullanır (maskesiz self-attention, çeviri ÜRETMEZ, TEMSİL üretir).
  • Decoder’ın HER bloğunda üç alt-katman sırayla çalışır: maskeli self-attention → çapraz dikkat → FFN (14-15. ders) — her birinin ETRAFINDA artık bağlantı + layer norm VAR.

Bu 2 hatayı yaparsın:

  1. Çapraz dikkatin de self-attention gibi KARE bir matris ürettiğini sanmak — HAYIR, hedef ve kaynak uzunlukları FARKLI olabilir, matris dikdörtgen olabilir.
  2. Her Transformer modelinin encoder VE decoder içerdiğini düşünmek — GPT SADECE decoder, BERT SADECE encoder kullanır (18. ders bu farkı detaylandıracak).

Kendini test et

1. Çapraz dikkatin (cross-attention) self-attention'dan temel farkı nedir?
  1. Farklı bir matematiksel formül kullanır
  2. Sorgu (Q) BİR diziden (decoder), anahtar/değer (K, V) BAŞKA bir diziden (encoder çıktısı) gelir -- self-attention'da ÜÇÜ de AYNI diziden gelir (doğru cevap)
  3. Sadece kısa cümlelerde çalışır
  4. Softmax kullanmaz

Neden: capraz-dikkat bloğunda Q_dec decoder'ın X_hedef'inden, K_capraz ise encoder_ciktisi'nden hesaplanıyor -- oz-vs-capraz tablosunda bu ayrım AÇIKÇA özetleniyor.

2. Notebook'ta çapraz dikkat matrisinin şekli (2, 3) -- yani KARE DEĞİL. Bunun nedeni ne?
  1. Bir hesaplama hatası
  2. Hedef dizi (2 kelime, şimdiye kadar üretilen) ile kaynak dizi (3 kelime) FARKLI uzunlukta -- dikkat matrisinin şekli (hedef uzunluğu × kaynak uzunluğu) olduğu için kare olmak ZORUNDA değil (doğru cevap)
  3. Sadece decoder'ın son katmanında bu şekil kare olmaz
  4. Matris her zaman kare olmalıydı, bu bir tasarım hatasıdır

Neden: capraz-dikkat bloğunun çıktısında matris şekli (2, 3) = (len(HEDEF_SIMDIYE_KADAR), len(KAYNAK)) -- self-attention'daki N×N kısıtlaması burada YOKTUR çünkü Q ve K farklı dizilerden geliyor.

3. 'cat' üretilirken çapraz dikkat neden kaynak cümledeki 'Kedi'ye en yüksek ağırlığı (0.658) veriyor?
  1. Rastgele bir sonuç
  2. Decoder'ın 'cat' sorgusu ile encoder çıktısındaki 'Kedi' anahtarı arasındaki nokta çarpım BENZERLİĞİ en yüksek çıktığı için -- bu, gerçek modellerde EĞİTİMLE öğrenilen çeviri hizalamasının (alignment) küçük ölçekli bir örneği (doğru cevap)
  3. 'Kedi' kelimesi alfabetik olarak ilk sırada olduğu için
  4. Çapraz dikkat her zaman ilk kaynak kelimeye en yüksek ağırlığı verir

Neden: capraz-dikkat bloğunda 'cat' token'ının gömmesi ÖĞRETİCİ amaçlı 'Kedi'ye yakın tasarlandı; softmax(QKᵀ/√d) formülü bu benzerliği en yüksek ağırlığa çeviriyor -- gerçek modellerde bu hizalama veri üzerinde EĞİTİLİR.

Özet

Özet

  • Encoder-decoder yapısı, kaynak diziyi (encoder) ve hedef diziyi (decoder) AYRI ele alır -- çeviri gibi "diziden diziye" görevler için tasarlanmıştır.
  • Decoder'ın İKİ dikkat türü var: maskeli self-attention (kendi ürettiklerine bakar) ve çapraz dikkat (encoder çıktısına bakar).
  • Çapraz dikkatte Q decoder'dan, K ve V encoder çıktısından gelir -- dikkat matrisi KARE OLMAK ZORUNDA DEĞİLDİR.
  • Notebook'ta 'cat' üretilirken, model 'Kedi'ye 0.658 ağırlıkla bakarak çeviri karşılığını buldu.
  • GPT sadece decoder, BERT sadece encoder kullanır -- her Transformer modelinin encoder VE decoder içermesi GEREKMEZ (18. ders).
Sonraki adım: Transformer'ın eğitimi ve çıkarımı →