Ders 13 / 24
Yinelemeli Ağlar
Gizli durumun dizi uzadıkça ne kadar bilgi taşıdığının sayılması: aynı dizinin yalnız ilk adımı değiştirildiğinde son gizli durumdaki fark uzunluk 2'de 0,92844 iken uzunluk 12'de 0,00913'e iniyor, adım başına çarpan 0,62. İlk adımdaki işaretin son durumdan geri okunma doğruluğu 1,0000'den 0,5300'e, yani rastlantı düzeyine düşüyor. Aynı 61 parametreli ağ uzunluk 2'de taban çizgisini 0,2300 ve 0,2800, uzunluk 8'de 0,2100 ve 0,1700, uzunluk 10'da 0,1850 ve 0,1850 geçerken uzunluk 12'de yalnız 0,0250 ve 0,0050 geçiyor: bağımlılık on adımda taşınıyor, on iki adımda taşınmıyor.
İçindekiler
Üç derste girdi bir ızgaraydı ve ağa bir kerede verildi. Bir abonenin sayaç okumaları ise bir sıra oluşturur: okumalar dönem dönem gelir, sıradaki yer anlamlıdır ve abone başına okuma sayısı aynı olmak zorunda değildir. Sabit boyda bir pencereden bakan bir çekirdek bu veriye uymaz — pencere dışında kalan geçmiş görünmez.
Yinelemeli ağ diziyi baştan sona adım adım okur ve o ana kadar gördüklerini bir gizli durumda biriktirir. Her adımda aynı ağırlıklar kullanılır; bu, evrişimin uzamda yaptığı ağırlık paylaşımının zaman eksenindeki karşılığıdır ve parametre sayısını dizi uzunluğundan bağımsız kılar. Bu dersin ölçüsü şudur: dizinin başındaki bir bilgi, dizi uzadıkça gizli durumda ne kadar kalıyor.
- MI28. Okuma dizisi kurgudur. Her abone için on iki dönemlik sayaç okuması üretilir; tohum 20260218. Uzunluk 12’yi aşmaz ve dizi bu payın ilk üç dersindeki ızgaradan bağımsız, ayrı bir kurgudur.
- MI29. İşaret dizinin başındadır. Abonelerin yaklaşık yarısında ilk dönemin okuması sıfırdır — sayaç değişimi. Sıfır okuma yalnız ilk dönemde görülür, böylece işaret tektir ve yeri bellidir.
- MI30. Etiket iki koşulun birlikte sağlanmasıdır: ilk dönem sıfır okuma ve son dönemin okuması tarife basamağı 25 m³’ün üstünde. Ağın son adımda karar verebilmesi için dizinin başındaki bilgiyi sonuna kadar taşıması gerekir.
- MI31. Her adımın girdisi iki sayıdır: okumanın 40 m³’e bölünmüş değeri ve sıfır okuma göstergesi.
- MI32. Etiket dizi uzunluğuna bağlıdır, çünkü “son dönem” uzunlukla değişir. Bu yüzden her uzunluk için taban çizgisi ayrıca hesaplanır ve karşılaştırmalar tabana göre farkla yapılır.
- MI33. Ağ sabittir: 6 birimlik gizli durum, hiperbolik tanjant, çıkış son gizli durumdan okunan sigmoit. Parametre sayısı 61’dir ve dizi uzunluğu ne olursa olsun değişmez.
- MI34. Bilgi ölçümü eğitimsiz ağda yapılır. Aynı dizinin yalnız ilk adımı değiştirilir ve iki son gizli durumun farkı ölçülür. Sorulan şey yapının ne taşıyabildiğidir, eğitimin ne başardığı değil.
- MI35. Kütüphane çağrılmaz; ileri geçiş, zaman içinde geri yayılım ve eğitim döngüsü ders içinde yazılır ve modeldir.
- MI36. Her ağ iki kez koşulur; ikinci koşumda yalnız başlangıç değerleri değişir.
Dizi ve Gizli Durum
# dizi.py — MODELDIR. Okuma dizisi KURGUDUR: her abone icin on iki donemlik # sayac okumasi uretilir. Ilk donemin okumasi bir kismi abonede SIFIRDIR # (sayac degisimi); bu, dizinin basina konan ISARETTIR. Etiket, isaretin # varligi ile son donemin tarife basamagini asmasinin BIRLIKTE saglanmasidir. import math TOHUM, M32 = 20260218, 0xFFFFFFFF UZUN, TARIFE, OLCEK, GIZLI = 12, 25.0, 40.0, 6 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 okuma_dizisi(no): r = uretec(TOHUM + 400000 + no) taban = 23.0 + 8.0 * r() d = [math.floor(taban * math.exp((r() + r() + r() - 1.5) * 0.62) * 100 + 0.5) / 100 for _ in range(UZUN)] if r() < 0.5: d[0] = 0.0 # isaret return d def kes(d, T): """Ilk T donem; girdi adim basina iki sayi, etiket iki kosulun birlikte.""" x = [[v / OLCEK, 1.0 if v == 0.0 else 0.0] for v in d[:T]] return x, 1 if (d[0] == 0.0 and d[T - 1] > TARIFE) else 0 def karistir(n, tohum): r, s = uretec(tohum), list(range(n)) for i in range(n - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] return s HAM = [okuma_dizisi(i) for i in range(500)] DZ = [HAM[i] for i in karistir(500, TOHUM + 95000)] EGT, SIN = DZ[:200], DZ[300:] def taban_cizgisi(T): p = sum(kes(d, T)[1] for d in SIN) return max(p, len(SIN) - p) / len(SIN) def kur(tohum, H=GIZLI): r = uretec(tohum) a1, a2 = (1 / 2) ** 0.5, (1 / H) ** 0.5 return [[[(r() * 2 - 1) * a1 for _ in range(2)] for _ in range(H)], [[(r() * 2 - 1) * a2 for _ in range(H)] for _ in range(H)], [0.0] * H, [(r() * 2 - 1) * a2 for _ in range(H)], [0.0]] def ileri(P, x): """h_t = tanh(Wx x_t + Wh h_(t-1) + b); cikis son gizli durumdan okunur.""" Wx, Wh, b, v, c = P H = len(b) h, izler = [0.0] * H, [] for t in range(len(x)): h = [math.tanh(b[k] + Wx[k][0] * x[t][0] + Wx[k][1] * x[t][1] + sum(Wh[k][j] * h[j] for j in range(H))) for k in range(H)] izler.append(h) z = c[0] + sum(v[k] * h[k] for k in range(H)) return 1 / (1 + math.exp(-max(-30, min(30, z)))), izler ornek = next(d for d in DZ if d[0] == 0.0 and d[UZUN - 1] > TARIFE) print("ornek dizi (m3):", " ".join(f"{v:.2f}" for v in ornek)) print(f"isaret orani {sum(1 for d in DZ if d[0] == 0.0) / len(DZ):.3f}; " f"bolme {len(EGT)}/100/{len(SIN)}; gizli durum {GIZLI} birim; " f"parametre {GIZLI * 2 + GIZLI * GIZLI + GIZLI + GIZLI + 1}") print(f"{'T':>3}{'pozitif':>9}{'taban cizgisi':>15}") for T in (2, 4, 6, 8, 10, 12): print(f"{T:>3}{sum(kes(d, T)[1] for d in SIN):>9}{taban_cizgisi(T):>15.4f}")
ornek dizi (m3): 0.00 26.80 37.98 20.95 35.18 49.78 24.15 22.38 47.64 35.14 26.95 25.18 isaret orani 0.514; bolme 200/100/200; gizli durum 6 birim; parametre 61 T pozitif taban cizgisi 2 56 0.7200 4 56 0.7200 6 63 0.6850 8 51 0.7450 10 60 0.7000 12 58 0.7100
Örnek dizide ilk okuma sıfırdır ve son okuma 25,18 m³ ile tarife basamağının üstündedir; etiket 1’dir. Aradaki on dönem karar için hiçbir şey söylemez — ağın taşıması gereken tek bilgi baştaki sıfırdır.
Parametre sayısı 61’dir ve alt tablodaki altı uzunluğun hepsinde aynıdır. Aynı ağırlıklar her adımda yeniden kullanılır; bir dizi ne kadar uzarsa uzasın yeni ağırlık gerekmez. Bu, evrişimin uzamda yaptığının zaman eksenindeki karşılığıdır ve tam bağlı bir katmanın yapamayacağı şeydir: tam bağlı katman girdinin uzunluğunu baştan bilmek zorundadır.
Taban çizgileri uzunluğa göre 0,6850 ile 0,7450 arasında geziniyor, çünkü etiketin ikinci koşulu “son dönem” ile tanımlıdır ve son dönem uzunlukla değişir. Bu yüzden uzunluklar arasındaki karşılaştırma ham doğrulukla değil, tabana göre farkla yapılır.
Gizli Durum Neyi Taşıyor
# iz.py — gizli durumun tasidigi bilgi. Ayni dizinin YALNIZ ilk adimi # degistirilir (isaretli / isaretsiz) ve son gizli durumlarin farki olculur. # Olcum EGITIMSIZ agda yapilir: sorulan sey yapinin ne tasiyabildigidir. def ciftler(d, T): x, _ = kes(d, T) a = [s[:] for s in x] a[0] = [0.0, 1.0] b = [s[:] for s in x] b[0] = [d[1] / OLCEK, 0.0] return a, b def geri_okuma(P, T): """En yakin merkez okuyucusu: h_T'den isaret geri okunabiliyor mu.""" hs = [(ileri(P, kes(d, T)[0])[1][-1], 1 if d[0] == 0.0 else 0) for d in DZ] egt, sin = hs[:200], hs[300:] mer, say = [[0.0] * GIZLI, [0.0] * GIZLI], [0, 0] for h, s in egt: say[s] += 1 for k in range(GIZLI): mer[s][k] += h[k] for s in (0, 1): mer[s] = [u / say[s] for u in mer[s]] ort = [(mer[0][k] * say[0] + mer[1][k] * say[1]) / len(egt) for k in range(GIZLI)] sd = [max(1e-9, (sum((h[k] - ort[k]) ** 2 for h, _ in egt) / len(egt)) ** 0.5) for k in range(GIZLI)] def uzak(h, s): return sum(((h[k] - mer[s][k]) / sd[k]) ** 2 for k in range(GIZLI)) return sum(1 for h, s in sin if (uzak(h, 1) < uzak(h, 0)) == (s == 1)) / len(sin) print(f"{'T':>3}{'h farki k1':>12}{'h farki k2':>12}{'adim basina k1':>16}" f"{'geri okuma k1':>15}{'geri okuma k2':>15}") onceki = [None, None] for T in (2, 4, 6, 8, 10, 12): sat = [] for P in (kur(TOHUM + 11), kur(TOHUM + 12)): f = 0.0 for d in DZ: a, b = ciftler(d, T) ia, ib = ileri(P, a)[1][-1], ileri(P, b)[1][-1] f += sum(abs(ia[k] - ib[k]) for k in range(GIZLI)) sat.append((f / len(DZ), geri_okuma(P, T))) oran = "-" if onceki[0] is None else f"{(sat[0][0] / onceki[0]) ** 0.5:.3f}" onceki[0] = sat[0][0] print(f"{T:>3}{sat[0][0]:>12.5f}{sat[1][0]:>12.5f}{oran:>16}" f"{sat[0][1]:>15.4f}{sat[1][1]:>15.4f}")
T h farki k1 h farki k2 adim basina k1 geri okuma k1 geri okuma k2 2 0.92844 1.39970 - 1.0000 0.9750 4 0.34417 0.24972 0.609 0.7850 0.9350 6 0.15338 0.06435 0.668 0.8000 0.6350 8 0.05986 0.01560 0.625 0.5900 0.5500 10 0.02362 0.00333 0.628 0.4600 0.4600 12 0.00913 0.00067 0.622 0.5300 0.4750
İlk sütun dersin sayısıdır. Aynı dizinin yalnız ilk adımı değiştirildiğinde son gizli durumda kalan fark uzunluk 2’de 0,92844, uzunluk 12’de 0,00913’tür — yüzde birinden az. Dördüncü sütun küçülmenin biçimini veriyor: adım başına çarpan 0,609 ile 0,668 arasında, yani sabit bir çarpanla üstel bir azalma. Gizli durum bilgiyi unutmaya karar vermiyor; her adımda aynı dizeyle çarpılıyor ve çarpanın büyüklüğü birden küçük olduğu için iz kendiliğinden siliniyor.
İkinci koşum aynı biçimi farklı bir hızla gösteriyor: uzunluk 12’de fark 0,00067, birinci koşumun on dörtte biri. Yalnız başlangıç değerleri değişti; unutma hızı bir mimari sabiti değil, ilklendirmenin sonucudur.
Son iki sütun bunun ne anlama geldiğini yazıyor. Uzunluk 2’de işaret son gizli durumdan 1,0000 doğrulukla geri okunuyor. Uzunluk 8’de 0,5900’e, uzunluk 10’da 0,4600’e iniyor — işaret oranı 0,514 olduğuna göre bu rastlantı düzeyidir. Uzunluk 12’deki 0,5300 bir toparlanma değil, aynı düzeydeki ölçüm oynamasıdır. Bilgi gizli durumda yoktur; hiçbir okuyucu onu geri getiremez.
Ne Kadar Geriye Taşınıyor
# egit.py — MODELDIR: zaman icinde geri yayilim elle yazilir. Ayni ag, ayni # tur butcesi, degisen tek sey dizi uzunlugudur. def egit(P, veri, tur, gadim, tohum): Wx, Wh, b, v, c = P H, r, n = len(b), uretec(tohum), len(veri) for _ in range(tur): s = list(range(n)) for i in range(n - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] for idx in s: x, y = veri[idx] p, izler = ileri(P, x) d = p - y dh = [d * v[k] for k in range(H)] for k in range(H): v[k] -= gadim * d * izler[-1][k] c[0] -= gadim * d for t in range(len(x) - 1, -1, -1): onceki = izler[t - 1] if t > 0 else [0.0] * H yeni = [0.0] * H for k in range(H): g = dh[k] * (1 - izler[t][k] ** 2) b[k] -= gadim * g Wx[k][0] -= gadim * g * x[t][0] Wx[k][1] -= gadim * g * x[t][1] for j in range(H): yeni[j] += g * Wh[k][j] Wh[k][j] -= gadim * g * onceki[j] dh = yeni return P def dogruluk(P, veri): return sum(1 for x, y in veri if (ileri(P, x)[0] >= 0.5) == (y == 1)) / len(veri) print(f"{'T':>3}{'taban':>8}{'kosum 1':>9}{'kosum 2':>9}{'fark 1':>9}{'fark 2':>9}" f"{'kosum araligi':>15}") for T in (2, 4, 6, 8, 10, 12): eg = [kes(d, T) for d in EGT] sn = [kes(d, T) for d in SIN] tb, s = taban_cizgisi(T), [] for tohum in (TOHUM + 11, TOHUM + 12): P = kur(tohum) egit(P, eg, 30, 0.05, tohum + 500) s.append(dogruluk(P, sn)) print(f"{T:>3}{tb:>8.4f}{s[0]:>9.4f}{s[1]:>9.4f}{s[0] - tb:>+9.4f}" f"{s[1] - tb:>+9.4f}{abs(s[0] - s[1]):>15.4f}")
T taban kosum 1 kosum 2 fark 1 fark 2 kosum araligi 2 0.7200 0.9500 1.0000 +0.2300 +0.2800 0.0500 4 0.7200 0.9550 0.9550 +0.2350 +0.2350 0.0000 6 0.6850 0.9350 0.9550 +0.2500 +0.2700 0.0200 8 0.7450 0.9550 0.9150 +0.2100 +0.1700 0.0400 10 0.7000 0.8850 0.8850 +0.1850 +0.1850 0.0000 12 0.7100 0.7350 0.7150 +0.0250 +0.0050 0.0200
Eğitim, ölçümün söylediğini doğruluyor ama tam olarak aynı yerde değil. Uzunluk 2’den 10’a kadar ağ taban çizgisini 0,1700 ile 0,2700 arasında geçiyor. Uzunluk 12’de fark 0,0250 ve 0,0050’ye düşüyor: ağ artık taban çizgisiyle aynı şeyi söylüyor, yani baştaki işareti hiç kullanmıyor ve yalnız son dönemin okumasına bakan bir kurala dönüşüyor.
Eğitimsiz ölçüm işaretin uzunluk 10’da zaten geri okunamadığını söylemişti; eğitilen ağ ise uzunluk 10’da hâlâ 0,1850 fark üretiyor. Çelişki değildir: eğitim, ağırlıkları başlangıç değerlerinden uzaklaştırır ve yinelemeli dizeyi izin verdiği kadar bilgi taşıyacak biçimde ayarlar. Kazanılan iki adımdır. On ikide o iki adım da yetmez, çünkü sorun ağırlıkların ayarlanmasıyla çözülecek türden değildir: taşıma çarpımla yapılır ve çarpanı biraz büyütmek uzun dizide patlamaya, biraz küçültmek sönmeye götürür.
Koşum aralığı sütunu tabloya kendi uyarısını yazıyor. Uzunluk 8’de iki koşum 0,0400 ayrılıyor; bu, uzunluk 8 ile uzunluk 10 arasındaki farkın (0,0250) üstündedir. Uzunluğun kattığı fark ile başlangıç değerlerinin kattığı fark aynı büyüklük sırasındadır ve tek koşumla ölçülen bir “kaç adıma kadar çalışıyor” yanıtı bu yüzden güvenilir değildir.
Özet
- Okuma dizisi kurgudur: on iki dönemlik okuma, işaret olarak ilk dönemin sıfır okuması, etiket işaret ile son dönemin tarife basamağını aşmasının birlikte sağlanması.
- Yinelemeli ağ her adımda aynı ağırlıkları kullanır; parametre sayısı 61’dir ve dizi uzunluğundan bağımsızdır.
- İlk adımdaki işaretin son gizli durumda bıraktığı fark uzunluk 2’de 0,92844, uzunluk 12’de 0,00913’tür; adım başına çarpan 0,609 ile 0,668 arasında sabittir.
- İşaretin son durumdan geri okunma doğruluğu 1,0000’den uzunluk 10’da 0,4600’e, yani rastlantı düzeyine iner; ikinci koşumda unutma daha da hızlıdır (uzunluk 12’de fark 0,00067).
- Eğitilen ağ taban çizgisini uzunluk 10’a kadar 0,1700–0,2700 geçer, uzunluk 12’de yalnız 0,0250 ve 0,0050 geçer.
- Uzunluk 8’deki koşum aralığı 0,0400, uzunluk 8 ile 10 arasındaki farktan büyüktür; “kaç adıma kadar” sorusu tek koşumla yanıtlanamaz.
Sonraki Adım
Gizli durum bilgiyi tutmayı seçmiyor; her adımda aynı dizeyle çarpılıyor ve çarpanın büyüklüğü neyin kalacağını belirliyor. Aynı çarpan hem yeni okumayı hem de baştaki işareti eşit biçimde etkiliyor, oysa bu iki bilginin ömrü aynı olmamalı: okuma bir adım sonra gereksizdir, işaret dizinin sonuna kadar gereklidir. Sonraki ders duruma iki karar ekler — neyin silineceği ve neyin yazılacağı — ve bu kararları girdiye bakarak veren birimler kurar. Ölçü aynı kalır ve doğrudan karşılaştırılır: yalın yinelemeli ağ ile kapı birimli ağ aynı görevde, aynı uzunluklarda, her biri iki koşumla yan yana konur ve bağımlılığın kaç adım geriye taşınabildiği sayılır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.