İçeriğe geç
academia.sh

Ders 14 / 24

Kapı Birimleri

Uzun bağımlılığın kaç adım geriye taşınabildiğinin sayılması: eğitimsiz ağda ilk adımdaki işaretin son gizli durumda kalan payı yalın 6 birimli ağda yüzde 0,98 ve yüzde 0,05, 9 birimli yalın ağda yüzde 0,71 ve yüzde 0,05 iken kapı birimli ağda yüzde 9,34 ve yüzde 5,63. Aynı tur bütçesinde uzunluk 8'e kadar üç yapı da taban çizgisini 0,1700–0,2100 geçiyor; uzunluk 12'de 61 parametreli yalın ağ 0,0250 ve 0,0050'ye düşerken 115 parametreli kapı birimli ağ 0,2650 ve 0,2050, 118 parametreli geniş yalın ağ 0,2700 ve 0,1700 veriyor. Kapı yapısının eşit bütçeli yalın ağa üstünlüğü on iki adımda ölçülemiyor, çünkü geniş yalın ağın iki koşumu arasındaki 0,1000'lik fark iki yapı arasındaki farktan büyük.

İçindekiler

Önceki dersin gizli durumu bilgiyi tutmayı seçmiyordu. Her adımda aynı dizeyle çarpılıyor, çarpanın büyüklüğü neyin kalacağını belirliyordu ve ölçülen çarpan adım başına 0,62 idi. Aynı çarpan hem yeni okumaya hem baştaki işarete uygulanıyordu, oysa bu iki bilginin ömrü aynı olmamalıdır: okuma bir adım sonra gereksizdir, işaret dizinin sonuna kadar gereklidir.

Kapı birimi duruma iki ayrı hesap ekler: ne kadarının tutulacağı ve yerine ne yazılacağı. İkisi de o adımın girdisine ve o ana kadarki duruma bakarak hesaplanır, yani birim her adımda ayrı bir karar verir. Bu dersin ölçüsü şudur: bu karar, bağımlılığı kaç adım geriye taşıyor — ve kazanç gerçekten kapıdan mı geliyor.

  • MI37. Küme ve bölme değişmez. Önceki dersin kurgu okuma dizisi aynı tohumla üretilir: on iki dönem, ilk dönemin sıfır okuması işaret, etiket işaret ile son dönemin tarife basamağını aşmasının birlikte sağlanması. Bölme 200/100/200, taban çizgisi her uzunluk için ayrı.
  • MI38. Kapı birimi iki bloktan kurulur. Tutma kapısı utu_t sigmoit çıkışlıdır ve her birim için 0 ile 1 arasında bir sayı verir. Aday değer ata_t hiperbolik tanjant çıkışlıdır. Yeni durum ikisinin karışımıdır: ht=utht1+(1ut)ath_t = u_t h_{t-1} + (1 - u_t) a_t.
  • MI39. Kapının açtığı yol çarpımsal değil seçimseldir. utu_t bire yakınsa eski durum neredeyse olduğu gibi geçer; sıfıra yakınsa aday değer yazılır. Yalın birimde böyle bir seçenek yoktur, her adım aynı dönüşümü uygular.
  • MI40. Tutma kapısının yanması pozitif ilklendirilir (değer 1). Kapı başlangıçta açıktır ve eğitim onu kapatmayı öğrenir; ters yönde ilklendirme, öğrenmenin başlaması için önce kapının açılmasını beklemeyi gerektirir.
  • MI41. Parametre sayısı karşılaştırılır. Kapı birimi iki blok taşıdığı için aynı gizli birim sayısında yalın birimden yaklaşık iki kat fazla parametre tutar. Bu yüzden eşit bütçeli bir yalın ağ da tabloya konur: 9 birimli yalın ağ, 6 birimli kapı birimli ağla yaklaşık aynı parametreyi taşır.
  • MI42. Ölçü iki katmanlıdır. Birincisi eğitimsiz ağda işaretin son gizli durumda kalan payıdır — yapının ne taşıyabildiği. İkincisi eğitilen ağın taban çizgisine göre farkıdır — ne taşıdığı.
  • MI43. Üç yapı aynı bütçeyle eğitilir: 30 tur, öğrenme adımı 0,05, aynı bölme, aynı sıra üreteci. Yalın 6 birimli ağın sayıları önceki dersle birebir aynıdır.
  • MI44. Kütüphane çağrılmaz; kapı birimi, zaman içinde geri yayılım ve eğitim döngüsü ders içinde yazılır ve modeldir. Yapı adıyla anılır, kısaltma kullanılmaz.
  • MI45. Her ağ iki kez koşulur; ikinci koşumda yalnız başlangıç değerleri değişir.

Kapı Birimi

# kapi.py — MODELDIR. 04'un KURGU okuma dizisi ayni tohumla uretilir.
# Yalin: h_t = tanh(...). Kapili: h_t = u_t * h_(t-1) + (1 - u_t) * a_t.
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
    return d


def kes(d, T):
    return ([[v / OLCEK, 1.0 if v == 0.0 else 0.0] for v in d[:T]],
            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


DZ = [okuma_dizisi(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 sig(z):
    return 1 / (1 + math.exp(-max(-30, min(30, z))))


def kur(tohum, H=GIZLI):
    r = uretec(tohum)
    return [[[(r() * 2 - 1) * (1 / 2) ** 0.5 for _ in range(2)] for _ in range(H)],
            [[(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)] for _ in range(H)],
            [0.0] * H, [(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)], [0.0]]


def ileri(P, x):
    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)
    return sig(c[0] + sum(v[k] * h[k] for k in range(H))), izler


def kur_kapi(tohum, H=GIZLI, kapi_yanma=1.0):
    r = uretec(tohum)

    def blok(b0):
        return [[[(r() * 2 - 1) * (1 / 2) ** 0.5 for _ in range(2)] for _ in range(H)],
                [[(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)] for _ in range(H)],
                [b0] * H]
    return [blok(kapi_yanma), blok(0.0),
            [(r() * 2 - 1) * (1 / H) ** 0.5 for _ in range(H)], [0.0], H]


def ileri_kapi(P, x):
    U, A, v, c, H = P
    h, izler = [0.0] * H, []
    for t in range(len(x)):
        u = [sig(U[2][k] + U[0][k][0] * x[t][0] + U[0][k][1] * x[t][1]
                 + sum(U[1][k][j] * h[j] for j in range(H))) for k in range(H)]
        a = [math.tanh(A[2][k] + A[0][k][0] * x[t][0] + A[0][k][1] * x[t][1]
                       + sum(A[1][k][j] * h[j] for j in range(H))) for k in range(H)]
        yeni = [u[k] * h[k] + (1 - u[k]) * a[k] for k in range(H)]
        izler.append((h, u, a, yeni))
        h = yeni
    return sig(c[0] + sum(v[k] * h[k] for k in range(H))), izler


def par_yalin(H):
    return 2 * H + H * H + H + H + 1


def par_kapi(H):
    return 2 * (2 * H + H * H + H) + H + 1


print(f"{'yapi':<22}{'gizli birim':>12}{'parametre':>11}")
for ad, H, f in (("yalin yinelemeli", GIZLI, par_yalin), ("yalin yinelemeli", 9, par_yalin),
                 ("kapi birimli", GIZLI, par_kapi)):
    print(f"{ad:<22}{H:>12}{f(H):>11}")
print(f"\n{'T':>3}{'taban cizgisi':>15}")
for T in (2, 4, 8, 12):
    print(f"{T:>3}{taban_cizgisi(T):>15.4f}")
yapi                   gizli birim  parametre
yalin yinelemeli                 6         61
yalin yinelemeli                 9        118
kapi birimli                     6        115

  T  taban cizgisi
  2         0.7200
  4         0.7200
  8         0.7450
 12         0.7100

Kapı biriminin karışım bağıntısı tek satırdır ve önemli olan bu satırın biçimidir: eski durum o adımın girdisinden hesaplanan bir katsayıyla çarpılır, üstüne bir aday eklenir. Yalın birimde kalan payı ağırlıkların büyüklüğü belirlerdi ve bütün adımlar için aynıydı.

Parametre tablosu karşılaştırmanın kuralını koyuyor. Aynı 6 birimle kapı birimli ağ 115, yalın ağ 61 parametre tutar; bu ikisini yan yana koymak kapıya ait olmayan bir farkı kapıya yazmak olurdu. Bu yüzden 9 birimli, 118 parametreli bir yalın ağ da tabloya konur.

İşaretin İzi Üç Yapıda

# iz.py — 04'un olcusu uc yapida, EGITIMSIZ agda yinelenir: dizinin yalniz
# ilk adimi degistirilir, son gizli durumdaki fark olculur.
def ciftler(d, T):
    x = kes(d, T)[0]
    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 iz(P, T, kapili):
    f = 0.0
    for d in DZ:
        a, b = ciftler(d, T)
        if kapili:
            ia, ib = ileri_kapi(P, a)[1][-1][3], ileri_kapi(P, b)[1][-1][3]
        else:
            ia, ib = ileri(P, a)[1][-1], ileri(P, b)[1][-1]
        f += sum(abs(ia[k] - ib[k]) for k in range(len(ia)))
    return f / len(DZ)


YAPI = [("yalin 6", lambda t: kur(t, 6), False),
        ("yalin 9", lambda t: kur(t, 9), False),
        ("kapi 6", lambda t: kur_kapi(t, 6), True)]
print(f"{'T':>3}" + "".join(f"{ad + ' k' + str(k + 1):>12}"
                            for ad, _, _ in YAPI for k in range(2)))
ilk = {}
for T in (2, 4, 8, 12):
    sat = []
    for ad, f, kapili in YAPI:
        for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
            u = iz(f(tohum), T, kapili)
            sat.append(u)
            if T == 2:
                ilk[(ad, k)] = u
    print(f"{T:>3}" + "".join(f"{u:>12.5f}" for u in sat))
print("uzunluk 2'deki ize gore uzunluk 12'de kalan pay:")
for i, (ad, f, kapili) in enumerate(YAPI):
    for k, tohum in enumerate((TOHUM + 11, TOHUM + 12)):
        print(f"  {ad} k{k + 1}: {iz(f(tohum), 12, kapili) / ilk[(ad, k)]:.4%}")
  T  yalin 6 k1  yalin 6 k2  yalin 9 k1  yalin 9 k2   kapi 6 k1   kapi 6 k2
  2     0.92844     1.39970     2.23946     1.75462     0.32959     0.46329
  4     0.34417     0.24972     0.65803     0.40122     0.17443     0.22063
  8     0.05986     0.01560     0.10734     0.01796     0.07712     0.06693
 12     0.00913     0.00067     0.01600     0.00083     0.03077     0.02610
uzunluk 2'deki ize gore uzunluk 12'de kalan pay:
  yalin 6 k1: 0.9837%
  yalin 6 k2: 0.0478%
  yalin 9 k1: 0.7143%
  yalin 9 k2: 0.0473%
  kapi 6 k1: 9.3350%
  kapi 6 k2: 5.6329%

Ham sayılar yanıltıcıdır, oran satırları düzeltir. Kapı birimli ağ uzunluk 2’de yalın ağdan daha az iz taşıyor (0,32959 ile 0,92844), çünkü tutma kapısı yeni bilgiyi de yavaşlatır. Ölçülecek şey başlangıçtaki iz değil, on adım sonra kalan paydır.

O pay yalın 6 birimli ağda yüzde 0,98 ve yüzde 0,05; kapı birimli ağda yüzde 9,34 ve yüzde 5,63. Kapı, işaretin kalan payını on ila yüz kat büyütüyor.

Ortadaki iki sütun kapının ne olmadığını yazıyor. Yalın ağı 6 birimden 9’a genişletmek kalan payı yüzde 0,98’den 0,71’e düşürüyor: unutma hızı birim sayısının değil, her adımda uygulanan çarpımın sonucudur. Taşıma kapasitesini değiştiren tek şey karışım bağıntısının biçimidir.

Kaç Adım Geriye

# egit.py — MODELDIR: uc yapi ayni veride, 30 tur, ogrenme adimi 0,05.
# Zaman icinde geri yayilim elle yazilir.
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, yeni = (izler[t - 1] if t > 0 else [0.0] * H), [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 egit_kapi(P, veri, tur, gadim, tohum):
    U, A, v, c, H = P
    r, n = 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_kapi(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][3][k]
            c[0] -= gadim * d
            for t in range(len(x) - 1, -1, -1):
                onceki, u, a, _ = izler[t]
                yeni = [0.0] * H
                for k in range(H):
                    du = dh[k] * (onceki[k] - a[k]) * u[k] * (1 - u[k])
                    da = dh[k] * (1 - u[k]) * (1 - a[k] ** 2)
                    U[2][k] -= gadim * du
                    A[2][k] -= gadim * da
                    for i2 in (0, 1):
                        U[0][k][i2] -= gadim * du * x[t][i2]
                        A[0][k][i2] -= gadim * da * x[t][i2]
                    yeni[k] += u[k] * dh[k]
                    for j in range(H):
                        yeni[j] += du * U[1][k][j] + da * A[1][k][j]
                        U[1][k][j] -= gadim * du * onceki[j]
                        A[1][k][j] -= gadim * da * onceki[j]
                dh = yeni
    return P


def dogruluk(P, veri, kapili):
    f = ileri_kapi if kapili else ileri
    return sum(1 for x, y in veri if (f(P, x)[0] >= 0.5) == (y == 1)) / len(veri)


print(f"{'T':>3}{'taban':>8}" + "".join(f"{ad + ' k' + str(k + 1):>12}"
                                        for ad, _, _ in YAPI for k in range(2)))
for T in (2, 4, 8, 12):
    eg = [kes(d, T) for d in EGT]
    sn = [kes(d, T) for d in SIN]
    tb, sat = taban_cizgisi(T), []
    for ad, kurucu, kapili in YAPI:
        for tohum in (TOHUM + 11, TOHUM + 12):
            P = kurucu(tohum)
            (egit_kapi if kapili else egit)(P, eg, 30, 0.05, tohum + 500)
            sat.append(dogruluk(P, sn, kapili) - tb)
    print(f"{T:>3}{tb:>8.4f}" + "".join(f"{u:>+12.4f}" for u in sat))
  T   taban  yalin 6 k1  yalin 6 k2  yalin 9 k1  yalin 9 k2   kapi 6 k1   kapi 6 k2
  2  0.7200     +0.2300     +0.2800     +0.2350     +0.2800     +0.2250     +0.2650
  4  0.7200     +0.2350     +0.2350     +0.2300     +0.2450     +0.2300     +0.2550
  8  0.7450     +0.2100     +0.1700     +0.2000     +0.1800     +0.1750     +0.1800
 12  0.7100     +0.0250     +0.0050     +0.2700     +0.1700     +0.2650     +0.2050

Sayılar tabana göre farktır: etiket son dönemle tanımlı olduğundan her uzunluğun kendi tabanı vardır. İlk üç satırda üç yapı ayırt edilemez — uzunluk 8’e kadar hepsi tabanı 0,1700 ile 0,2800 arasında geçiyor ve bağımlılık yalın bir dizeyle de taşınabiliyor.

Son satır ayrımı açıyor. 61 parametreli yalın ağ 0,0250 ve 0,0050’ye, yani tabanın söylediğine düşüyor; kapı birimli ağ 0,2650 ve 0,2050 veriyor. Bağımlılık yalın 6 birimli ağda sekiz ile on adım arası taşınıyor, kapı birimli ağda on iki — dizinin tamamı.

Üçüncü çift saklanmaz ve dersin en önemli satırıdır. Eşit parametre bütçesindeki geniş yalın ağ da on iki adımı taşıyor: 0,2700 ve 0,1700. Kapı birimli ağın 0,2650 ve 0,2050’siyle karşılaştırıldığında iki yapı arasında ölçülebilir bir fark yoktur. Dahası geniş yalın ağın iki koşumu arasındaki fark 0,1000’dir; iki yapı arasındaki farkın her okunuşundan büyüktür. Eğitimsiz ölçüm kapının kalan payı on ila yüz kat büyüttüğünü söylemişti; eğitilen ağın sayısı bunu bu uzunlukta doğrulamıyor da yalanlamıyor da — çünkü eğitim, yalın ağın ağırlıklarını başlangıçtaki değerlerden uzaklaştırıp yavaş unutan bir dize kurabiliyor.

Kural şudur: bir yapının kattığı fark ancak görev o farkı zorlayacak kadar zorsa ölçülebilir. On iki adım yetmiyor ve bu kurgunun sınırı on iki adımdır; daha uzun bir dizide ayrımın açılması beklenir ama ölçülmemiş bir beklenti sayılmaz.

Özet

  • Kapı birimi durumu ht=utht1+(1ut)ath_t = u_t h_{t-1} + (1 - u_t) a_t ile günceller; katsayı sabit değil, o adımın girdisinden hesaplanır.
  • Aynı 6 birimde kapı birimli ağ 115, yalın ağ 61 parametre tutar; bütçeyi eşitlemek için 118 parametreli 9 birimli yalın ağ da ölçülür.
  • Eğitimsiz ağda uzunluk 12’de kalan pay yalın 6’da yüzde 0,98 ve 0,05, yalın 9’da 0,71 ve 0,05, kapı birimlide 9,34 ve 5,63’tür; genişlik unutma hızını değiştirmez.
  • Uzunluk 8’e kadar üç yapı da tabanı 0,1700–0,2800 geçer ve ayırt edilemez.
  • Uzunluk 12’de yalın 6 birimli ağ 0,0250 ve 0,0050’ye düşer; kapı birimli 0,2650 ve 0,2050, geniş yalın 0,2700 ve 0,1700 verir.
  • Kapının eşit bütçeli yalın ağa üstünlüğü bu uzunlukta ölçülemez: geniş yalın ağın iki koşumu arasındaki 0,1000’lik fark, iki yapı arasındaki farktan büyüktür.

Sonraki Adım

Kapı birimi uzun bağımlılığı taşıdı, ama taşıma biçimi değişmedi: bilgi hâlâ tek bir gizli durumdan geçmek zorundaydı ve o durum her adımda yeniden yazıldı. Uzak bir adım gerektiğinde aradaki bütün adımların üzerinden aktarılarak geliyor, doğrudan okunmuyor. Sonraki ders şunu sorar: ağ, karar anında dizinin hangi adımına bakacağını kendisi seçebilseydi ne kazanırdı. Ölçülecek şey ağırlıkların nereye düştüğüdür: seçimin kaçı doğru adıma gidiyor ve yüksek bir ağırlık, o adımın kararı gerçekten belirlediği anlamına geliyor mu.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat