Kitaplar / Yöntem ile Sıfırdan Dil Modeli / Bölüm 4 — Sinir ağıyla ikili model
Bölüm 4 — Sinir ağıyla ikili model
Saymak küçük bir pencere için işe yarar ama pencere büyüdükçe imkânsızlaşır. Son 10 karaktere bakan bir model için 30¹⁰, yani yaklaşık 590 trilyon satırlık bir tablo gerekirdi ve bu satırların neredeyse hepsi veride hiç görülmemiş olurdu. Çıkış yolu, tabloyu doldurmak yerine olasılıkları hesaplayan bir fonksiyon öğrenmektir: bir sinir ağı.
Bu bölümde aynı ikili modeli sinir ağıyla kurup sayarak bulduğumuz sonuca ulaşıp ulaşamadığımıza bakacağız. Bu, sonraki bölümlerde kullanacağımız tüm parçaların en sade halidir.
Dört adım
- Tek-sıcak kodlama. Karakter numarası 3 ise, 30 sayılık bir vektörün 3. yeri 1, geri kalanı 0 olur.
BirSıcakfonksiyonu bunu yapar. - Logitler. Bu vektörü 30 × 30’luk bir ağırlık matrisi W ile çarparız. Sonuç 30 sayıdır; her biri, o karakterin sırada gelme ihtimali için ham bir puandır. Bu puanlara logit denir. Logitler eksi de olabilir, toplamları 1 olmak zorunda değildir.
- Softmaks. Logitleri olasılığa çevirir: her birinin üstelini alır, toplama böler.
- Çapraz entropi. Doğru karaktere verilen olasılığın eksi logaritmasıdır; 3. bölümdeki kayıpla aynı şeydir.
Bu formülün sürpriz bir sonucu vardır. Tek-sıcak bir vektörü W ile çarpmak, W’nin bir satırını seçmekten başka bir şey değildir. Yani ağ, her karakter için bir satır sayı öğreniyor. Bu satıra o karakterin gömmesi (embedding) denir. Büyük dil modellerinin ilk katmanı da tam olarak budur: her simge için bir gömme satırı olan dev bir tablo.
program SinirAğıylaİkiliModel
{ Aynı ikili modeli bu kez sinir ağıyla kuruyoruz. Saymak yerine bir ağırlık
matrisi W öğreniriz:
girdi : önceki karakterin tek-sıcak vektörü x (30 sayı, biri 1, kalanı 0)
logit : x @ W (30 puan, her olası sonraki karakter için bir tane)
olasılık: softmaks(logit)
Kayıp çapraz entropidir: doğru sonraki karaktere verilen olasılığın -log'u.
x tek-sıcak olduğu için x @ W, W'nin bir satırını seçer; bu satıra o karakterin
"gömmesi" (embedding) denir. Büyük dil modellerinin ilk katmanı tam olarak budur. }
kullan Atasozleri, DilAraclari, YZ
değişken
veri, harfler: metin dizisi
numara: sözlük
girdiler, hedefler: tamsayı dizisi
a, kar: metin
i, j, n, önceki, adım: tamsayı
X, W, kayıp, P: tensör
opt: herhangi
sözcük: metin
başla
Tohum(42)
veri := Atasozleri.Hepsi
harfler := DilAraclari.Harfler
n := Uzunluk(harfler)
numara := DilAraclari.Numaralar(harfler)
{ Eğitim çiftleri: (önceki karakter, sonraki karakter) }
girdiler := []; hedefler := []
veri içindeki her a için
başla
önceki := 0
(a + '.').Karakterler içindeki her kar için
başla
girdiler.Ekle(önceki); hedefler.Ekle(numara[kar]); önceki := numara[kar]
bitir
bitir
yaz(Biçimle('{} eğitim çifti', Uzunluk(girdiler)), 1)
X := BirSıcak(girdiler, n) { 5282 × 30 }
W := RastgeleTensör(n, n, 0.1, doğru) { öğrenilecek 900 ağırlık }
opt := Adam([W], 0.1)
1'den 300'e kadar her adım için
başla
opt.SıfırlaGrad
kayıp := ÇaprazEntropi(X @ W, hedefler)
kayıp.GeriYay
opt.Adım
eğer adım = 1 veya adım mod 50 = 0 ise
yaz(Biçimle('Adım {:3}: kayıp {:.4}', adım, kayıp.Değer), 1)
bitir
yaz('', 1); yaz('Sinir ağının ürettiği "atasözleri":', 1)
1'den 8'e kadar her j için
başla
sözcük := ''; i := 0
tekrarla
P := Softmaks(BirSıcak([i], n) @ W) { 1 × 30 olasılık }
i := DilAraclari.Örnekle(P.Satır(0).Veri)
eğer i <> 0 ise sözcük := sözcük + harfler[i]
i = 0 olana dek
yaz(' ' + sözcük, 1)
bitir
bitir.Programın çıktısı şöyledir:
5282 eğitim çifti
Adım 1: kayıp 3.4135
Adım 50: kayıp 2.3569
Adım 100: kayıp 2.3475
Adım 150: kayıp 2.3449
Adım 200: kayıp 2.3436
Adım 250: kayıp 2.3429
Adım 300: kayıp 2.3424
Sinir ağının ürettiği "atasözleri":
n ayekacu suşi n a baker
k sttin klazü
tükolde dör
an hvar
yaven çi mazarüşen sa paye yağ hanevademaserırgere ktademaşmen seyvu dü yema dışiştakomağır bacayliltlezan dancayağadi yoll inden muş
sugöz umir ban k
sır
itanı yolürarÇıktıyı okumak
Kayıp 3,41’den başlıyor; bu, 3. bölümde hesapladığımız “hiçbir şey bilmeyen model” değerine (ln 30 ≈ 3,40) çok yakındır. Ağırlıklar küçük ve rastgele olduğu için model başta tüm karakterlere hemen hemen eşit olasılık veriyor.
300 adımda kayıp 2,3424’e iniyor. Düzleştirmesiz saymanın kaybı 2,3408 idi. Sinir ağı neredeyse aynı yere vardı ve vardığı yer bir rastlantı değildir: ikili bir model için en iyi olasılıklar, sayımdan çıkan oranlardır. Gradyan inişi bu oranları kendi başına buldu. Üretilen metnin 3. bölümdekine bu kadar benzemesinin nedeni de budur.
Değişen şey yöntemdir. Artık elimizde kayıp fonksiyonunu otomatik olarak küçülten bir düzenek vardır: kayıp.GeriYay her ağırlığın kayba etkisini (gradyanını) hesaplıyor, opt.Adım da ağırlıkları kaybı azaltacak yöne biraz kaydırıyor. Bu düzenek ağ ne kadar karmaşık olursa olsun aynı kalacak. Kitabın geri kalanında yalnızca X @ W kısmını daha akıllı bir fonksiyonla değiştireceğiz.
Neden ÇaprazEntropi’ye logit veriyoruz?
Dikkat ederseniz eğitimde ÇaprazEntropi(X @ W, hedefler) yazıyoruz; araya Softmaks koymuyoruz. ÇaprazEntropi softmaksı kendisi uygular ve bunu sayısal olarak daha güvenli bir yolla yapar. Metin üretirken ise olasılıkları kendimiz istediğimiz için Softmaks’ı elle çağırıyoruz.
Alıştırma. Eğitimden sonra “ş” harfinin satırına softmaks uygulayınız: Softmaks(BirSıcak([numara['ş']], n) @ W). En büyük beş olasılığı 3. bölümdeki “ş harfinden sonra en sık gelenler” listesiyle karşılaştırınız.