İçeriğe geç
academia.sh

Ders 17 / 24

Gömme Katmanları

Ayrık bir olay kodunun sürekli bir vektöre eşlenmesinin ne kattığının ölçülmesi: en sık sınıf tabanı 0,6444 iken 103 parametreli öğrenilen gömme 150 turda 0,9722 ve 0,9833 veriyor, 157 parametreli bir-sıcak kodlama aynı turda 0,7167 ve 0,7000'de kalıp aynı sayıya ancak 600 turda ulaşıyor (0,9611 ve 0,9556). Aynı boyuttaki dondurulmuş tablo 0,6944 ve 0,7278'de kalıyor, sıralı sayısal kod ise dört tur bütçesinde de tam olarak tabanda duruyor. Öğrenilen tabloda şüpheli kodlar arası uzaklık grup içi uzaklığın 3,9153 katı, dondurulmuş tabloda 1,0728 katıdır.

İçindekiler

Önceki iki derste girdinin her adımı hazır bir sayıydı. Diziler böyle gelmez. Bir sayaç kaydında okumanın yanında bir olay kodu durur — kalibrasyon, iletişim kesintisi, kapak açılması, elle okuma — ve bu kod bir simgedir. Sayısal bir değeri yoktur; on yedinci kodun on altıncıdan büyük olması hiçbir şey söylemez.

M27/K02 bu simgeleri bir-sıcak sütunlara çevirmişti: her kod için bir gösterge sütunu. Yordam çalışır, ama iki bedeli vardır. Girdi boyutu kod sayısıyla birlikte büyür, ve simgeler arasındaki hiçbir yakınlık taşınmaz — birbirinin yerine geçebilen iki kod, ilgisiz iki kod kadar uzaktır. Bu dersin sorusu şudur: kodun temsilini elle vermek yerine öğrenmek hangi sayıyı oynatır, ve öğrenilen temsil ile göreve hiç bakmadan sabitlenmiş bir temsil arasındaki fark nedir.

  • MI64. Bu payın dizi kurgusu mimariler/06’da kuruldu ve kurgudur. Bu derste her adıma kurgu bir olay kodu eklenir: 24 kod, adım başına bir tane, tohum 20260218. Okumalar değişmez.
  • MI65. Sekiz kod şüpheli olarak işaretlidir ve bu sekizin dizideki numaraları bitişik değildir. Etiket, on iki adımın en az beşinde şüpheli bir kod bulunmasıdır.
  • MI66. Taban çizgisi en sık sınıftır. Kod numaralarının sırası etiketle ilişkisiz olduğu için sıralı bir sayısal kodlamanın tabanı geçmesi beklenmez ve bu ölçülür.
  • MI67. Model ders içinde yazılır ve modeldir: adımların temsilleri ortalanır, bir gizli katmandan (altı birim, doğrultulmuş doğrusal birim) geçirilir ve tek çıkışa bağlanır. Kitaplık çağrılmaz.
  • MI68. Dört kurulum aynı gövdeyi paylaşır ve yalnız kodun temsilinde ayrılır: bir-sıcak, öğrenilen gömme, dondurulmuş gömme, sıralı sayısal kod.
  • MI69. Bir-sıcak kurulumda tablo birim dizeydir ve saklanmaz; kod bunu sayımla gerçekleştirir. Parametre sayımında birim dizey parametre sayılmaz, çünkü serbest bir değeri yoktur.
  • MI70. Dondurulmuş gömme, aynı boyutta bir tablonun ilklendirilip hiç güncellenmemesidir. M27/K04 boyut-azaltma’nın izdüşümü de göreve bakmadan sabitlenmişti; oradaki ölçü geri kurma hatasıydı, burada ayrılmış küme sayısıdır.
  • MI71. Eğitim tam toplu eğim inişidir, öğrenme adımı 0,9, ve dört tur bütçesinde ölçülür: 150, 300, 450, 600.
  • MI72. Her kurulum iki koşumla basılır; koşumlar ilklendirme tohumunda ayrılır.

Aynı Gövde, Dört Temsil

Görev kodların sayımına bağlıdır, sırasına değil. Bu yüzden model adım temsillerini ortalar ve ortalamayı küçük bir gizli katmana verir. Etiket kodlardan tam olarak belirlendiği için, şüpheli kodları öbürlerinden ayırabilen bir temsil görevi kusursuz çözebilir; ayıramayan bir temsil ise hiçbir tur bütçesinde çözemez.

# ORTAK — MODELDIR. `mimariler/06`'nin KURGU dizi kumesi ayni tohumla yeniden uretilir;
# her adima KURGU bir olay kodu eklenir.
import math

TOHUM, M32, ADIM = 20260218, 0xFFFFFFFF, 12
KOD, SUP, ESIK = 24, (1, 4, 5, 9, 13, 16, 20, 22), 5


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()
        oku = [0.0] + [round((r() + r() + r() - 1.5) * 1.9, 3) for _ in range(ADIM - 1)]
        r()
        o = uretec(tohum + 8000 + i)
        kod = [int(o() * KOD) for _ in range(ADIM)]
        D.append({"oku": oku, "kod": kod,
                  "y": 1 if sum(c in SUP for c in kod) >= ESIK else 0})
    return D


VERI = dizi_kur(720, TOHUM)
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}, kod sayisi {KOD}, supheli kod {len(SUP)}")
print(f"etiket orani egitim {sum(x['y'] for x in EGT) / len(EGT):.4f}, ayrilmis {oran:.4f}")
print(f"taban cizgisi (en sik sinif) {TABAN:.4f}")
print(f"ornek kod dizisi {VERI[0]['kod']}, supheli sayisi "
      f"{sum(c in SUP for c in VERI[0]['kod'])}, etiket {VERI[0]['y']}")
dizi 720, uzunluk 12, kod sayisi 24, supheli kod 8
etiket orani egitim 0.3450, ayrilmis 0.3556
taban cizgisi (en sik sinif) 0.6444
ornek kod dizisi [0, 8, 0, 16, 22, 10, 17, 7, 14, 19, 7, 18], supheli sayisi 2, etiket 0

Gömme katmanı bir tablodur: kod sayısı kadar satır, gömme boyutu kadar sütun. Bir kodun temsili o tablodan okunan satırdır ve satır bir parametredir — eğim onu da günceller. Bir-sıcak kurulumda tablo yoktur, çünkü gösterge vektörünü bir doğrusal katmanla çarpmak zaten o katmanın sütununu okumaktır. İki kurulum arasındaki fark bir ilke farkı değil, satırın nereye yazıldığı ve kaç tane olduğudur.

GIZ, DUR = 6, (150, 300, 450, 600)


def temsil(T, kod):
    if T is None:                       # bir-sicak: tablo birim dizeydir, sayim yeter
        h = [0.0] * KOD
        for c in kod:
            h[c] += 1.0 / ADIM
        return h
    h = [0.0] * len(T[0])
    for c in kod:
        for j in range(len(h)):
            h[j] += T[c][j] / ADIM
    return h


def tablo(tip, tohum, d=3):
    if tip == "bir-sicak":
        return None, KOD
    if tip == "sayisal":
        return [[c / (KOD - 1)] for c in range(KOD)], 1
    r = uretec(tohum)
    return [[(r() + r() + r() - 1.5) * 1.1 for _ in range(d)] for _ in range(KOD)], d


def egit(tohum, T, dm, ogren, EG, adim=0.9):
    r = uretec(tohum + 500)
    g = lambda: (r() + r() + r() - 1.5) * 0.9
    W1 = [[g() for _ in range(dm)] for _ in range(GIZ)]
    b1, w, b, n, olcum = [0.0] * GIZ, [g() for _ in range(GIZ)], [0.0], len(EG), {}
    for tur in range(1, max(DUR) + 1):
        gW1 = [[0.0] * dm for _ in range(GIZ)]
        gb1, gw, gb = [0.0] * GIZ, [0.0] * GIZ, 0.0
        gT = [[0.0] * dm for _ in range(KOD)] if ogren else None
        for h, kod, y in EG:
            z = [sum(W1[i][j] * h[j] for j in range(dm)) + b1[i] for i in range(GIZ)]
            o = sum(w[i] * z[i] for i in range(GIZ) if z[i] > 0) + b[0]
            df = 1.0 / (1.0 + math.exp(-max(-30.0, min(30.0, o)))) - y
            gb += df
            da = [df * w[i] if z[i] > 0 else 0.0 for i in range(GIZ)]
            for i in range(GIZ):
                gw[i] += df * max(0.0, z[i])
                gb1[i] += da[i]
                for j in range(dm):
                    gW1[i][j] += da[i] * h[j]
            if ogren:
                dh = [sum(da[i] * W1[i][j] for i in range(GIZ)) for j in range(dm)]
                for c in kod:
                    for j in range(dm):
                        gT[c][j] += dh[j] / ADIM
        for i in range(GIZ):
            w[i] -= adim * gw[i] / n
            b1[i] -= adim * gb1[i] / n
            for j in range(dm):
                W1[i][j] -= adim * gW1[i][j] / n
        b[0] -= adim * gb / n
        if ogren:                       # gomme tablosu da bir parametredir
            for c in range(KOD):
                for j in range(dm):
                    T[c][j] -= adim * gT[c][j] / n
            for k, (_h, kod, y) in enumerate(EG):
                EG[k] = (temsil(T, kod), kod, y)
        if tur in DUR:
            P = {"T": T, "dm": dm, "W1": [u[:] for u in W1], "b1": b1[:],
                 "w": w[:], "b": b[0]}
            olcum[tur] = dogruluk(P, SIN)
    return P, olcum


def cikti(P, kod):
    h = temsil(P["T"], kod)
    z = [sum(P["W1"][i][j] * h[j] for j in range(P["dm"])) + P["b1"][i]
         for i in range(GIZ)]
    return sum(P["w"][i] * max(0.0, z[i]) for i in range(GIZ)) + P["b"]


def dogruluk(P, D):
    return sum((cikti(P, x["kod"]) > 0) == (x["y"] == 1) for x in D) / len(D)


AG, KUR = {}, (("bir-sicak", "bir-sicak", False), ("gomme, ogrenilen", "gomme", True),
               ("gomme, dondurulmus", "gomme", False), ("sayisal kod", "sayisal", False))

print(f"gizli birim {GIZ}, egitim ornegi {len(EGT)}, "
      f"taban cizgisi {TABAN:.4f}")
print(f"{'kurulum':<21}{'parametre':>10}{'ogrenilen':>10}{'kosum':>7}"
      + "".join(f"{'tur ' + str(t):>10}" for t in DUR))
for ad, tip, ogren in KUR:
    AG[ad] = []
    for k in (1, 2):
        T, dm = tablo(tip, TOHUM + 900 + k)
        EG = [(temsil(T, x["kod"]), x["kod"], x["y"]) for x in EGT]
        P, olcum = egit(TOHUM + k, T, dm, ogren, EG)
        AG[ad].append(P)
        gom = KOD * dm if tip == "gomme" else 0
        par = GIZ * dm + 2 * GIZ + 1 + gom
        ogr = par - (0 if ogren else gom)
        print(f"{ad if k == 1 else '':<21}{par:>10}{ogr:>10}{k:>7}"
              + "".join(f"{olcum[t]:>10.4f}" for t in DUR))
gizli birim 6, egitim ornegi 200, taban cizgisi 0.6444
kurulum               parametre ogrenilen  kosum   tur 150   tur 300   tur 450   tur 600
bir-sicak                   157       157      1    0.7167    0.8000    0.9222    0.9611
                            157       157      2    0.7000    0.8111    0.8611    0.9556
gomme, ogrenilen            103       103      1    0.9722    1.0000    1.0000    1.0000
                            103       103      2    0.9833    1.0000    1.0000    1.0000
gomme, dondurulmus          103        31      1    0.6944    0.6778    0.6778    0.6833
                            103        31      2    0.7278    0.7389    0.7444    0.7444
sayisal kod                  19        19      1    0.6444    0.6444    0.6444    0.6444
                             19        19      2    0.6444    0.6444    0.6444    0.6444

Dört satır dört ayrı sonuç veriyor. Öğrenilen gömme 150 turda 0,9722 ve 0,9833’e çıkıyor, 300 turda iki koşumda da 1,0000’e oturuyor — görev kodlardan tam belirlendiği için bu beklenen tavandır. Bir-sıcak kurulum aynı 150 turda 0,7167 ve 0,7000, yani tabanın az üstünde. Fark ifade gücünden gelmiyor: 600 turda 0,9611 ve 0,9556’ya çıkıyor. Aynı yere dört kat tur bütçesiyle varıyor ve bunu 157 parametreyle yapıyor, gömmenin 103’üne karşılık.

Dondurulmuş tablo aynı boyuttadır ve aynı gövdeye bağlıdır; tek farkı 72 satırlık tablonun hiç güncellenmemesidir. Dört tur bütçesinde de 0,68 ile 0,75 arasında kalıyor. Tur eklemek işe yaramıyor, çünkü eksik olan bütçe değil: göreve bakmadan seçilmiş üç yön, şüpheli sekiz kodu öbür on altıdan ayırmıyor ve gövde ayrılmamış bir temsilden ayrım üretemiyor. M27/K04 boyut-azaltma aynı konumu geri kurma hatasıyla ölçmüştü — orada sütun ortalamalarıyla geri kurmanın 3,3411’ine karşı iki bileşenli izdüşüm 2,7762 vermişti — ve oradaki yönler de veriden, etiketten değil, seçilmişti. Bir temsilin veriyi iyi koruması, görevin istediği ayrımı taşıdığı anlamına gelmez.

Son satır en serttir. Sıralı sayısal kod dört bütçenin dördünde de tam olarak 0,6444, yani taban çizgisinin kendisidir. Kod numaraları arasındaki sıra etiketle ilişkisiz olduğu için tek kanal hiçbir şey taşımıyor. M27/K02’nin kodlama dersinin uyarısı burada sayıya dönüşüyor.

Parametre Sayısı Kod Sayısıyla Nasıl Büyüyor

Yirmi dört kodda gömmenin parametre kazancı küçüktür: 103’e karşı 157. Kazancın nereden geldiği ancak kod sayısı ve gizli katman büyüdükçe görünür. Hesap tek satırlıktır ve koşum gerektirmez.

def sayim(V, giz, d=None):
    if d is None:
        return V * giz + 2 * giz + 1        # bir-sicak vektor dogrudan katmana
    return V * d + d * giz + 2 * giz + 1    # gomme tablosu, sonra katman


print(f"{'kod sayisi':>11}{'gizli birim':>13}{'bir-sicak':>11}{'gomme d=3':>11}"
      f"{'oran':>8}{'adim basina carpma':>20}")
for V in (KOD, 240, 2400):
    for giz in (GIZ, 64):
        a, b = sayim(V, giz), sayim(V, giz, 3)
        print(f"{V:>11}{giz:>13}{a:>11}{b:>11}{b / a:>8.3f}"
              f"{f'{V * giz} / {3 * giz}':>20}")
 kod sayisi  gizli birim  bir-sicak  gomme d=3    oran  adim basina carpma
         24            6        157        103   0.656            144 / 18
         24           64       1665        393   0.236          1536 / 192
        240            6       1453        751   0.517           1440 / 18
        240           64      15489       1041   0.067         15360 / 192
       2400            6      14413       7231   0.502          14400 / 18
       2400           64     153729       7521   0.049        153600 / 192

Bir-sıcak kurulumda parametre sayısı kod sayısı ile gizli birim sayısının çarpımı kadar büyür. Gömmede tablo kod sayısıyla doğru orantılı büyür ama gizli katman yalnız gömme boyutuna bağlıdır, dolayısıyla ikinci çarpan sabit kalır. 2.400 kod ve 64 gizli birimde oran 0,049’a iner. Son sütun çarpma sayısını aynı biçimde okur: bir-sıcak vektörle çarpım 153.600 çarpma ister ve bunların 153.408’i sıfırla yapılır; tablodan satır okuyup 192 çarpma yapmak aynı sonucu verir. Yalnız ilk satır ölçüldü; kalanlar aynı formülün değerleridir.

Öğrenilen Tablo Neyi Kodladı

Gömmenin sayısı yükseltmesi bir sonuçtur; hangi yapıyı bulduğu ayrı bir sorudur. Görev kodları iki gruba ayırıyor, ve bu ayrım tabloda görünüyorsa şüpheli kodların birbirine, öbürlerinden daha yakın durması gerekir. Ölçü ölçek bağımsızdır: gruplar arası ortalama uzaklığın grup içi ortalama uzaklığa oranı.

def uzaklik(u, v):
    return sum((u[i] - v[i]) ** 2 for i in range(len(u))) ** 0.5


def ortalama_ikili(T, A, B):
    c = [uzaklik(T[i], T[j]) for i in A for j in B if i != j]
    return sum(c) / len(c)


S = [c for c in range(KOD) if c in SUP]
D = [c for c in range(KOD) if c not in SUP]
print(f"supheli kod {len(S)}, oteki {len(D)}")
print(f"{'tablo':<26}{'kosum':>7}{'supheli ici':>13}{'oteki ici':>11}"
      f"{'gruplar arasi':>15}{'ayrim orani':>13}")
for ad in ("gomme, ogrenilen", "gomme, dondurulmus"):
    for k in (0, 1):
        T = AG[ad][k]["T"]
        i, o, a = (ortalama_ikili(T, S, S), ortalama_ikili(T, D, D),
                   ortalama_ikili(T, S, D))
        print(f"{ad if k == 0 else '':<26}{k + 1:>7}{i:>13.4f}{o:>11.4f}"
              f"{a:>15.4f}{a / ((i + o) / 2):>13.4f}")
supheli kod 8, oteki 16
tablo                       kosum  supheli ici  oteki ici  gruplar arasi  ayrim orani
gomme, ogrenilen                1       0.7629     0.8020         3.0634       3.9153
                                2       0.8673     0.9887         3.0602       3.2977
gomme, dondurulmus              1       0.9898     1.0181         1.0771       1.0728
                                2       1.0155     1.1029         1.0766       1.0164

Öğrenilen tabloda iki grup birbirinden ayrılmıştır: gruplar arası ortalama uzaklık grup içi ortalamanın 3,9153 ve 3,2977 katıdır. Dondurulmuş tabloda aynı oran 1,0728 ve 1,0164 — yani grup içi ile gruplar arası uzaklık neredeyse eşittir, çünkü rastgele seçilmiş üç yön kodları görevin tanımadığı bir düzende dağıtmıştır. İki koşumun ayrım oranları arasında 0,6176’lık bir fark vardır ve her iki koşum da 1,0000 doğruluk üretmektedir; tablonun tam olarak nereye yerleştiği koşuma bağlıdır, ayrımı yapması ise değildir.

Özet

  • Bir-sıcak vektörü doğrusal bir katmana vermek, gömme tablosundan satır okumakla aynı işlemdir; fark parametre sayısında ve çarpma sayısındadır.
  • Aynı gövdede öğrenilen gömme 103 parametreyle 150 turda 0,9722 ve 0,9833 verir; 157 parametreli bir-sıcak kurulum aynı turda 0,7167 ve 0,7000’de kalır ve benzer sayıya ancak 600 turda ulaşır.
  • Göreve bakmadan dondurulmuş aynı boyuttaki tablo 0,68 ile 0,75 arasında kalır ve tur eklemek bunu düzeltmez; M27/K04’ün izdüşümü de aynı konumdaydı ve orada geri kurma hatasıyla ölçülmüştü.
  • Sıralı sayısal kodlama dört tur bütçesinde de tam olarak taban çizgisini, 0,6444’ü verir, çünkü kod numaralarının sırası etiketle ilişkisizdir.
  • Öğrenilen tabloda gruplar arası uzaklık grup içi uzaklığın 3,9153 ve 3,2977 katıdır; dondurulmuş tabloda 1,0728 ve 1,0164 katı, yani ayrım yoktur.

Sonraki Adım

Bu derste gömme tablosu görevin kendi etiketleriyle öğrenildi ve iki yüz eğitim örneği buna yetti. Etiketin pahalı olduğu durumlarda bu varsayım düşer: elde yirmi ya da kırk etiketli dizi varsa, yüz üç parametrenin hepsini o kırk örnekten öğrenmek aşırı uyumla biter. Bir yol daha vardır ve bu derste kurulan yapı onu doğrudan kullanır — tablo başka bir görevde öğrenilip bu göreve taşınabilir. Sonraki ders önceden eğitilmiş bir modeli kurgu bir kaynak görevden kendi eliyle üretir, ağırlıkları ya dondurup ya ince ayar yaparak aktarır ve aktarımın kattığı farkı kaç etiketli örnekle kattığıyla birlikte aynı tabana karşı basar.

İ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