Ana sayfa › Blog

Küçük bir modelde fp16 neden bozuldu? 1330'luk aktivasyonlar ve RMSNorm taşması

4 Ekim 2026 · 3 dk okuma · Töz AI

Modeli PyTorch'ta kusursuz çalışıyordu, ONNX'e çevirip tarayıcıda fp16 ile açınca saçmalamaya başladı. Bulduğumuz şey, bir ölçümü yanlış donanımda yapmanın ne kadar yanıltıcı olabileceğini gösterdi.

Belirti

Modeli tarayıcıda çalıştırmak için ağırlıkları ONNX biçimine ve 16 bitlik kayan noktaya (fp16) çevirdik; indirme boyutu 442 MB'a, 4-bit ile 161 MB'a iniyordu. Tarayıcıda WebGPU ile açtığımızda çıktı şuydu:

"Türkiye'nin başkenti neresidir?"   →  "Türkiye'nin başkenti Ankara'ddır."     (çift d)
"İstiklal Marşı'nın şairi kimdir?"  →  "Mehmet Akif Akif Akif Akif Akif …"
bazı istemler                       →  hemen <|endoftext|>, yani sessizlik

Python'daki referans aynı istemlerde tertemiz çalışıyordu: "Türkiye'nin başkenti Ankara'dır." ve "İstiklal Marşı'nın şairi Mehmet Akif Ersoy'dur."

Önce neyi doğruladık

İlk refleks "model bozuk" olmaktı. Dönüşüm hattını halka halka doğruladık:

Üç halka da sağlamdı ve biz bu yüzden bir süre "sorun modelde" dedik. Yanılıyorduk: dördüncü halkayı, yani fp16'nın hedef donanımdaki sayısal davranışını hiç ölçmemiştik.

Teşhis

Model sahibinin Python tarafında yaptığı bir ölçümde, her katmanın çıkışındaki en büyük mutlak değere bakıldı. Gömme çıkışından başlayıp katman katman residual akışındaki max|h|:

0.2, 22, 38, 46, 68, 101, 98, 219, 407, 1310, 1324, 1327, 1327, 1329, 1330, 1327, 1317, 120, 31

Orta katmanlarda aktivasyonlar yaklaşık 1330'a çıkıyor. Bu tek başına sorun değil; fp16 65.504'e kadar sayıyı tutabilir. Sorun, RMSNorm'un mean(x²) hesabı: 1330² ≈ 1,77 milyon, yani fp16'nın tavanının yaklaşık 27 katı. Hesap gerçekten fp16'da yapılırsa sonsuza taşar, normalize edilen çıktı sıfıra gider ve model çöpe dönüşür.

PyTorch'taki Qwen3RMSNorm bu yüzden hesabı fp32'ye yükseltir. Modelin eğitim kodundaki RMSNorm de aynısını yapıyordu (x.float()); model bu varsayımla eğitilmişti. ONNX dönüşümü bu yükseltmeyi düşürmüştü.

Düzeltme ve kalan sorun

Dönüştürücüye RMSNorm'un bileşen işlemlerini (Pow, ReduceMean, Sqrt, Div ve benzerleri) fp32'de bırakmasını söyledik, ve üretilen grafta bu işlemlerin gerçekten fp16'ya inmediğini yapısal olarak doğrulayan bir kontrol ekledik. Saçmalama bitti, model gerçek cümleler kurmaya başladı. Ama çıktı hâlâ referansla birebir değildi (Ankara'ddır, Akif Akif …).

Sebep artık taşma değil, hassasiyet. fp16'da 1024 ile 2048 arasındaki sayıların komşu değerler arası adımı 1,0'dır: 1330,7 ile 1331,2 aynı sayıya yuvarlanır. Bu hata 18 katman boyunca birikiyor.

Bunu bir deneyle doğruladık: 4-bit ağırlıklı sürüm (q4f16), fp16 sürümüyle kelimesi kelimesine aynı bozuk çıktıyı verdi. Hata ağırlıklarda olsaydı 4 bit ile 16 bit aynı çıkamazdı; demek ki baskın hata aktivasyonlardan geliyor. Çözüm, ağırlıkları 8 bite indirirken aktivasyonları fp32'de tutan sürüm: 8-bit (q8), dört referans istemin dördünü de PyTorch ile birebir tutturdu ve zayıf bir CPU'da WebAssembly ile çalışıyor. Sitedeki sürüm bu.

Üç ders

  1. Doğrulamayı hedef donanımda yapın. fp16'yı ilk CPU'da doğruladık ve bozukluğu göremedik. Bizim açıklamamız (doğrulamadık): CPU çekirdekleri fp16 tensörlerini içeride fp32'ye yükseltiyor, taşma orada hiç oluşmuyor; yalnızca WebGPU'nun gerçek fp16 aritmetiğinde ortaya çıkıyor.
  2. Bir metriğin sinyali, ölçüldüğü ortamda geçerlidir. Aynı CPU ölçümü, v1'in q8'ini perplexity'de yaklaşık %20 kötü, v2'ninkini tamamen bozuk gösterdi; oysa tarayıcıda v1'in q8'i dört referans cevabı birebir tutturdu, v2'ninki de doğru ve akıcı cevaplar verdi. Bu çelişkiyi tam açıklayamıyoruz. Pratik sonuç: kuantize bir sürümün kullanılabilirliğine ancak hedef ortamda gerçek istemlerle üretim yaptırarak karar veriyoruz.
  3. Büyük aktivasyonlar bir dağıtım riskidir. Bir model PyTorch'ta sorunsuz çalışıp düşük hassasiyetli çıkarımda bozulabilir. Sonraki eğitimlerde aktivasyon büyüklüğünü sınırlamak (örneğin z-loss'u artırmak ya da residual ölçeklemek) fp16 ve 4-bit dağıtımı mümkün kılabilir; şimdilik bunu denemedik.

Modelin kendisi hakkında bilgi için Töz-1 nedir yazısına, çıkarımı neden tarayıcıda yaptığımız için sunucu ya da tarayıcı yazısına bakın.

Töz-1'i tarayıcınızda deneyin: kurulum yok, sunucu yok.

Töz-1'i dene