Ders 16 / 24
Çok Başlı Dikkat ve Dönüştürücüler
Sorgunun çoğaltılmasının ve konum kodlamasının aynı parametre bütçesinde ne kattığının ölçülmesi: 33 parametre sabit tutulup baş sayısı 1, 2 ve 4 yapıldığında ayrılmış küme ortalaması 0,8722, 0,8806 ve 0,8972 oluyor, yani baş sayısının kattığı 0,0250 iken tek bir kurulumun iki koşumu arasındaki fark 0,0500'e çıkıyor. İki başlı ağın ikinci koşumu başları dizinin iki ucuna ayırıyor (ağırlık merkezleri 3,30 ve 8,55, ayrıklık 0,7264) ama birinci koşum ayırmıyor (5,57 ve 6,30) ve doğruluğu düşmüyor. Konum kodlaması çıkarıldığında iki koşum da tam olarak taban çizgisine, 0,6611'e iniyor ve okumalar karıştırıldığında çıktı 0,0000 oynuyor.
İçindekiler
Dikkat katmanı tek bir sorgu taşıdı ve dizinin tamamını tek bir ağırlık dağılımına indirdi. Görev buna elverişliydi: etiket tek bir adımdan okunuyordu ve adımların hangi sırada geldiği hiçbir şeyi değiştirmiyordu. Gerçek dizilerde iki şey birden değişir. Bir karar çoğu zaman dizinin birden çok yerinden okunan bilginin birleşiminden çıkar, ve o bilginin nerede durduğu bilginin kendisi kadar önemlidir.
Bu ders iki eklemeyi ölçer. Birincisi sorgunun çoğaltılmasıdır: aynı iç boyut birden çok başa bölünür, her baş kendi ağırlık dağılımını üretir ve çıktılar birleştirilir. İkincisi konum kodlamasıdır: adımın dizideki yeri, girdinin yanına bir sayı olarak eklenir. Bu ikisi, adım başına bir izdüşüm ve atlamalı bağlantılarla birlikte dönüştürücü mimarinin taşıyıcı parçalarıdır — yinelemesiz, bütün adımlara aynı anda bakan bir yapı. Burada yalnız taşıyıcı iki parça yazılır ve ölçülür.
- MI55. Bu payın dizi kurgusu
mimariler/06’da kuruldu ve kurgudur: 720 dizi, uzunluk 12, tohum 20260218. Aynı diziler aynı tohumla yeniden üretilir. - MI56. Bu dersin sorusu ayrıdır ve sıraya bağlıdır: etiket, yedinci ile on birinci adımın ortalamasının birinci ile beşinci adımın ortalamasını 0,30’dan fazla aşıp aşmadığıdır. Altıncı adım iki bölgenin dışında bırakılır.
- MI57. Taban çizgisi yine en sık sınıftır. Etiket iki bölgenin farkından okunduğu için dizinin genel düzeyi tabanı geçmeye yetmez.
- MI58. Konum kodlaması bir sinüs ve bir kosinüs kanalıdır: adım için ve . Tek frekans ölçeği küçük tutmak için seçilmiştir; gerçek kurulumlar birden çok frekans kullanır.
- MI59. Karşılaştırma eşit parametre bütçesindedir. Toplam iç boyut 4’te sabittir ve baş sayısı arttıkça baş başına boyut küçülür. Parametre sayısı üç kurulumda da aynıdır.
- MI60. Katman ders içinde yazılır ve modeldir. Kitaplık çağrılmaz.
- MI61. Eğitim momentumlu iniştir: 150 tur, öğrenme adımı 0,15, momentum 0,8. Momentum
M27/K05
sinir-agi-temellerikonusunda kuruldu ve burada tekrarlanmaz. - MI62. Her kurulum iki koşumla basılır; koşumlar yalnız ilklendirme tohumunda ayrılır.
- MI63. Sıra sınaması şudur: bir dizinin okumaları kendi aralarında karıştırılır, konum kanalları yerinde bırakılır ve çıktı olasılığının ne kadar oynadığı ölçülür.
Aynı Bütçe, Farklı Baş Sayısı
Önceki dersin dizileri aynen kullanılır, soru değişir. Yeni etiket iki bölgenin ortalaması arasındaki farktan okunduğu için tek bir ağırlıklı ortalamayla üretilmesi zordur: bir dizi ortalama iki bölgeyi ayıramaz.
# ORTAK — MODELDIR. `mimariler/06`'da kurulan KURGU dizi kumesi ayni tohumla yeniden uretilir. import math TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12 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 dizi_kur(n, tohum): D = [] for i in range(n): r = uretec(tohum + i) r() # bolge cekilisi: bu derste kullanilmaz, dizi ayni kalsin diye tuketilir oku = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)] r() D.append({"oku": oku}) return D VERI = dizi_kur(720, TOHUM) ILK, SON = range(1, 6), range(7, 12) for x in VERI: a = sum(x["oku"][t] for t in ILK) / 5 b = sum(x["oku"][t] for t in SON) / 5 x["y"] = 1 if b - a > 0.30 else 0 EGT, SIN = VERI[:200], VERI[540:] oran = sum(x["y"] for x in SIN) / len(SIN) TABAN = max(oran, 1 - oran) print(f"dizi {len(VERI)}, uzunluk {ADIM}, egitim {len(EGT)}, ayrilmis {len(SIN)}") print(f"artis etiketi orani egitim {sum(x['y'] for x in EGT) / len(EGT):.4f}, " f"ayrilmis {oran:.4f}") print(f"taban cizgisi (en sik sinif) {TABAN:.4f}") print(f"ornek dizi {VERI[0]['oku']}")
dizi 720, uzunluk 12, egitim 200, ayrilmis 180 artis etiketi orani egitim 0.3150, ayrilmis 0.3389 taban cizgisi (en sik sinif) 0.6611 ornek dizi [0.0, 0.893, -0.222, -0.542, -0.404, -1.114, 0.234, -1.03, -1.493, 0.534, -1.807, 0.05]
Çok başlı dikkatte her baş kendi anahtar, değer ve sorgu izdüşümüne sahiptir. Toplam iç boyut sabit tutulduğu için baş sayısı iki katına çıktığında baş başına boyut yarıya iner; parametre sayısı değişmez. Karşılaştırmanın anlamı buradadır — kazanç varsa kapasiteden değil, aynı kapasitenin bölünme biçiminden gelir.
DTOP, DIN = 4, 3 def girdi(x, kod=True): K = [[math.sin(math.pi * t / (ADIM - 1)), math.cos(math.pi * t / (ADIM - 1))] for t in range(ADIM)] return [[x["oku"][t]] + (K[t] if kod else [0.0, 0.0]) for t in range(ADIM)] def ilklendir(tohum, H): d = DTOP // H r = uretec(tohum) g = lambda: (r() + r() + r() - 1.5) * 0.9 return {"H": H, "d": d, "ol": 1.0 / math.sqrt(d), "Wk": [[[g() for _ in range(DIN)] for _ in range(d)] for _ in range(H)], "Wv": [[[g() for _ in range(DIN)] for _ in range(d)] for _ in range(H)], "q": [[g() for _ in range(d)] for _ in range(H)], "w": [g() for _ in range(DTOP)], "b": [0.0]} def agirlik(P, X, h): # sorgu ile anahtar izdusumu tek bir yone katlanir: u = q^T Wk d, wk, q = P["d"], P["Wk"][h], P["q"][h] u = [sum(q[i] * wk[i][j] for i in range(d)) for j in range(DIN)] s = [(u[0] * x[0] + u[1] * x[1] + u[2] * x[2]) * P["ol"] for x in X] mx = max(s) e = [math.exp(v - mx) for v in s] z = sum(e) return [v / z for v in e] def bas(P, X, h): a = agirlik(P, X, h) Xa = [sum(a[t] * X[t][j] for t in range(ADIM)) for j in range(DIN)] return a, Xa, [sum(P["Wv"][h][i][j] * Xa[j] for j in range(DIN)) for i in range(P["d"])] def ileri(P, X): d, o = P["d"], P["b"][0] for h in range(P["H"]): c = bas(P, X, h)[2] o += sum(P["w"][h * d + i] * c[i] for i in range(d)) return o def egit(tohum, H, EG, tur=150, adim=0.15, mom=0.8): P = ilklendir(tohum, H) d, ol, n, hiz = P["d"], P["ol"], len(EG), None for _ in range(tur): gWk = [[[0.0] * DIN for _ in range(d)] for _ in range(H)] gWv = [[[0.0] * DIN for _ in range(d)] for _ in range(H)] gq = [[0.0] * d for _ in range(H)] gw, gb = [0.0] * DTOP, [0.0] for X, y in EG: B = [bas(P, X, h) for h in range(H)] o = P["b"][0] + sum(P["w"][h * d + i] * B[h][2][i] for h in range(H) for i in range(d)) df = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y gb[0] += df for h in range(H): a, Xa, c = B[h] dc = [df * P["w"][h * d + i] for i in range(d)] mv = [sum(dc[i] * P["Wv"][h][i][j] for i in range(d)) for j in range(DIN)] da = [mv[0] * x[0] + mv[1] * x[1] + mv[2] * x[2] for x in X] orta = sum(a[t] * da[t] for t in range(ADIM)) S = [0.0, 0.0, 0.0] for t in range(ADIM): ds, x = a[t] * (da[t] - orta) * ol, X[t] S[0] += ds * x[0] S[1] += ds * x[1] S[2] += ds * x[2] for i in range(d): gw[h * d + i] += df * c[i] gq[h][i] += sum(P["Wk"][h][i][j] * S[j] for j in range(DIN)) for j in range(DIN): gWk[h][i][j] += P["q"][h][i] * S[j] gWv[h][i][j] += dc[i] * Xa[j] par = [P["Wk"][h][i] for h in range(H) for i in range(d)] \ + [P["Wv"][h][i] for h in range(H) for i in range(d)] \ + P["q"] + [P["w"], P["b"]] egm = [gWk[h][i] for h in range(H) for i in range(d)] \ + [gWv[h][i] for h in range(H) for i in range(d)] + gq + [gw, gb] if hiz is None: hiz = [[0.0] * len(u) for u in par] for u, v, g in zip(par, egm, hiz): # momentumlu inis for i in range(len(u)): g[i] = mom * g[i] - adim * v[i] / n u[i] += g[i] return P def dogruluk(P, G): return sum((ileri(P, X) > 0) == (y == 1) for X, y in G) / len(G) GK = [(girdi(x), x["y"]) for x in VERI] EG, SG = GK[:200], GK[540:] AG = {} print(f"toplam ic boyut {DTOP}, tur 150, egitim ornegi {len(EG)}, " f"taban cizgisi {TABAN:.4f}") print(f"{'bas':>4}{'bas boyutu':>12}{'parametre':>11}{'kosum 1':>10}{'kosum 2':>10}" f"{'ortalama':>10}{'kosum farki':>13}") for H in (1, 2, 4): AG[H] = [egit(TOHUM + k, H, EG) for k in (1, 2)] a, b = (dogruluk(P, SG) for P in AG[H]) print(f"{H:>4}{DTOP // H:>12}{2 * DTOP * DIN + 2 * DTOP + 1:>11}{a:>10.4f}" f"{b:>10.4f}{(a + b) / 2:>10.4f}{abs(a - b):>13.4f}")
toplam ic boyut 4, tur 150, egitim ornegi 200, taban cizgisi 0.6611 bas bas boyutu parametre kosum 1 kosum 2 ortalama kosum farki 1 4 33 0.8889 0.8556 0.8722 0.0333 2 2 33 0.8778 0.8833 0.8806 0.0056 4 1 33 0.8722 0.9222 0.8972 0.0500
Ortalamalar tek yönde ilerliyor: 0,8722, 0,8806, 0,8972. Baş sayısını birden dörde çıkarmak ayrılmış küme sayısına 0,0250 katıyor ve taban çizgisinin 0,2361 üstüne taşıyor. Sağdaki sütun kazancı bağlama oturtuyor: dört başlı kurulumun iki koşumu arasındaki fark 0,0500, yani baş sayısının kattığının iki katı. Aynı kapasiteyi başlara bölmenin getirdiği fark, o bölmenin kendisini yeniden koşmanın getirdiği farktan küçüktür. Baş sayısı bu ölçekte bir ayar değişkenidir ve tek koşumla seçilirse yanlış seçilir.
Başlar Neye Bakıyor
Baş sayısının niçin bir şey kattığı ağırlıkların nereye düştüğüne bakılarak sorulabilir. Görev iki bölgenin ortalamasını istiyor; başlar bu iki bölgeye ayrılıyorsa yapı görevin biçimini bulmuş demektir. Ölçü iki sayıdır: her başın ağırlık merkezi ve başlar arası ayrıklık — iki dağılım arasındaki farkın yarısı, sıfırdan bire.
def merkez(P, G, h): return sum(sum(t * agirlik(P, X, h)[t] for t in range(ADIM)) for X, _ in G) / len(G) def ayriklik(P, G): H, s = P["H"], 0.0 if H < 2: return 0.0 for X, _ in G: A = [agirlik(P, X, h) for h in range(H)] for i in range(H): for j in range(i + 1, H): s += sum(abs(A[i][t] - A[j][t]) for t in range(ADIM)) / 2 return s / (len(G) * H * (H - 1) / 2) print(f"gorevin istedigi iki bolge: adim {min(ILK)}-{max(ILK)} ve {min(SON)}-{max(SON)}") print(f"{'':18}{'agirlik merkezleri':>34}{'ayriklik':>10}{'ayrilmis':>10}") for H in (1, 2, 4): for k in (0, 1): P = AG[H][k] m = ", ".join(f"{merkez(P, SG, h):.2f}" for h in range(H)) print(f"{H} bas, kosum {k + 1:<5}{m:>34}{ayriklik(P, SG):>10.4f}" f"{dogruluk(P, SG):>10.4f}")
gorevin istedigi iki bolge: adim 1-5 ve 7-11
agirlik merkezleri ayriklik ayrilmis
1 bas, kosum 1 5.51 0.0000 0.8889
1 bas, kosum 2 6.02 0.0000 0.8556
2 bas, kosum 1 5.57, 6.30 0.4096 0.8778
2 bas, kosum 2 3.30, 8.55 0.7264 0.8833
4 bas, kosum 1 5.84, 5.48, 5.79, 5.61 0.4782 0.8722
4 bas, kosum 2 3.24, 5.81, 8.37, 4.59 0.4291 0.9222
İki başlı kurulumun ikinci koşumu tam beklenen ayrımı yapıyor: bir baş 3,30’da, öbürü 8,55’te duruyor ve bu iki nokta görevin istediği iki bölgenin ortasına düşüyor. Ayrıklık 0,7264, yani iki dağılım büyük ölçüde ayrı adımlara bakıyor.
Aynı kurulumun birinci koşumu bunu yapmıyor. Başlar 5,57 ve 6,30’da, ikisi de dizinin ortasında duruyor ve ayrıklık 0,4096’da kalıyor. Buna karşın ayrılmış küme sayısı 0,8778 — ayıran koşumdan yalnız 0,0055 aşağıda. Aynı gözlem dört başlı kurulumda daha da nettir: birinci koşumun dört başı 5,48 ile 5,84 arasında sıkışmışken doğruluğu 0,8722’dir. Yapının “görevin biçimini bulması” mimariden değil koşumdan gelmektedir ve bulmamış bir koşum da yakın bir sayı üretebilmektedir.
Konum Kodlaması Bir İyileştirme Değil, Önkoşuldur
Dikkat bütün adımlara aynı anda bakar ve adımlar arasında hiçbir sıra bağı taşımaz. Bir adımın girdisinde yerine dair bir sayı yoksa, katman için dizi bir çokluk kümesidir: aynı okumaların başka sırayla gelmesi aynı çıktıyı verir. Bu bir başarım kaybı değil, bilginin yokluğudur ve doğrudan sınanabilir.
def okumalari_karistir(X, tohum): r, s = uretec(tohum), list(range(ADIM)) for i in range(ADIM - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] return [[X[s[t]][0], X[t][1], X[t][2]] for t in range(ADIM)] def olasilik(P, X): return 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, ileri(P, X))))) def sira_sinamasi(P, G): e, en = 0.0, 0.0 for i, (X, _y) in enumerate(G): d = abs(olasilik(P, okumalari_karistir(X, TOHUM + 4000 + i)) - olasilik(P, X)) e, en = e + d, max(en, d) return e / len(G), en TUM = [(girdi(x, False), x["y"]) for x in VERI] KOD = [egit(TOHUM + k, 2, TUM[:200]) for k in (1, 2)] print(f"taban cizgisi (en sik sinif) {TABAN:.4f}") print(f"{'':28}{'kosum 1':>9}{'kosum 2':>9}{'ort |degisim|':>15}{'en buyuk':>10}") for ad, M, G in (("konum kodlamasi var", AG[2], SG), ("konum kodlamasi yok", KOD, TUM[540:])): e, en = sira_sinamasi(M[1], G) print(f"{ad:<28}{dogruluk(M[0], G):>9.4f}{dogruluk(M[1], G):>9.4f}" f"{e:>15.4f}{en:>10.4f}")
taban cizgisi (en sik sinif) 0.6611
kosum 1 kosum 2 ort |degisim| en buyuk
konum kodlamasi var 0.8778 0.8833 0.3173 0.9753
konum kodlamasi yok 0.6611 0.6611 0.0000 0.0000
Alt satır iki yerde birden keskindir. Kodlamasız kurulum iki koşumda da tam olarak 0,6611 verir — tabanın kendisi. Ondalık basamaklarda bile fark yoktur, çünkü ağ her diziye aynı sınıfı vermekten başka bir şey öğrenememektedir. Sıra sınaması nedenini söyler: okumalar karıştırıldığında çıktı olasılığı ortalama 0,0000 ve en fazla 0,0000 oynar. Bu bir yuvarlama değildir; katman girdiyi sırasız bir küme olarak gördüğü için çıktı bit düzeyinde aynıdır.
Kodlamalı kurulumda aynı karıştırma çıktıyı ortalama 0,3173, en fazla 0,9753 oynatır. Aradaki fark kodlamanın “yardımcı olması” değil, sıranın ancak kodlamayla ağın erişimine girmesidir. Yinelemeli bir ağda sıra yapının kendisinden gelir ve ayrıca kodlanması gerekmez; dikkat bu güvenceyi vermediği için sırayı girdiye yazmak bir seçim değil, bir zorunluluktur.
Özet
- Aynı iç boyut farklı sayıda başa bölündüğünde parametre sayısı 33’te sabit kalır; ayrılmış küme ortalaması 0,8722, 0,8806 ve 0,8972 olur ve baş sayısının kattığı 0,0250’dir.
- Dört başlı kurulumun iki koşumu arasındaki fark 0,0500’dür, yani baş sayısının kattığının iki katı; baş sayısı tek koşumla seçilirse yanlış seçilir.
- Başlar görevin istediği iki bölgeye yalnız bazı koşumlarda ayrılır: iki başlı kurulumun ikinci koşumu 3,30 ve 8,55 merkezleriyle ayrıklık 0,7264 verir, birinci koşumu 5,57 ve 6,30 ile 0,4096’da kalır ve doğruluğu yalnız 0,0055 düşüktür.
- Konum kodlaması olmadan iki koşum da tam olarak taban çizgisine, 0,6611’e iner; okumalar karıştırıldığında çıktı 0,0000 oynar, çünkü katman diziyi sırasız bir küme olarak görür.
- Konum kodlamalı kurulumda aynı karıştırma çıktıyı ortalama 0,3173 ve en fazla 0,9753 oynatır.
Sonraki Adım
Bu iki derste girdinin her adımı hazır bir sayıydı: okuma bir kayan noktalı değer, işaret bir sıfır ya da bir, konum bir sinüs. Dizilerin çoğu böyle gelmez. Bir sayaç tipi, bir tarife basamağı, bir bölge kodu ya da bir olay etiketi ayrık bir simgedir ve doğal bir sayısal değeri yoktur. M27/K02’nin kodlama dersleri bu simgeleri bir-sıcak sütunlara çevirmişti; bu, kategori sayısı büyüdükçe girdi boyutunu da aynı oranda büyütür ve simgeler arasındaki hiçbir yakınlığı taşımaz. Sonraki ders ayrık girdiyi öğrenilen bir vektöre eşleyen gömme katmanını kurar, parametre sayısını bir-sıcak kodlamaya karşı sayar ve öğrenilen bu temsili M27/K04’ün öğrenilmeyen izdüşümüyle aynı ölçüde karşılaştırır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.