Kısım III · Merak · Bölüm 52
Eğitim: Kayıp ve Gradyan İnişi
Ağı yanlışından öğrendirmek (Training: loss and gradient descent)
Neden burada: Elimizde iki parça var ve ikisi de henüz boşta duruyor. Birincisi, rastgele ağırlıklarla çalışan ama kötü tahmin eden bir ağ (Bölüm 51). İkincisi, her ağırlık için "çıktıyı azıcık artırmak istersem seni hangi yöne çevirmeliyim?" sorusunun cevabını veren geri yayılım (Bölüm 50). Bu bölüm, ikisini birleştirip öğrenmenin kendisini kuruyor: ağın ne kadar yanlış olduğunu tek bir sayıya çeviriyoruz (kayıp), sonra ağırlıkları o sayıyı küçültecek yönde azar azar itiyoruz (gradyan inişi), ve bunu defalarca tekrarlıyoruz (eğitim döngüsü). Makine öğrenmesinin bütün gizemi, hiç abartmadan, bu üç cümledir.
Neye dayanıyor: Bölüm 50'den: loss.backward()'ın her parametrenin .grad'ine, "kaybı en hızlı artıracak yön ve hız"ı yazması. Bölüm 51'den: MLP'nin parameters() listesi (hepsi Value). Bölüm 48'den: eğim, azıcık değişirsen ne olur sorusudur; eğim pozitifse yukarı, negatifse aşağı demektir. Bölüm 47'den: eğitim ve çıkarım ayrımı.
- Kat 10Uygulamalar: bizimki ve içinde yaşayan yapay zekâEğitim, bir programın kendisi: bir döngü, birkaç toplama ve çarpma.
- Kat 4–9Python, işletim sistemi, bellekDöngüyü çalıştıran ve sayıları tutan katlar. Bölüm 9–20, 21.
- Kat 3İşlemci ve GPUEğitimin milyonlarca tekrarını yapan donanım. Bölüm 6, 55.4.
- Kat 0–2Bit, kapı, devreHer "adım" aslında bu katta bitlerin dönmesi. Bölüm 2–5.
Bu bölümün sonunda şunları bilebileceksin: kayıp fonksiyonu nedir ve neden bir sayı olmalı; gradyan inişi bir tepeden iniş gibi nasıl çalışır; öğrenme oranı neden ne çok büyük ne çok küçük olmalı; dört adımlık eğitim döngüsü (ileri, kayıp, geri, güncelle); gradyanı sıfırlamayı unutmak neden sorun; ve aşırı öğrenme (ezberleme) ne demek; micrograd'daki döngünün PyTorch'ta hiç değişmediğini.
52.1 Kayıp fonksiyonu: ne kadar yanlışız
Öğrenmenin ilk koşulu bir ölçüdür. Bir öğrenci sınav sonucunu hiç görmeden gelişemez; bir ağ da "ne kadar kötü olduğunu" sayıyla bilmeden gelişemez. Bu sayıya kayıp (loss) ya da kayıp fonksiyonu (loss function) denir. 3Blue1Brown buna maliyet (cost) der; aynı şeydir: ağın verdiği cevap ile istenen cevap arasındaki uyumsuzluğun tek bir sayısı. Büyükse kötüyüz, küçükse iyiyiz, sıfırsa kusursuzuz.1
Tek örnek için: farkın karesi
En basit kayıp: ağın tahmini ile istenen değer arasındaki farkı al, karesini al. Bölüm 51'deki örnek ağımızı hatırla: dört örnek, istenen çıktılar [1.0, -1.0, -1.0, 1.0]. Başlangıçta ağın tahminleri 0,6994, 0,5026, 0,6932, 0,8755'ti (Python'un random.seed(42) tohumuyla kurduğum ağda). İkinci örnek için istenen −1, tahmin 0,5026:
fark = tahmin - istenen = 0,5026 - (-1) = 1,5026
kare = 1,5026 * 1,5026 ≈ 2,258
Neden fark değil de farkın karesi? İki sebep. Birincisi işaret: tahmin istenenin altında da üstünde de olabilir; fark bazen negatif, bazen pozitiftir ve toplarken birbirini götürür. Kare her zaman pozitiftir; hata nereye olursa olsun "kötü" sayılır. İkincisi büyüklük: kare, büyük hataları orantısız biçimde cezalandırır (hata 2 katına çıkarsa ceza 4 katına). Bu bir tasarım seçimidir, tek seçenek değil; sonraki bölümlerde başka kayıp fonksiyonları da göreceğiz (Bölüm 54).
Bütün örnekler için: toplamak
Dört örneğin dördü için de karesel farkı hesaplayıp toplarsak, tek bir sayı elde ederiz. Karpathy'nin derste yazdığı satır:2
ypred = [n(x) for x in xs]
loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))
Satır satır: ilk satır, ağı dört girdiden her birine uygulayıp tahmin listesi yapar. İkinci satır, her tahmin (yout) ile istenen (ygt, "ground truth", gerçek değer) çiftini eşleştirir, farkın karesini alır ve hepsini toplar. Başlangıçtaki ağımın kaybı 5,2305 çıktı. Bu sayıyı yorumlamak için bir referans: dört örneğin hepsine doğru cevabı verseydi 0, hepsine tam ters bir cevap (+1 yerine −1) verseydi 4 × 4 = 16 olurdu. 5,23, yani "epey kötü ama tam ters değil".
Bu bakış açısı değişikliği bölümün en önemli fikri. Ağı kullanırken girdi (x) değişir, parametreler sabittir: tahmin = ağ(x). Ağı eğitirken bunu tersine çeviririz: veri sabit (dört örnek), parametreler değişken. Kayıp, parametrelerin bir fonksiyonu olur: "şu 41 sayıyı böyle ayarlarsam kayıp şu kadar çıkar." 3Blue1Brown bunu şöyle söyler: ağın kendisi girdiden çıktıya bir fonksiyondur; kayıp ise onun üstüne bir katman daha ekler, girdileri ağın 13.002 ağırlığı ve sapmasıdır ve tek bir sayı üretir.1 Eğitim, bu fonksiyonun en düşük noktasını bulma işidir.
Gerçek dünyada kayıbı hukukçu gözüyle şöyle düşünebilirsin: bir mahkemenin verdiği kararın bir "hata payı" olsaydı ve bu hata payını tek bir sayıya çevirebilseydik, "kararlarımızı daha iyi yapmak" sorusu bu sayıyı küçültmeye dönüşürdü. Aynı mantık ağ için de geçerli: "daha iyi ağ" demek "daha küçük kayıp" demek.
52.2 Gradyan inişi ve öğrenme oranı
Elimizde şimdi 41 ayarlanabilir parametre var ve bir sayıyı (kayıp) küçültmek istiyoruz. Rastgele denemek umutsuz: 41 parametre, her biri sonsuz değer alabilir. Gerek de yok, çünkü Bölüm 50'den bir bilgi var: gradyan.
Tepeden iniş
3Blue1Brown'ın imgesi şöyle: kayıp fonksiyonunu bir arazi gibi düşün; parametrelerin her bir kombinasyonu arazide bir konum, kayıp da o konumun yüksekliği. Bizim amacımız vadinin en dibini bulmak. Dibi doğrudan hesaplamak (eğimin sıfır olduğu yeri çözmek) çok karmaşık fonksiyonlar için mümkün değildir. Daha esnek bir yol: rastgele bir noktada başla, bulunduğun yerdeki eğime bak, eğim yukarı bakıyorsa aşağı yürü, tekrar bak, tekrar yürü. 3Blue1Brown'ın anlatımıyla "bir topun tepeden yuvarlanması".1
Çok boyutlu uzayda ("parametre sayısı kadar boyut") eğim tek bir sayı olmaz, bir yön olur: en dik çıkışın yönü. Bu yöne gradyan (gradient) denir (Bölüm 48.3). Gradyanın eksi işaretlisi, en dik iniş yönüdür. 3Blue1Brown'ın ifadesiyle, gradyanın her bileşeni iki şey söyler: işareti, o parametrenin yukarı mı aşağı mı itilmesi gerektiğini; büyüklüğü ise o değişimin ne kadar önemli olduğunu.1
Algoritma
Her parametre için tek kural: kaybın o parametreye göre eğimi pozitifse parametreyi azalt, negatifse artır. Matematiksel olarak:
yeni_değer = eski_değer - öğrenme_oranı * gradyan
Semboller: gradyan (p.grad): kaybın bu parametreye göre eğimi, geri yayılımın verdiği sayı. Eksi işareti: eğim yukarı bakıyorsa aşağı git. öğrenme_oranı (öğrenme oranı (learning rate)): adım büyüklüğünü ayarlayan küçük sabit bir sayı, örneğin 0,1. 3Blue1Brown'da "eta" harfiyle yazılır; küçük adımlar yavaş ama güvenli, büyük adımlar hızlı ama hedefi aşma riskli der.1 Bu bütün algoritma. Ona gradyan inişi (gradient descent) denir.
Tek bir parametreyle, sayıyla
Soyut kalmasın: Bölüm 51'deki ağın (tohum 42) birinci katmanındaki ilk nöronun ilk ağırlığına bakalım, tek ileri geçiş ve tek loss.backward() sonrası:
p.data = 0,2788... (şimdiki ağırlık)
p.grad = -1,3722... (kaybın bu ağırlığa göre eğimi)
Eğim negatif: bu ağırlığı artırırsam kayıp azalır. Güncelleme (öğrenme oranı 0,1):
yeni = 0,2788 - 0,1 * (-1,3722) = 0,2788 + 0,1372 = 0,4161
Ağırlığı artırdık, çünkü eğim negatifti. Bu eğimin doğru olup olmadığını kendim sınadım: ağırlığı 0,000001 kadar kıpırdatıp kaybı yeniden hesapladım ve aradaki farkı kıpırtıya böldüm (Bölüm 48'in "azıcık değiştir, ne kadar değişiyor" tanımı); sonuç −1,37226; geri yayılımın verdiği −1,37226 ile örtüştü. Yani motorun gradyanı sayısal olarak da doğrulandı; geri yayılımın inandırıcılığı budur.
Öğrenme oranı: Goldilocks
Öğrenme oranı küçük bir sayı gibi görünür ama eğitimin kaderini belirler. Aynı ağı üç farklı oranla 20 adım eğittim:
| Öğrenme oranı | 20 adım sonunda kayıp | Ne oldu |
|---|---|---|
| 0,0005 | ≈ 4,59 | 5,23'ten çok yavaş indi: adımlar çok küçük |
| 0,1 | ≈ 0,04 | sağlıklı iniş |
| 1,5 | 8,0 (donup kaldı) | ilk adımda aşırı zıpladı, sonra hiç kıpırdamadı |
1,5 durumunda ne oldu? Adım o kadar büyüktü ki ağırlıklar öyle bir yere fırladı ki tanh'ın çıktıları +1 ya da −1'e yapıştı (Bölüm 51.2'de gördüğün düzleşme bölgesi: eğim sıfıra çok yakın). Kayıp tam 8,0'da kaldı: iki örnek tamamen yanlış, her biri (2)² = 4 ceza, 4 + 4 = 8. Eğim sıfırsa gradyan da sıfır, gradyan sıfırsa adım da sıfır; ağ tuzağa düştü ve ne yaptığı kimsenin umurunda değil. Bu bir hata mesajı vermez, ağ "çalışmıyormuş gibi" davranır. Bu yüzden öğrenme oranı, eğitimin en hassas ayarlarından biridir.
Karpathy'nin ders defterinde bu kadar küçük ağ için 0,1 gibi bir değer kullanması tesadüf değil. (Bölüm 55'te bigram modelinde, aynı fikre rağmen, 50 gibi çok daha büyük bir değer kullanacağız: öğrenme oranı modele ve kayba göre değişir, evrensel bir "doğru değer" yoktur.)
3Blue1Brown'ın uyarısı: gradyan inişi sizi bir yerel dibe (local minimum) götürür, mutlaka dünyanın en derin vadisine değil. Başladığın yere (rastgele başlangıç ağırlıklarına) bağlıdır.1 Pratikte yine de çoğu ağ için yeterince iyi sonuç verir. İniş sırasında kayıp her adımda düşmek zorunda da değil: örnek ağımda ikinci adımda kayıp 3,12'den 3,27'ye çıktı (adım, eğrinin kıvrıldığı yerde biraz fazla büyüktü), sonra yeniden düşmeye başladı. Önemli olan genel eğilim.
52.3 Eğitim döngüsü: ileri, kayıp, geri, güncelle
Şimdi parçaları bir araya getirelim. Bir eğitim döngüsü (training loop) dört işi tekrar tekrar yapar:
- İleri geçiş: ağı örneklere uygula, tahminleri al (Bölüm 49).
- Kayıp: tahminleri istenenlerle karşılaştır, tek sayıya çevir (52.1).
- Geri geçiş:
loss.backward(); her parametrenin gradyanını hesapla (Bölüm 50). - Güncelle: her parametreyi gradyanın ters yönünde azıcık it (52.2).
Karpathy'nin ders defterindeki hali (okumayı kolaylaştırmak için yorum satırlarını Türkçeleştirdim):2
for k in range(20):
# 1-2. ileri geçiş ve kayıp
ypred = [n(x) for x in xs]
loss = sum((yout - ygt)**2 for ygt, yout in zip(ys, ypred))
# 3. geri geçiş
for p in n.parameters():
p.grad = 0.0
loss.backward()
# 4. güncelleme
for p in n.parameters():
p.data += -0.1 * p.grad
print(k, loss.data)
Satır satır: for k in range(20): yirmi tur. n.parameters(): Bölüm 51'in 41 parametrelik listesi. p.grad = 0.0 satırının neden orada olduğu 52.4'te. loss.backward(): 41 parametrenin hepsine gradyan yazar. p.data += -0.1 * p.grad: tek tek her parametre için 52.2'deki güncelleme formülü; p.data değerin kendisi, -0.1 eksi öğrenme oranı. Hepsi bu.
Aynı döngüyü tohum 42'li ağımla çalıştırdım. Her adımdaki kayıp (güncellemeden önceki):
| Adım | Kayıp | Adım | Kayıp |
|---|---|---|---|
| 0 | 5,2305 | 10 | 0,0837 |
| 1 | 3,1241 | 12 | 0,0658 |
| 2 | 3,2660 | 15 | 0,0493 |
| 3 | 0,8522 | 17 | 0,0420 |
| 5 | 0,3751 | 19 | 0,0365 |
Yirmi güncellemeden sonra ağın dört tahmini 0,906, −0,952, −0,876 ve 0,912 oldu; istenen +1, −1, −1, +1'di. Yani ağ işaretleri doğru bulmuş, değerleri de hedefe yaklaştırmış. Yüz adım sonra kayıp 0,0049'a indi, tahminler 0,967, −0,982, −0,952, 0,967 oldu. Başladığımız yerde ağırlıkları rastgele olan bir ağ, kimse ona kural söylemeden bu dört örneği "öğrendi".
Bunun neden önemli olduğunu burada durup düşün. Kimse ağa "birinci ve dördüncü girdi şu işareti taşıyorsa pozitif de" demedi. Ağa yalnızca örnekler ve bir hata ölçüsü verildi. Bölüm 47.2'deki "kuralı yazmak yerine örnekten çıkarmak" ayrımının somut hali bu 10 satırlık döngü. Aynı döngü, çok daha büyük bir ölçekte, bugünkü dil modellerini de eğitiyor.
Uygulamamızda eğitim döngüsüne benzeyen bir şey zaten var, yalnızca insanlar için: bir kullanıcı bir soruyu cevaplar (ileri geçiş), doğru ya da yanlış olduğu belli olur (kayıp: yanlışsa bir can kaybı), seri ve puan buna göre güncellenir (güncelleme) ve ertesi gün tekrar eder (döngü). Bu bir benzetme, bir uygulama değil: puan sistemi bir sinir ağı değildir. Ama bu benzetme bir şeyi doğru gösterir: öğrenme, ölçülebilir bir geri bildirimin ardından küçük düzeltmeler yapıp tekrarlamaktır. Eğer bir gün kullanıcının hangi konuda zorlandığını tahmin eden bir model eğitmek istersek, döngü tam olarak bu bölümdeki döngü olacaktır: veri (kullanıcı cevapları), kayıp (tahminle gerçek cevap arasındaki fark), gradyan inişi. Gerçek bir ağ eğitmeden önce, çoğunlukla basit bir SQL sorgusu (Bölüm 38) "bu kullanıcı hangi etiketlerde en çok yanlış yapıyor" diye sormak çok daha ucuz ve açıklanabilir bir çözümdür.
52.4 Sık hatalar: gradyanı sıfırlamayı unutmak; aşırı öğrenme
Gradyanı sıfırlamayı unutmak
Döngüdeki p.grad = 0.0 satırı neden var? Hatırla, Bölüm 50'deki _backward fonksiyonları gradyanı = ile değil += ile yazar: self.grad += other.data * out.grad. Bunun sebebi, bir değerin grafikte birden çok yerde kullanılabilmesi ve her kullanımdan gelen katkının toplanması gerektiğidir. Ama bu, .grad'in bir önceki turdan kalan değerle toplanacağı anlamına da gelir. Sıfırlamazsak, gradyan "şimdiki eğim" olmaktan çıkar ve "şimdiye kadarki bütün eğimlerin toplamı" olur. PyTorch'un öğreticisi de aynı şeyi söyler: geri geçişte gradyanlar birikir (accumulate), doğru gradyan için önceki gradyanı sıfırlamak gerekir.3 micrograd'ın Module sınıfında bunun için bir zero_grad() metodu hazırdır (Bölüm 51).
Ne olur? Merak ettim ve denedim: aynı ağı, p.grad = 0.0 satırı olmadan, 5 farklı rastgele tohum ve 2 öğrenme oranıyla 20 adım eğittim (toplam 10 deneme). Sonuç beklediğimden ilginçti:
| Durum | Sonuç (20 adım sonra kayıp) |
|---|---|
| Sıfırlamalı (doğru döngü), 10 denemede | hepsinde 0,01 ile 0,09 arası, sorunsuz iniş |
| Sıfırlamasız, 10 denemenin 9'u | 0 ile 0,0015 arası: şaşırtıcı biçimde hatta daha hızlı |
| Sıfırlamasız, 10 denemenin 1'i (tohum 3, oran 0,1) | 8,0 (bölümdeki tuzağa düştü, takılı kaldı) |
Yani gradyanı sıfırlamamak bu minik örnekte her zaman felaket değil; birikmiş gradyanlar bir tür "ivme" gibi davranıp adımları büyütüyor, hız kazandırıyor. Ama bu şanslı bir tesadüf: adımın anlamı bozuldu, ne kadar büyüyeceği ağın şekline bağlı ve aynı hata bir başka tohumda ağı 8,0'da dondurdu. Bu bir hata türü olarak çok tehlikelidir, çünkü hata mesajı vermez: kod çalışır, kayıp bir şeyler yapar, siz sonuca bakıp "belki bu işin doğası" diye düşünürsünüz. Kuralı basit tut: her turda, geri geçişten önce gradyanları sıfırla.
Aşırı öğrenme
İkinci tuzak başka türden. Eğitimin amacı, ağın görmediği örneklerde de iyi olması; yalnızca gördüğü örnekleri ezberlemesi değil. Bir öğrenci geçmiş yılların sınav sorularını ezberleyip yeni soruda çuvallayabilir; bir ağ da eğitim verisinde kayıp sıfıra yakınken yeni veride kötü olabilir. Buna aşırı öğrenme (overfitting) denir. 3Blue1Brown'ın dersinde bu şöyle geçer: ağın başarısı, görmediği (test) verilerde sınanır; eğitim verisinden bir kısmı bu amaçla ayrı tutulur.1
Bunu Bölüm 53'te yazacağımız isim modeliyle somut göstereyim. Henüz modeli anlatmadım (kısaca: harf çifti sayma tablosu); şimdilik yalnızca sonucu gör. Karıştırılmış 32.033 isimden eğitim için sadece ilk 200 ismi kullanıp, kalan ve eğitimde görülmeyen 2.000 isimde sınadım. Karşılaştırma ölçüsü, "ortalama kayıp"; küçük olan iyi (anlamı Bölüm 54'te):
| Eğitim verisi | Eğitimdeki kayıp | Görülmeyen veride kayıp |
|---|---|---|
| 200 isim | 2,308 | 2,894 |
| 2.000 isim | 2,443 | 2,496 |
| 30.000 isim | 2,454 | 2,457 |
(Model en az düzgünleştirmeli sürümüydü; Bölüm 54.3'te düzgünleştirmeyi öğreneceğiz. Bir not: isim listesinde bazı isimler birden çok kez geçtiği için görülmeyen veri tamamen "yeni" değil; yine de eğilim açık.) Küçük eğitim kümesinde model eğitimdeki verisini "iyi biliyor" (2,31) ama görmediği veride kötü (2,89): fark 0,59. Veri büyüdükçe fark 0,003'e kadar küçülüyor. Ezber, az veriyle kolaydır; çok veri ağı genelleme yapmaya zorlar. Bu yüzden gerçek eğitimlerde veriyi eğitim ve doğrulama kümelerine ayırırız (Bölüm 56.4).
52.5 micrograd'dan PyTorch'a: aynı fikir, tensörlerle
Bu bölümde yazdığımız her şey, gerçek derin öğrenme kütüphanelerinde de aynı. PyTorch, micrograd'ın yaptığını çok daha hızlı ve çok daha büyük ölçekte yapar: Value yerine tensör (tensor) adı verilen sayı ızgaraları (Bölüm 55.3'te anlatılacak) üzerinde çalışır, geri geçişi otomatik hesaplar, ve GPU'yu kullanır. micrograd'ın README'si ve testleri bunun açık bir kanıtıdır: testlerde PyTorch, micrograd'ın hesapladığı gradyanları doğrulamak için referans olarak kullanılır.4
Karşılaştırma tablosu:
| Adım | micrograd (bu bölüm) | PyTorch |
|---|---|---|
| Parametreler | n.parameters() (Value listesi) | tensörler, requires_grad=True ile işaretlenir3 |
| Gradyanı sıfırla | p.grad = 0.0 | W.grad = None ya da zero_grad() |
| Geri geçiş | loss.backward() | loss.backward() |
| Güncelleme | p.data += -0.1 * p.grad | W.data += -0.1 * W.grad (elle) ya da bir optimizer |
Satırlar Karpathy'nin makemore dersindeki PyTorch hâlidir (Bölüm 55'te kullanacağız):5
# geri geçiş
W.grad = None # gradyanı sıfırla
loss.backward()
# güncelleme
W.data += -50 * W.grad
Bu iki bloğun her satırını artık tanıyorsun: aynı sıfırlama (None, sıfır yerine "hiç gradyan yok" demek; sıfırlamak kadar etkili), aynı backward, aynı güncelleme (öğrenme oranı burada 50). İsim farkları var, fikir aynı. makemore'un kendi kodu (makemore.py) elle yazılmış güncellemeyi bile bırakır ve hazır bir optimizer (torch.optim.AdamW) kullanır; her turda model.zero_grad(set_to_none=True) çağrılır.6 Optimizer, güncelleme kuralını (p.data += -lr * p.grad) ve daha akıllı varyantlarını (adım büyüklüğünü kendi ayarlayan) sizin yerinize uygulayan hazır bir araçtır; bizim 4. adımın bir fabrikadan çıkmış hali.
Bölüm 47'de eğitim ile çıkarımı ayırmıştık: eğitim parametreleri ayarlar, çıkarım ayarlanmış modeli kullanır. Artık ikisini de görebiliyorsun: eğitim bu bölümdeki döngü (ileri-kayıp-geri-güncelle, binlerce tur), çıkarım yalnızca ileri geçiş (n(x)), kayıp yok, geri yok, güncelleme yok. Bölüm 48'de eğim sezgisini kurmuştun; burada o eğim, "ağırlığı hangi yöne çevireyim" sorusunun cevabı oldu. Bölüm 50'deki geri yayılım, 41 parametrenin her birine kendi eğimini yazan makine; Bölüm 51 o parametrelerin kimler olduğunu söyledi. Hepsi yerli yerine oturdu.
Bu bölümde neler kuruldu
Kayıp fonksiyonu, bir ağın ne kadar yanlış olduğunu tek bir sayıya çevirir; kayıp, parametrelerin bir fonksiyonudur (veri sabit). Gradyan inişi, her parametreyi gradyanın ters yönünde, öğrenme oranı kadar iterek kaybı küçültür: yeni = eski − oran × gradyan. Öğrenme oranı ne çok küçük (yavaş) ne çok büyük (zıplar, düzleşen bölgeye takılır) olmalıdır. Eğitim döngüsü: ileri geçiş, kayıp, geri geçiş, güncelleme; bir tur. Sık hatalar: gradyanı sıfırlamayı unutmak (gradyanlar birikir; bu bazen sinsi biçimde "çalışır") ve aşırı öğrenme (eğitim verisinde iyi, görülmeyen veride kötü). PyTorch aynı döngüyü tensörlerle, GPU'da ve hazır optimizer'larla yapar; fikir değişmez.
Terimler sözlükte, Bölüm 52 başlığı altında.
3Blue1Brown, "Gradient descent, how neural networks learn": özellikle The Cost Function, Minimizing the Cost Function ve Beyond Slope: Using The Gradient başlıkları. Derinleşmek için: Karpathy, nn-zero-to-hero deposundaki micrograd ders defterlerinin son bölümü (dört örnekli eğitim döngüsü) ve PyTorch, "Automatic Differentiation with torch.autograd" (gradyanların birikmesi).
Takıldığın her yeri yapay zekâ öğretmenine sor. Bölüme özgü alıştırma: ondan, tek parametreli ve tek örnekli bir kayıp için (örneğin tahmin = w·3, istenen 6) üç tur gradyan inişini elle yaptırmasını iste. Öğrenme oranını 0,1, 0,5 ve 1,0 al; kaybın her birinde nasıl davrandığını izle (biri hızlı iner, biri aşar).
Bölüm sonu soruları
Kitaba bakmadan cevapla. Kâğıt kalem serbest.
p.grad = 0.0 satırı neden vardır?loss.backward() ve p.data += -0.1 * p.grad PyTorch'ta nasıl karşılık bulur?Örnek cevabı göster
Sisli havada vadinin nerede olduğunu göremiyorsun ama ayağının altındaki eğimi hissedebiliyorsun (gradyan). Eğim aşağıya doğruysa o yöne bir adım atıyorsun, sonra yeniden hissedip tekrar adım atıyorsun. Öğrenme oranı adımının uzunluğu: çok küçükse vadiye varmak çok uzun sürer; çok büyükse vadiyi aşıp karşı yamaca fırlarsın ya da hiç kıpırdamayacağın düz bir yere düşersin. Ayrıca vadinin en derin vadi olduğunun garantisi yok.
Cevabı göster
Tahmin = 3, kayıp = (3 − 6)² = 9. Gradyan = 2·(3 − 6)·3 = −18. Yeni w = 1 − 0,05·(−18) = 1 + 0,9 = 1,9. Yeni tahmin 5,7, yeni kayıp (5,7 − 6)² = 0,09: tek adımda kayıp 9'dan 0,09'a indi.
Kaynaklar
- 3Blue1Brown, "Gradient descent, how neural networks learn" (yazılı ders sayfası; ders: Grant Sanderson, metin uyarlaması: Josh Pullen): maliyet fonksiyonu, tepe/vadi imgesi, gradyan ve eksi gradyan, öğrenme oranı, yerel minimum, eğitim ve test verisi.
- Karpathy, nn-zero-to-hero, micrograd ders defteri (ikinci yarı): dört örnekli veri kümesi, kayıp hesabı, eğitim döngüsü.
- PyTorch, Automatic Differentiation with torch.autograd:
requires_grad, geri geçişte gradyanların.grad'de birikmesi, gradyanı sıfırlama gerekliliği. - Karpathy, micrograd README'si: testlerin gradyanları PyTorch ile doğrulaması;
demo.ipynb'nin SGD ile bir MLP'yi eğitmesi. - Karpathy, makemore_part1_bigrams.ipynb:
W.grad = None; loss.backward(); W.data += -50 * W.gradsatırları. - Karpathy, makemore deposu,
makemore.py:torch.optim.AdamWvemodel.zero_grad(set_to_none=True).