Matematik sezgisi: vektörler, eğim, gradyan iniş
Kısaca
- Nokta çarpımı ve kosinüs benzerliğinin ne ölçtüğünü anlamak
- Türevi "bu yöne gidersem kayıp ne kadar değişir" diye okumak
- Gradyan inişi NumPy ile sıfırdan yazmak ve öğrenme oranının etkisini görmek
İlk adım: aşağıdaki Gradyan iniş deneyini bul ve içindeki görevi çöz. Okumadan önce kurcalamak, okuduğunu çok daha kolay anlamanı sağlar.
Korkma, formül ezberlemeyeceğiz. Bu derste üç fikri elinle deneyerek göreceksin: anlamı sayılarla ölçmek, doğru yönü bulmak ve küçük adımlarla ilerlemek. Bir modelin “öğrenmesi” dediğimiz şey bu üçünden ibaret.
1. Her şey bir vektör
Bir model için kelime, resim, kullanıcı ya da şarkı fark etmez. Hepsi bir sayı listesine dönüşür. Bu listeye vektör denir. “Kedi” kelimesi örneğin 768 sayıdan oluşan bir vektör olabilir.
Neden işe yarar? Çünkü iki vektörün birbirine ne kadar yakın olduğunu ölçebiliriz. Model, anlamca yakın şeylere yakın sayılar vermeyi öğrenir.
İki vektörün ne kadar aynı yöne baktığını nokta çarpımı söyler:
import numpy as np
kedi = np.array([0.9, 0.1, 0.8])
kopek = np.array([0.8, 0.2, 0.7])
araba = np.array([0.1, 0.9, 0.0])
def kosinus(a, b):
return (a @ b) / (np.linalg.norm(a) * np.linalg.norm(b))
print(kosinus(kedi, kopek)) # ~0.99: neredeyse aynı yön
print(kosinus(kedi, araba)) # ~0.20: alakasız
Kod yazmadan önce elinle dene. İki oku sürükle ve sayıların nasıl değiştiğine bak:
- a
- (2.2, 1.2)
- b
- (0.8, 2.3)
- a·b
- 4.52
- açı
- 42°
- kosinüs
- 0.741
benzer
- İki oku aynı yöne çevir
- Birbirine dik yap
- Tam zıt yönlere çevir
Uç noktalardan tutup sürükle. Okların uzunluğu değil, yönleri benzerliği belirler: kısa bir oku aynı yöne çevirsen de kosinüs 1’e yaklaşır. Bir dil modeli “kedi” ile “köpek” kelimelerinin yakın olduğunu tam olarak böyle ölçer, yalnızca 2 değil yüzlerce boyutta.
Kosinüs benzerliği 1’e yaklaştıkça iki şey birbirine benzer. Yedinci dersteki RAG sistemi, tam olarak bu fonksiyonla “soruna en çok benzeyen belgeyi” bulacak.
2. Eğim: hangi yöne gitmeli?
Bir modeli eğitmek, bir kayıp (loss) sayısını küçültmek demek. Kayıp, modelin ne kadar yanıldığını ölçer.
Türev, “parametreyi biraz artırırsam kayıp ne kadar değişir?” sorusunun cevabıdır. Türev pozitifse parametreyi artırmak kaybı artırır, o zaman azaltmalıyız. Negatifse tersi.
Noktayı eğrinin üstünde sürükle. Mavi çizgi o noktadaki eğim, kırmızı ok ise “aşağı” yön:
Birden fazla parametre olduğunda her birinin türevini bir vektörde toplarız: buna gradyan denir. Gradyan, kaybın en hızlı arttığı yönü gösterir. Biz tam tersine gideriz.
3. Gradyan iniş
Bir sinir ağını eğitmek, aslında şu tek satırı milyarlarca kez tekrarlamaktır:
parametre ← parametre − öğrenme_oranı × gradyan
Aşağıdaki lab’de tek bir parametre var ve kayıp eğrisi görünüyor. Önce öğrenme oranını 0,3’te bırakıp Oynat’a bas. Sonra 1,2 yap, sonra 2,1. Ardından “iki çukur” fonksiyonunu seç.
- adım
- 0
- x
- 3.600
- kayıp f(x)
- 6.480
- eğim f′(x)
- 3.600
Adım at ya da oynat. Her adımda top, eğimin tersi yönünde öğrenme oranı kadar ilerler.
Gerçek modellerde tek bir ağırlık değil milyonlarcası var, yani kayıp bir eğri değil, çok boyutlu bir yüzey. Aşağıda iki ağırlıklı bir modelin kayıp yüzeyi var: yükseklik kayıp, top modelin o anki ağırlıkları. Fareyle döndür, yüzeye tıklayıp topu farklı yerlere bırak. Bazen en derin çukura değil, yakındaki sığ bir çukura yuvarlandığını göreceksin.
Görmen gerekenler:
- Küçük oran: güvenli ama yavaş.
- Büyük oran: top çukurun iki yanında zıplar; çok büyükse kaçar (ıraksama).
- İki çukur: başladığın yere göre daha sığ bir yerel minimuma takılabilirsin. Gerçek modellerde bu yüzden momentum, Adam gibi daha akıllı iyileştiriciler ve rastgele başlangıçlar kullanılır.
4. Kendin yaz
Aynı şeyi bir doğru uydurmak için yapalım. Elimizde noktalar var ve y = w·x + b doğrusunu arıyoruz:
import numpy as np
rng = np.random.default_rng(0)
x = rng.uniform(-3, 3, 100)
y = 2.5 * x - 1 + rng.normal(0, 0.5, 100) # gerçek: w=2.5, b=-1
w, b, lr = 0.0, 0.0, 0.05
for adim in range(200):
tahmin = w * x + b
hata = tahmin - y
kayip = (hata ** 2).mean() # ortalama kare hata
dw = 2 * (hata * x).mean() # kaybın w'ye göre türevi
db = 2 * hata.mean() # kaybın b'ye göre türevi
w -= lr * dw
b -= lr * db
if adim % 40 == 0:
print(f"adım {adim:3d} kayıp {kayip:.3f} w {w:.2f} b {b:.2f}")
w 2,5’e, b −1’e yaklaşmalı. lr değerini 0,5 yapıp tekrar çalıştır: lab’de gördüğün ıraksamayı terminalde göreceksin.
İlham
Matematiğin bir dil olduğunu, sıfırdan başlayıp kendi kendini kuran bir dünya gibi göstermenin en güzel örneklerinden biri:
Kendini dene
1. İki gömme vektörünün kosinüs benzerliği 0,97. Bu ne anlama gelir?
2. Eğitim sırasında kayıp her adımda büyüyor ve sonunda NaN oluyor. İlk şüphelin ne olmalı?
3. Gradyan neyi gösterir?
Daha derine inmek istersen