Dikkat Artı MLP, Tekrarlanan
İki Alt Katman
Bir transformer bloğu tam olarak iki alt katman içerir, her biri [batch, seq_len, d_model] şeklinde bir token dizisi üzerinde çalışır:
1. Çok başlı dikkat alt katmanı. Token'lar birbirine bakar. Etkinlik 68 bunu detaylı bir şekilde ele almıştı. Çıkış şekli giriş şekline uyar.
2. Besleme ileri MLP alt katmanı. Her token, iki katmanlı bir perceptron aracılığıyla bağımsız olarak dönüşür. Token'lar arası bilgi akışı yok. Çıkış şekli giriş şekline uyar.
Her iki alt katman da [batch, seq_len, d_model] şeklini korur. Bu koruma, blokların istiflenmesini sağlar: katman N'nin çıkışı katman N+1'in girişine şekil jimnastiği yapmadan beslenir.
Her Alt Katmanın Katkısı
Dikkat bilgiyi pozisyonlar arasında taşır: 17. pozisyondaki bir token, 1'den 16'ya kadar olan pozisyonlardan bilgi çekebilir. MLP bilgiyi her pozisyon içinde dönüştürür: bir token'ın temsili öğrenilmiş doğrusal olmayan fonksiyonlar aracılığıyla yeniden şekillendirilir, ancak komşularını asla görmez.
Blokları yığmak bu iki işlemi sırayla değiştirir. Katman 1 dikkat konumları karıştırır. Katman 1 MLP her konuma göre yeniden şekillendirir. Katman 2 dikkat tekrar karıştırır, şimdi yeniden şekillendirilmiş temsiller üzerinde. Bu değişim derinlikle ifade gücünü artırır.
ANDREA'nın Yığını
| Varyant | n_layer | n_head | d_model | mlp_dim |
|---|---|---|---|---|
| ANDREA-12M | 6 | 12 | 384 | 1536 |
| ANDREA-120M | 12 | 12 | 768 | 3072 |
| ANDREA-480M | 16 | 24 | 1536 | 6144 |
Aile genelinde mlp_dim = 4 × d_model olduğunu fark edin. Bu oran neredeyse her modern transformer'da geçerlidir. Bölüm 3 bunun nedenini açıklar.
Alt Katmanları Adlandırma
Neden Atlama Bağlantıları Önemli
Kalıntı Deseni
Her alt katman, hesabını bir kalıntı bağlantısı ile sarar. Çıktı, girdiyi geri ekler:
x = x + Attention(LayerNorm(x)) # attention alt katmanı
x = x + MLP(KatmanNorm(x)) # MLP alt katmanı
Her alt katmanın içinde, Attention(...) veya MLP(...) fonksiyonu bir delta üretir. Blok girdiyi değiştirmez; öğrenilmiş bir düzeltme ekler.
Bu Neden Önemli
Derin mimarilerde artık bağlantıların baskın olmasının üç nedeni:
1. Gradyan akışı. Geri yayılım sırasında, toplama işlemi gradyanlara çıktıdan girdiye doğrudan bir yol verir ve alt katmanı atlar. Kalıntısız 12 katmanlı bir yığın, gömülere ulaşmadan önce gradyan sinyalini uzun süre önce kaybederdi; kalıntılarla, gradyan büyüklüğü yüzlerce katman boyunca kullanılabilir kalır.
2. Kimlik başlatma. Başlatmada, alt katman ağırlıkları küçük çıktılar üretir. Kalıntı bağlantısı, N. katmanın başlangıçta neredeyse değişmeden geçmesine neden olur. Eğitim, çalışan bir başlangıç noktasından deltas'ları ilerici olarak öğrenir.
3. Bileşimsel öğrenme. Her blok bir yenileme öğrenir, bir değiştirme değil. Katman 1 konum bilgisi ekleyebilir. Katman 2 sentaktik yapı ekleyebilir. Katman 7 anlamsal ilişkiler ekleyebilir. Kalıntı akışı birikir.
Katman Normalizasyonu
Her alt katmandan önce, LayerNorm her token'ın temsilini sıfır ortalama ve birim varyansa yeniden ölçekler, ardından öğrenilen özellik başına kazanç ve önyargı uygular:
y = gamma * (x - mean(x)) / sqrt(var(x) + epsilon) + beta
Ortalama & varyans, d_model boyutu boyunca her token için ayrı ayrı hesaplanır. İki öğrenilen vektör (gamma, beta, her biri [d_model] şeklinde) ifadeli ölçeği geri yükler. Normalizasyon, aktivasyonları sayısal olarak kararlı bir aralıkta tutar; onsuz, küçük eğitim kararsızlıkları NaN gradyanlarına dönüşen bir çığ haline gelir.
Pre-Norm vs Post-Norm
İnce Ama Kritik Bir Seçim
```Bir artık katmanına layer norm'u bağlamanın iki yolu:
Post-norm (orijinal 2017 makalesi):
x = LayerNorm(x + Attention(x))
Layer norm, artık toplama işleminden sonra yer alır. Artık akış kendisi her katmanda normalize edilir.
Pre-norm (modern standart, ANDREA'da kullanılan):
x = x + Attention(LayerNorm(x))
Layer norm, alt katmanın önünde, artık dal içinde yer alır. Artık akış normalize edilmez; sadece alt katmana giren girdi yeniden ölçeklenir.
Neden Pre-Norm Kazandı
Post-norm, LR ısınma olmadan ve dikkatli hiperparametre ayarı olmadan kötü eğitilir. Gradyanlar, her katman normunun artık akışın birikmiş durumunu karıştırması nedeniyle erken katmanlarda patlar. Orijinal 2017 makalesi kapsamlı ayarlamayla post-norm kullandı; sonraki çalışmalar (GPT-2, LLaMA, ANDREA) pre-norm'u standartlaştırdı.
Pre-norm sabit bir şekilde eğitir. Kalıntı akışı tüm katmanlarda temiz bir şekilde birikir; yalnızca alt katman girdileri sayısal kararlılık için normalize edilir. Modern transformer'lar varsayılan olarak pre-norm kullanır ve & ANDREA bu seçimi miras alır.
Son Blok Denklemi
Kalıntıları, pre-norm konumundaki katman normunu ve her iki alt katmanı birleştirerek ANDREA'nın tam bloğu elde edilir:
```python
def block_forward(x):
```
x = x + Attention(LayerNorm(x)) # attention alt katmanı
x = x + MLP(LayerNorm(x)) # MLP alt katmanı
return x
İki alt katman, iki rezidüel toplama, iki katman normalizasyonu (not: her alt katmanın kendi katman normalizasyonu vardır; ANDREA-120M'de 12 blok boyunca 24 katman normalizasyonu artı çıktıdaki sonuncusu, toplam 25). 12 kez tekrarla. Bu ANDREA-120M'nin gövdesi.
Neden Pre-Norm Eğitimi Stabilize Eder
İki Doğrusal Katman, Bir Aktivasyon
Üç İşlem
MLP alt katmanı, katmanlar arasında doğrusal olmayan bir aktivasyon içeren iki katmanlı bir perceptrondur:
def mlp_forward(x):
h = x · W_1 + b_1 # genişlet: d_model → mlp_dim
h = GELU(h) # doğrusal olmayan aktivasyon
y = h · W_2 + b_2 # daralt: mlp_dim → d_model
return y
Üç işlem. İki doğrusal, bir doğrusal olmayan. İlk doğrusal genişliği artırır; ikincisi tekrar daraltır.
4× Genişletme Oranı
Modern transformer'lar mlp_dim = 4 × d_model olarak ayarlar. ANDREA-120M:
d_model = 768
mlp_dim = 4 × 768 = 3072
W_1 şekli = [768, 3072] # ~2.36M parametre
W_2 şekli = [3072, 768] # ~2.36M parametre
Blok başına MLP parametreleri = 4.72M (bias'lar yok sayılarak)
Her dikkat alt katmanı çifti arasında (blok başına bir tane) iki MLP bulunur. On iki blok × 4.72M ≈ ANDREA-120M'de toplam 56.6M MLP parametresi, tüm parametrelerin yaklaşık yarısı.
Neden 4×
4× oranı ampirik olarak ortaya çıktı. Daha küçük oranlar model kapasitesini azaltır. Daha büyük oranlar harcanan parametre başına azalan getiriler üretir. On yıllar süren mimari aramalarında 4× dayanıklılığını korudu; GPT, BERT, T5, LLaMA ve ANDREA'da görünür.
Son çalışmalar (PaLM, Chinchilla) kapı mekanizmalarının (SwiGLU) 8/3× genişlemeyi daha düşük maliyetle karşılaştırılabilir kapasiteyle kullanabileceğini buldu; ANDREA sadelik için klasik GELU + 4× ile kalıyor.
GELU: Pürüzsüz Bir Aktivasyon
GELU Ne Hesaplar
GELU (Gaussian Error Linear Unit), modern transformer'larda MLP katmanları arasında standart aktivasyondur. Formülü:
GELU(x) = x · Φ(x)
Φ(x), standart normal dağılımın kümülatif dağılım fonksiyonudur: standart Gauss rastgele değişkeninin x'e eşit veya altında olma olasılığı. Sayısal olarak hesaplanır:
Φ(x) ≈ 0.5 × (1 + tanh(sqrt(2/π) × (x + 0.044715 × x³)))
Bölgeye Göre Davranış
- Büyük pozitif x için: Φ(x) ≈ 1, yani GELU(x) ≈ x. ReLU gibi.
- Büyük negatif x için: Φ(x) ≈ 0, yani GELU(x) ≈ 0. ReLU gibi.
- x = 0 civarında: Φ(x) ≈ 0.5, yani GELU(0) = 0 tam olarak. Köken üzerinden yumuşak geçiş.
ReLU'dan farklı olarak, GELU bazı negatif girdilerin Φ(x) ile ağırlıklandırılmış olarak geçmesine izin verir. Küçük bir negatif girdi hala küçük bir negatif çıktı katkısı sağlar, tam girdiden daha az olsa da.
Neden GELU ReLU'yu Aştı
Deneysel olarak, GELU ile eğitilen transformer'lar aynı parametre sayısında ReLU ile eğitilenlere göre daha düşük kayba ulaşır. Sıfır civarındaki pürüzsüzlük önemlidir: ReLU'nun sıfırdaki sert kesintisi gradyan süreksizlikleri üretir; GELU'nun pürüzsüz eğrisi geri yayılım için daha temiz gradyanlar sağlar.
ANDREA'nın eğitim motoru microgpt_cuda.cu el yazması GELU CUDA çekirdeğiyle gelir. Çekirdek yukarıdaki tanh yaklaştırmasını kullanır; modern GPU'lar tanh'i tek talimat op olarak içerir.
MLP Parametrelerini Hesaplama
On İki Blok ANDREA-120M'yi Oluşturur
Bloktan Modele
ANDREA-120M'nin tam ileri geçişi:
def model_forward(token_ids):
x = token_embed(token_ids) + position_embed(positions)
for block_idx in range(n_layer): # 12 blok
x = block_forward(x) # attention + MLP kalıntılarla
x = LayerNorm(x) # son norm
logits = x · token_embed.T # çıktı projeksiyonu için bağlı ağırlıklar
return logits
Altı satır. Ana kısım block_forward içinde yer alır ve on iki kez çağrılır. Gömme vektörler (embeddings) boru hattını başlatır; bağlı çıkarma (unembedding) (giriş sorgusu için kullanılan aynı matrisin, çıktı projeksiyonu için transpoze edilmiş hali) ile biter.
Derinlik Olarak Bileşim
Her blok artık akımı (residual stream) okur, bir delta hesaplar ve onu geri ekler. On iki geçişten sonra, akım her bloktan biriken katkıları içerir. İçsel olarak, katmanlar uzmanlaşma eğilimindedir:
- Erken katmanlar (1-3): sentaktik desenler, pozisyonel yapı
- Orta katmanlar (4-8): kelime ilişkileri, ifade sınırları
- Geç katmanlar (9-12): anlamsal içerik, olgusal hatırlama
Bu uzmanlaşma, mimari tercihler değil, eğitim baskısından kaynaklanır. Aynı tek tip blok tasarımı, dil üzerinde eğitildiğinde uzmanlaşmış katmanlar üretir.
Toplam Blok Parametreleri
| Bileşen | Blok başına | 12 blok boyunca |
|---|---|---|
| Dikkat projeksiyonları (4×W) | 2.36M | 28.3M |
| MLP ağırlıkları (W_1 + W_2) | 4.72M | 56.6M |
| Katman normları (gamma, beta) | ~3K (önemsiz) | ~37K |
| Blok başına toplam | ~7.1M | ~85M |
Gövdedeki 85M parametre. ~13M token gömme ekleyin (8449 kelime dağarcığı × 768 d_model × 2, giriş/çıkış bağlı) artı son katman normu, & ANDREA-120M'nin parametre sayısı yaklaşık 120M'ye ulaşır. Blok tasarımı üçte ikisini; gömme kalanını oluşturur.