Kitaplar / Yöntem ile Sıfırdan Dil Modeli / Bölüm 9 — Metin üretmek
Bölüm 9 — Metin üretmek
Eğitilmiş bir dil modeli metin yazmaz; her adımda bir olasılık dağılımı verir. Bu dağılımdan bir karakteri nasıl seçtiğimiz ise çıkan metnin karakterini belirler. Aynı model, seçim yöntemine göre sıkıcı ve tekrarcı da olabilir, yaratıcı ve dağınık da. Sohbet uygulamalarındaki “sıcaklık” ayarı da tam olarak bu bölümün konusudur.
Üç yöntem
Açgözlü seçim. Her adımda en olası karakteri alırız. Rastgelelik yoktur; aynı başlangıç her zaman aynı metni verir. Kulağa en mantıklı yöntem gibi gelir ama genellikle kötü sonuç verir. Model kendi ürettiği metne bakarak karar verdiği için kolayca bir döngüye girer.
Sıcaklık. Örneklemeden önce logitleri bir T sayısına böleriz. T < 1 iken büyük logitler daha da öne çıkar; model daha emin ve tutucu davranır. T > 1 iken dağılım düzleşir; düşük olasılıklı karakterler de seçilmeye başlar. T = 1 modelin öğrendiği dağılımın kendisidir. T sıfıra yaklaştıkça açgözlü seçime yaklaşır.
Top-k. Yalnızca en olası k karakter arasından seçeriz; geri kalanların olasılığını sıfırlarız. Model bazen düşük ama sıfır olmayan bir olasılıkla saçma bir karakter seçer ve metin oradan sonra raydan çıkar. Top-k bu kuyruğu keser. Büyük modellerde benzer bir yöntem olan top-p (çekirdek örnekleme) da yaygındır: k sabit sayı yerine, olasılıkları toplamı p’yi geçene kadar en olasıdan başlayarak alınır.
Program, 8. bölümde kaydedilen ağırlıkları yükler. Dosya yoksa modeli 8. bölümle birebir aynı biçimde yeniden eğitir. Aynı tohumla başlayıp rastgele sayıları aynı sırayla çektiği için aynı ağırlıklara ulaşır. Bu, oyun alanında programlar arasında dosya taşınamadığı için gereklidir.
program MetinÜretmek
{ Eğitilmiş bir dil modeli her adımda bir OLASILIK DAĞILIMI verir. Bir sonraki
karakteri bu dağılımdan nasıl seçtiğimiz, üretilen metnin karakterini belirler:
açgözlü : her zaman en olası karakter (hep aynı metin, çoğu zaman tekrar)
sıcaklık : logitler T'ye bölünür; T < 1 dağılımı sivriltir, T > 1 düzleştirir
top-k : yalnızca en olası k karakter arasından seçilir
Program 8. bölümde kaydedilen ağırlıkları yükler. Dosya yoksa (örneğin oyun
alanında) modeli 8. bölümle aynı ayarlarla yeniden eğitir; bu yaklaşık 10 dakika sürer. }
kullan Atasozleri, DilAraclari, KucukGPT, YZ, Sistem, Matematik
sabit
BAĞLAM: tamsayı = 16
DOSYA: metin = 'kucuk_gpt.agirlik'
değişken
harfler: metin dizisi
numara: sözlük
model: GPT
P: ondalık dizisi
sıra: tamsayı dizisi
baş: metin
i, k: tamsayı
T: ondalık
fonksiyon SonrakiDağılım(bağ: tamsayı dizisi; sıcaklık: ondalık; enİyiK: tamsayı): ondalık dizisi
{ Son karakterden sonraki karakterin olasılıkları; sıcaklık ve top-k uygulanmış. }
değişken logit: ondalık dizisi; eşik: ondalık
başla
logit := model.İleri(bağ, 1, Uzunluk(bağ)).Satır(Uzunluk(bağ) - 1).Veri
logit := Eşle(logit, fonksiyon(z: ondalık) => z / sıcaklık)
eğer enİyiK > 0 ise
başla
eşik := Sırala(logit, fonksiyon(z: ondalık) => -z)[enİyiK - 1]
logit := Eşle(logit, fonksiyon(z: ondalık) => eğer z >= eşik ise z değilse -1000000000.0)
bitir
dön Softmaks(Tensör([logit])).Satır(0).Veri
bitir
fonksiyon Üret(başlangıç: metin; sıcaklık: ondalık; enİyiK: tamsayı; açgözlü: mantıksal): metin
değişken bağ: tamsayı dizisi; j: tamsayı; dağ: ondalık dizisi
başla
sonuç := başlangıç
bağ := [0] + DilAraclari.Kodla(başlangıç, numara)
tekrarla
eğer Uzunluk(bağ) > BAĞLAM ise bağ := Dilim(bağ, Uzunluk(bağ) - BAĞLAM, Uzunluk(bağ))
dağ := SonrakiDağılım(bağ, sıcaklık, enİyiK)
eğer açgözlü ise j := ArgMaks(dağ) değilse j := DilAraclari.Örnekle(dağ)
eğer j <> 0 ise sonuç := sonuç + harfler[j]
bağ := bağ + [j]
j = 0 veya Uzunluk(sonuç) > 70 olana dek
bitir
prosedür YenidenEğit
{ 8. bölümle birebir aynı eğitim: aynı tohum, veri, bırakma, öğrenme oranı takvimi ve
erken durdurma. Rastgele sayılar aynı sırayla çekildiği için aynı ağırlıklar çıkar. }
değişken veri: metin dizisi; eğitim, doğrulama, g, h: tamsayı dizisi
opt: herhangi; adım, b, s, ayrım: tamsayı; kayıp: tensör; enİyi, dk: ondalık
başla
yaz('Ağırlık dosyası bulunamadı; model 8. bölümdeki gibi yeniden eğitiliyor (yaklaşık 10 dakika)...', 1)
Tohum(2026)
veri := Atasozleri.Hepsi
ayrım := Uzunluk(veri) * 9 böl 10
eğitim := DilAraclari.Kodla('.' + Birleştir(Dilim(veri, 0, ayrım), '.') + '.', numara)
doğrulama := DilAraclari.Kodla('.' + Birleştir(Dilim(veri, ayrım, Uzunluk(veri)), '.') + '.', numara)
model := GPT.Oluştur(Uzunluk(harfler), BAĞLAM, 32, 4, 2)
model.bırakma := 0.2
opt := Adam(model.Parametreler, 0.003)
enİyi := 1000.0
1'den 3000'e kadar her adım için
başla
g := []; h := []
1'den 8'e kadar her b için
başla
s := Rastgele(Uzunluk(eğitim) - BAĞLAM - 1)
g := g + Dilim(eğitim, s, s + BAĞLAM); h := h + Dilim(eğitim, s + 1, s + BAĞLAM + 1)
bitir
opt.oran := 0.003 * 0.5 * (1 + Cos(Matematik.pi * adım / 3000))
model.eğitimde := doğru
opt.SıfırlaGrad
kayıp := ÇaprazEntropi(model.İleri(g, 8, BAĞLAM), h)
kayıp.GeriYay
opt.Adım
eğer adım = 1 veya adım mod 250 = 0 ise
başla
model.eğitimde := yanlış
dk := 0; s := 0; b := 0
s + BAĞLAM + 1 <= Min(Uzunluk(doğrulama), 512) iken
başla
dk := dk + ÇaprazEntropi(model.İleri(Dilim(doğrulama, s, s + BAĞLAM), 1, BAĞLAM),
Dilim(doğrulama, s + 1, s + BAĞLAM + 1)).Değer
b := b + 1; s := s + BAĞLAM
bitir
eğer dk / b < enİyi ise başla enİyi := dk / b; model.Kaydet(DOSYA) bitir
bitir
bitir
model.Yükle(DOSYA)
model.eğitimde := yanlış
bitir
başla
harfler := DilAraclari.Harfler
numara := DilAraclari.Numaralar(harfler)
eğer Sistem.DosyaVarMı(DOSYA) ise
başla
model := GPT.Oluştur(Uzunluk(harfler), BAĞLAM, 32, 4, 2)
model.Yükle(DOSYA)
bitir
değilse YenidenEğit
yaz('"damlaya damlaya g" yazıldıktan sonra modelin tahmini:', 1)
P := SonrakiDağılım([0] + DilAraclari.Kodla('damlaya damlaya g', numara), 1.0, 0)
sıra := Sırala(Aralık(Uzunluk(P)), fonksiyon(z: tamsayı) => -P[z])
0'dan 4'e kadar her k için yaz(Biçimle(' "{}" {:.3}', harfler[sıra[k]], P[sıra[k]]), 1)
yaz('', 1); yaz('Açgözlü seçim (her çalıştırmada aynı sonuç):', 1)
['', 'damlaya', 'sabır', 'dost', 'göz'] içindeki her baş için
yaz(' ' + Üret(baş, 1.0, 0, doğru), 1)
Tohum(9)
[0.5, 1.0, 1.5] içindeki her T için
başla
yaz('', 1); yaz(Biçimle('Sıcaklık {}:', T), 1)
1'den 4'e kadar her i için yaz(' ' + Üret('', T, 0, yanlış), 1)
bitir
yaz('', 1); yaz('Top-k (k = 3, sıcaklık 1.0):', 1)
1'den 4'e kadar her i için yaz(' ' + Üret('', 1.0, 3, yanlış), 1)
bitir.Programın çıktısı şöyledir:
"damlaya damlaya g" yazıldıktan sonra modelin tahmini:
"a" 0.220
"e" 0.199
"ı" 0.188
"ü" 0.130
"ö" 0.114
Açgözlü seçim (her çalıştırmada aynı sonuç):
alan yaran yerin derin derin derin derin derin derin derin derin derin
damlayan yerin derin derin derin derin derin derin derin derin derin de
sabır der derin derin derin derin derin derin derin derin derin derin d
dostun derin derin derin derin derin derin derin derin derin derin deri
gözün alan alarar
Sıcaklık 0.5:
dolun ye derin dişin olur güşmaz
akarıyı yolur
aşan der yayır
bili biş yelinde alarır
Sıcaklık 1.0:
kakır yülm z biş kasanı kaparı sok övük düzüş tayı bırdığa pedinin meyi
ağacıyık dilver
esol
gelemeyn dolanl apırsın sörmeden binekince dermik
Sıcaklık 1.5:
aşıgcı dok
acilmama
yelanca butaya koktuçt oçuknununz kebıden düzüderlcs dererin aktloşan
ısarlın götürüsaz ork ult
Top-k (k = 3, sıcaklık 1.0):
alın deren dolunun düşmez daranı yeri deliş
alan kere yokmaz
atla kaş dürün karan dalır
alılan deri delirÇıktıyı okumak
İlk tablo modelin ne bildiğini gösteriyor. “damlaya damlaya g” yazıldıktan sonra model, g’den sonra bir ünlü geleceğinden emindir: ilk beş tahminin hepsi ünlü. Ama doğru cevap olan “ö”yü ancak beşinci sıraya koyuyor. Bu atasözü eğitim verisinde olduğu halde model onu ezberlememiş; bırakma ve erken durdurmanın istediğimiz etkisi budur. Model, gördüğü metinlerden hecelerin ve eklerin genel kurallarını çıkarmış.
Açgözlü seçim bir döngüye takılıyor. Beş başlangıcın dördü kısa sürede “derin derin derin…” tekrarına düşüyor. Model “derin” yazdıktan sonra en olası devamın yine “derin” olduğunu düşünüyor; açgözlü seçim de bu döngüden hiç çıkamıyor. Büyük dil modellerinde de aynı sorun görülür; bu yüzden sohbet uygulamaları nadiren açgözlü seçim kullanır.
Sıcaklık bir ayar düğmesidir. Sıcaklık 0,5’te üretilen metin kısa, düzenli ve Türkçeye en yakın olanı: “olur”, “akarıyı”, “bili” gibi sözcükler ve “-maz”, “-ır” ekleri. Sıcaklık 1,5’te sözcükler dağılıyor; “düzüderlcs” gibi Türkçede mümkün olmayan harf dizileri belirliyor.
Top-k sınırlı bir özgürlük tanıyor. Top-k ile sıcaklık 1,0’da metin çeşitli kalıyor ama saçma harf dizileri kayboluyor. “alın deren dolunun düşmez” gerçek bir atasözü olmasa da kulağa bir atasözü gibi geliyor.
Uygulamada bu ayarlar birlikte kullanılır. Bir kod yazma asistanı düşük sıcaklık ister, çünkü doğru ve tutarlı olmak yaratıcı olmaktan önemlidir. Şiir yazdıran biri ise sıcaklığı yükseltebilir.
Alıştırma. Programa top-p örneklemeyi ekleyiniz: SonrakiDağılım’a bir p parametresi veriniz; olasılıkları büyükten küçüğe sıralayıp toplamı p’yi geçene kadar olanları tutunuz, kalanları sıfırlayıp yeniden normalleştiriniz. p = 0,9 ile üretilen metni top-k ile karşılaştırınız.