Ders 20 / 24
Hesap Çizgesi ve Otomatik Türev
Eğim hesabını mimariden ayıran soyutlamanın ders içinde yazılması ve elle yazılan geri yayılımla karşılaştırılması: otuz iki satırlık dört işlemli bir düzenek, seksen bir parametrenin eğimini elle yazılan on sekiz satırlık geri yayılımdan 2,78e-17 farkla veriyor ve otuz örnekli bir toplu için 6.622 düğüm kuruyor. Kursun üç sayısı burada kurulur: taban çizgisi 0,7579, ağın sayısı 0,8095 ve yalnız başlangıç değerleri değişen ikinci koşum 0,7937. On ilklendirmenin aralığı 0,7857 ile 0,8095 arasındadır ve M27/K03'ün karar ağacı (0,7857) ile doğrusal modelinin (0,8016) sayıları bu aralığın içine düşer.
İçindekiler
Önceki on derste mimari seçildi: evrişim, havuzlama, atlamalı bağlantı, yinelemeli durum, kapı birimi, dikkat, gömme, aktarım, otokodlayıcı. Her birinde ağın yapısı değişti ve eğim hesabı yeniden türetilip yeniden yazıldı; hepsi elle yazılmış küçük bir eğitim döngüsünde koştu. Gerçek eğitimin düzeneği hiç ele alınmadı.
Bu konu o düzeneği ele alır ve ilk parçası eğim hesabını mimariden ayıran soyutlamadır. Katalogda bu ders derin öğrenme kütüphanelerini anar; burada anlatılan kütüphaneler değil, kütüphanelerin sattığı soyutlamadır — hesap çizgesi (computation graph) ve otomatik türev (automatic differentiation) — ve soyutlama ders içinde yazılır. Ölçü iki sayıdır: elle yazılan geri yayılım ile otomatik türevin verdiği eğim arasındaki fark, ve iki yolun kaç satır tuttuğu.
- EP1. Küme M27/K01–K04’ün kurgu abone tablosudur, tohum 20260218, 1.260 abone; etiket kaçak ya da arıza şüphesidir ve kurgudur. Taban çizgisi en sık sınıfı söylemektir: sınamada 0,7579, M27/K01–K03’ten devralınır.
- EP2. Eğitim kümesi bu konuda 756 yerine 300 satırdır; bir ölçek kararıdır ve konunun bütün blokları birkaç saniyede koşar. Sınama kümesi 252 satırdır ve bir abone 0,0040 eder.
- EP3. Ağ bu konu boyunca sabittir: sekiz öznitelik, sekiz birimli tek gizli katman (doğrultulmuş doğrusal birim), tek çıkış; kayıp çapraz düzensizliktir. Katmanın sabit terimi yanma diye anılır ve istatistikteki yanlılıktan ayrıdır. Ölçekleme yalnız eğitim kümesinden öğrenilir (M27/K02, boru hattı).
- EP4. Kursun üçüncü sayısı ikinci koşumdur: aynı ağ, aynı veri, aynı örnek sırası, yalnız başlangıç değerleri değişir. Ölçü ham süre değildir: çizgenin bedeli düğüm, kodun bedeli satır sayısıyla ölçülür.
- EP5. Kayıp düğümü kaynaşıktır: sigmoit ile çapraz düzensizlik tek düğümde tutulur, çünkü ayrı tutulduğunda büyük çıkışlarda taşma olur. Yerel türevi iki yolda da aynıdır. Düzenek modeldir ve hiçbir çerçeve, kitaplık ya da satıcı adı anılmaz.
Küme, Ölçek ve Taban Çizgisi
# ORTAK — KURGUDUR. M27/K01-K04'un abone tablosu ayni tohumla (20260218) uretilir; # etiket kacak/ariza suphesidir. Egitim kumesi bu konuda 756'dan 300 satira # KUCULTULMUSTUR: konunun butun bloklari birkac saniyede kosar. import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF BOLGE = [("kuzey", 0.28, 21, 0.00), ("guney", 0.22, 17, -0.10), ("dogu", 0.18, 26, 0.30), ("bati", 0.14, 14, -0.05), ("merkez", 0.18, 23, 0.05)] ALAN = ["b_guney", "b_dogu", "b_bati", "b_merkez", "hane", "memnuniyet", "donem", "ortalama"] def uretec(t): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki(): s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki def ayrik(u, w): t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 def karistir(dizi, tohum): r, s = uretec(tohum), list(dizi) for i in range(len(s) - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] return s VERI = [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]) memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) if r() < 0.046: continue no = 10001 + i r, v = uretec(TOHUM + 7000 + no), [] for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): v.append(0.0 if r() < 0.038 else math.floor( b[2] * math.exp((r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100) r() if not v: continue ort, oyn, r = sum(v) / len(v), max(v) - min(v), uretec(TOHUM + 51000 + no) z = (0.052 * (ort - 20) + 0.85 * (min(v) == 0.0) + 0.026 * oyn + 0.24 * (hane >= 5) - 0.20 * (memnun >= 4) + b[3] + 0.9 * (no - 10001) / 1399 + (r() + r() + r() - 1.5) * 1.30) x = {"hane": hane, "memnuniyet": memnun, "donem": len(v), "ortalama": round(ort, 2), "supheli": int(z > 1.35)} for q in BOLGE[1:]: x["b_" + q[0]] = int(b[0] == q[0]) VERI.append(x) K = karistir(VERI, TOHUM + 90000) EGT, SIN = K[:300], K[1008:] def tablo(satirlar, ist=None): X = [[float(s[a]) for a in ALAN] for s in satirlar] if ist is None: # olcek yalniz egitim kumesinden ogrenilir ist = [] for j in range(4, 8): m = sum(v[j] for v in X) / len(X) ist.append((j, m, math.sqrt(sum((v[j] - m) ** 2 for v in X) / len(X)))) for v in X: for j, m, sd in ist: v[j] = (v[j] - m) / sd return X, [s["supheli"] for s in satirlar], ist XE, yE, IST = tablo(EGT) XS, yS, _ = tablo(SIN, IST) TABAN = sum(v == 0 for v in yS) / len(yS) print(f"kurgu abone {len(VERI)}; egitim {len(XE)} (756'dan kucultuldu), sinama " f"{len(XS)}, oznitelik {len(ALAN)}, egitimde supheli pay " f"{sum(yE) / len(yE):.4f}") print(f"taban cizgisi (en sik sinifi soylemek, sinamada) {TABAN:.4f}")
kurgu abone 1260; egitim 300 (756'dan kucultuldu), sinama 252, oznitelik 8, egitimde supheli pay 0.2200 taban cizgisi (en sik sinifi soylemek, sinamada) 0.7579
Çizge Bir Veri Yapısıdır
Elle türetmenin sıkıntısı hesabın zorluğu değil, yapıya bağlı olmasıdır: katman eklendiğinde türev yeniden yazılır. Hesap çizgesi bu bağı koparır. Her ara değer bir düğüm olarak tutulur ve düğüm kendi değerini, atalarını ve atalarına göre yerel türevini saklar; geri geçiş çizgeyi tersten gezip her düğümün eğimini atalarına dağıtır. Zincir kuralı bu dağıtımdır ve yalnız bir kez yazılır.
# Hesap cizgesi duzenegi — MODELDIR. Dort islem: toplama, carpma, dogrultma ve # kaynasik kayip. Her dugum degerini, egimini, atalarini ve ATALARINA GORE YEREL # TUREVINI tutar; geri adim yalnizca bunlari kullanir. import inspect class Deger: __slots__ = ("v", "e", "ata", "yerel") def __init__(self, v, ata=(), yerel=()): self.v, self.e, self.ata, self.yerel = float(v), 0.0, ata, yerel def __add__(self, o): o = o if isinstance(o, Deger) else Deger(o) return Deger(self.v + o.v, (self, o), (1.0, 1.0)) def __mul__(self, o): o = o if isinstance(o, Deger) else Deger(o) return Deger(self.v * o.v, (self, o), (o.v, self.v)) def dogrult(self): return Deger(self.v if self.v > 0 else 0.0, (self,), (1.0 if self.v > 0 else 0.0,)) def kayip(self, y): # capraz duzensizlik, dogrudan cikisa p = 1.0 / (1.0 + math.exp(-self.v)) if self.v > -30 else 0.0 k = max(0.0, self.v) + math.log(1.0 + math.exp(-abs(self.v))) - self.v * y return Deger(k, (self,), (p - y,)) def geriye(kok): sira, gorulen = [], set() def gez(d): if id(d) in gorulen: return gorulen.add(id(d)) for a in d.ata: gez(a) sira.append(d) gez(kok) kok.e = 1.0 for d in reversed(sira): for a, y in zip(d.ata, d.yerel): a.e += d.e * y return len(sira) SATIR = sum(len([s for s in inspect.getsource(o).splitlines() if s.strip()]) for o in (Deger, geriye)) print(f"duzenek {SATIR} satir, 4 islem; L = 5 * dogrult(a*b + c)") for bd in (3.0, -3.0): a, b, c = Deger(2.0), Deger(bd), Deger(4.0) L = (a * b + c).dogrult() * Deger(5.0) n = geriye(L) print(f" a=2 b={bd:+.0f} c=4 -> L={L.v:5.1f}, {n} dugum; dL/da {a.e:>6.1f}" f" dL/db {b.e:>6.1f} dL/dc {c.e:>6.1f}")
duzenek 32 satir, 4 islem; L = 5 * dogrult(a*b + c) a=2 b=+3 c=4 -> L= 50.0, 8 dugum; dL/da 15.0 dL/db 10.0 dL/dc 5.0 a=2 b=-3 c=4 -> L= 0.0, 8 dugum; dL/da 0.0 dL/db 0.0 dL/dc 0.0
Otuz iki satır ve dört işlem. Türevler elle denetlenebilir: pozitif bölgede , ve verir; çıktı bunu söylüyor. İkinci çağrıda yalnız eksi üç oldu: toplam eksiye düştü, doğrultma kapısı kapandı, üç türev de sıfır oldu. Çizge aynı, kod aynı; değişen yalnız verinin çizgede açtığı yol.
Aynı Eğim, İki Yol
# Ayni agin egimi iki yoldan: cizgeyi gezerek ve zincir kuralini ELLE yazarak. # Parametreler tek duz liste: p[j*G+i] agirlik, p[H*G+j] yanma, p[H*G+H+j] ve # p[-1] cikis katmani. G, H = len(ALAN), 8 def ilklendir(tohum): # kazanc olcekli ilklendirme r = uretec(tohum) return [(r() * 2 - 1) * math.sqrt(2.0 / G) for _ in range(H * G)] + [0.0] * H \ + [(r() * 2 - 1) * math.sqrt(2.0 / H) for _ in range(H)] + [0.0] def cizgeyle(p, X, y, par): d, top = [Deger(v) for v in p], None for k in par: x, o = X[k], d[-1] for j in range(H): z = d[H * G + j] for i in range(G): z = z + d[j * G + i] * x[i] o = o + d[H * G + H + j] * z.dogrult() L = o.kayip(y[k]) top = L if top is None else top + L kok = top * (1.0 / len(par)) return kok, geriye(kok), [u.e for u in d] def elle(p, X, y, par): g, kayip = [0.0] * len(p), 0.0 for k in par: x, hh = X[k], [0.0] * H for j in range(H): s = p[H * G + j] + sum(p[j * G + i] * x[i] for i in range(G)) hh[j] = s if s > 0 else 0.0 o = p[-1] + sum(p[H * G + H + j] * hh[j] for j in range(H)) kayip += max(0.0, o) + math.log(1.0 + math.exp(-abs(o))) - o * y[k] d = 1.0 / (1.0 + math.exp(-o)) - y[k] # kayip dugumunun yerel turevi g[-1] += d for j in range(H): g[H * G + H + j] += d * hh[j] if hh[j] > 0: # dogrultma kapisi kapaliysa gecmez g[H * G + j] += d * p[H * G + H + j] for i in range(G): g[j * G + i] += d * p[H * G + H + j] * x[i] return kayip / len(par), [v / len(par) for v in g] P0, TOPLU = ilklendir(TOHUM + 1), list(range(30)) kok, DUGUM, oto = cizgeyle(P0, XE, yE, TOPLU) kayip, el = elle(P0, XE, yE, TOPLU) print(f"parametre {len(P0)}; 30 ornekli toplu icin cizge {DUGUM} dugum, " f"ornek basina {DUGUM / 30:.1f}") print(f"kayip cizge {kok.v:.10f} elle {kayip:.10f}") print(f"egimlerin en buyuk mutlak farki {max(abs(u - v) for u, v in zip(oto, el)):.2e}" f" (en buyuk egim {max(abs(v) for v in oto):.4f})") print(f"elle yazilan yol {len(inspect.getsource(elle).splitlines())} satir " f"ve yalniz bu aga ait; duzenek {SATIR} satir ve agi hic bilmiyor")
parametre 81; 30 ornekli toplu icin cizge 6622 dugum, ornek basina 220.7 kayip cizge 0.7366651135 elle 0.7366651135 egimlerin en buyuk mutlak farki 2.78e-17 (en buyuk egim 0.3097) elle yazilan yol 18 satir ve yalniz bu aga ait; duzenek 32 satir ve agi hic bilmiyor
Dersin birinci sayısı burada. Seksen bir parametrenin eğimi iki yoldan hesaplandı ve en büyük
mutlak fark 2,78e-17 çıktı: kayan noktalı toplama sırasının ürettiği fark. En büyük eğim
0,3097 olduğuna göre iki yol on beş basamak boyunca aynı sayıyı veriyor; eşitlik == ile
değil, farkın en büyük eğime oranıyla denetlenir.
İkinci sayı tersini söyler. Elle yazılan yol on sekiz satır tuttu ve bu satırlar yalnız bu ağa
aittir; katman eklenirse yeniden yazılır. Otuz iki satırlık düzenek ağın yapısını hiç bilmez,
ileri geçişi yazan kim olursa olsun eğimi aynı geriye çağrısı verir. Bedeli üçüncü sayıdadır:
otuz örneklik toplu için çizge 6.622 düğüm kurdu, örnek başına 220,7. Elle yazılan yol düğüm
tutmaz, ara değerleri yerinde toplar.
Kursun Üç Sayısı
# Egitim ELLE yazilan geri yayilimla koser; cizge dogrulama icin kuruldu. Iki # kosum yalnizca BASLANGIC DEGERLERINDE ayrilir: ornek sirasi ikisinde de ayni. ADIM, TUR, TOPLU_BOY, SIRA_TOHUMU = 0.30, 40, 30, TOHUM + 700 def egit(tohum): p = ilklendir(tohum) for t in range(TUR): dizin = karistir(range(len(XE)), SIRA_TOHUMU + t) for bas in range(0, len(dizin), TOPLU_BOY): _, g = elle(p, XE, yE, dizin[bas:bas + TOPLU_BOY]) p = [a - ADIM * b for a, b in zip(p, g)] return p def dogruluk(p, X, y): n = 0 for k in range(len(X)): x = X[k] o = p[-1] + sum(p[H * G + H + j] * max(0.0, p[H * G + j] + sum(p[j * G + i] * x[i] for i in range(G))) for j in range(H)) n += (o >= 0.0) == (y[k] == 1) return n / len(X) S = [dogruluk(egit(TOHUM + t), XS, yS) for t in range(1, 11)] print(f"ag {G}-{H}-1, {len(P0)} parametre, {TUR} tur, toplu boy {TOPLU_BOY}, " f"ogrenme adimi {ADIM}, {TUR * (len(XE) // TOPLU_BOY)} guncelleme") print(f" taban cizgisi {TABAN:.4f}") print(f" agin sayisi {S[0]:.4f} (fark {S[0] - TABAN:+.4f})") print(f" ikinci kosum {S[1]:.4f} (fark {S[1] - TABAN:+.4f})") print(f"on ilklendirmede aralik {min(S):.4f} - {max(S):.4f}, genislik " f"{max(S) - min(S):.4f} ({round((max(S) - min(S)) * len(XS))} abone)") AGAC, DOGRUSAL = 198, 202 # M27/K03'un sayilari, ayni 252 satirlik sinamada en_az, en_cok = round(min(S) * len(XS)), round(max(S) * len(XS)) print(f"karsilastirma cizgileri (756 satirlik egitim kumesiyle): karar agaci {AGAC / len(XS):.4f}, " f"dogrusal model {DOGRUSAL / len(XS):.4f}; agin araligi {en_az}-{en_cok} abone" f" -> {sum(en_az <= v <= en_cok for v in (AGAC, DOGRUSAL))}/2 iceride") print(f"ayni egitim cizge uzerinden kossaydi " f"{TUR * (len(XE) // TOPLU_BOY) * DUGUM:,} dugum kurulurdu")
ag 8-8-1, 81 parametre, 40 tur, toplu boy 30, ogrenme adimi 0.3, 400 guncelleme taban cizgisi 0.7579 agin sayisi 0.8095 (fark +0.0516) ikinci kosum 0.7937 (fark +0.0357) on ilklendirmede aralik 0.7857 - 0.8095, genislik 0.0238 (6 abone) karsilastirma cizgileri (756 satirlik egitim kumesiyle): karar agaci 0.7857, dogrusal model 0.8016; agin araligi 198-204 abone -> 2/2 iceride ayni egitim cizge uzerinden kossaydi 2,648,800 dugum kurulurdu
Üç sayı yan yana: taban çizgisi 0,7579, ağın sayısı 0,8095, ikinci koşum 0,7937. Aradaki fark 0,0158, yani dört abone; iki koşum arasındaki bu fark, tabanın üstündeki kazancın (+0,0516) üçte birine yakındır. On ilklendirmede aralık 0,7857 ile 0,8095 arasına yayılıyor, altı abone genişliğinde. Kapasitede, veride, öğrenme adımında ve tur sayısında hiçbir şey değişmeden ağın sayısı bu aralıkta herhangi bir yere düşebilir.
M27/K03’ün karar ağacı sınama kümesinde 198, doğrusal modeli 202 aboneyi doğru ayırdı; ağın on koşumdaki aralığı 198–204 ve ikisi de içeride. Karşılaştırma birebir değildir, o sayılar 756 satırlık eğitim kümesinden geldi; ama yön nettir: ağın tek koşumda ürettiği sayıyla iki eski aileyi geçtiğini söylemek, koşum değişkenliğini bulgu diye okumaktır. Kursun kuralı bu yüzden vardır — aynı kapasitenin iki koşumda iki ayrı sayı verdiği yazılmayan sonuç ölçülmemiş sayılır.
Özet
- Hesap çizgesi bir veri yapısıdır: her düğüm değerini, atalarını ve yerel türevini tutar; geri geçiş çizgeyi tersten gezer ve zincir kuralı yalnız bir kez yazılır.
- Otuz iki satırlık dört işlemli düzenek, seksen bir parametrenin eğimini elle yazılan on sekiz satırlık geri yayılımdan 2,78e-17 farkla veriyor; en büyük eğim 0,3097.
- Otuz iki satır ağın yapısını bilmez, on sekiz satır yalnız bu ağa aittir; bedel otuz örneklik toplu için 6.622 düğüm, örnek başına 220,7.
- Kursun üç sayısı: taban çizgisi 0,7579, ağın sayısı 0,8095, ikinci koşum 0,7937; aradaki fark 0,0158, tabanın üstündeki kazancın üçte birine yakın.
- On ilklendirmenin aralığı 0,7857–0,8095 ve M27/K03’ün karar ağacı (0,7857) ile doğrusal modelinin (0,8016) sayıları bu aralığın içine düşüyor; tek koşumla okunan üstünlük koşum değişkenliğinden ayrılamaz.
Sonraki Adım
Eğim doğru hesaplandı, ama ağa hangi örneklerin hangi sırayla verildiği tek bir satırda geçti: eğitim kümesi her turda karıştırıldı ve otuzarlık topluya bölündü. O satır bir karardır. Sonraki ders veri yükleme hattını ele alır: toplu üretim sırasının sayıyı ne kadar oynattığı, veri artırmanın ne kattığı ve artırmanın hangi durumda ayrılmış kümeye sızıntı ürettiği ölçülür.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.