İçeriğe geç
academia.sh

Ders 05 / 14

Fonksiyon Yaklaşımı ve Deneyim Tekrarı

Çizelgenin yerini alan küçük bir ağın ve deneyim tekrarının sayıyla ölçülmesi: 243 durum ile 6 eylemin kurduğu 1.458 hücrenin 9.000 geçiş sonunda yalnız 780'i güncelleniyor, 37 durum hiç görülmüyor ve yalnız 60 durumda altı eylem de deneniyor. Ardışık altılı toplu iş ortalama 1,16 ayrı bölümden, tampondan çekilen altılı 5,50 ayrı bölümden geliyor. Taban çizgileri 0,000 ve 10,432, kural politikası 20,621, çizelge 24,495. 126 parametreli ağ çevrimiçi tek geçişle 23,211 ve 23,071, ardışık altılıyla 22,259 ve 20,146, tekrar tamponuyla 26,233 ve 25,302 veriyor; koşum bandı 2,113'ten 0,930'a iniyor.

İçindekiler

Önceki ders eylem değerini bir çizelgede öğrendi ve çizelgenin kaç hücresinin hiç güncellenmediğini saydı. Bu ders o sayıyı bir sınır olarak ele alır. Çizelgenin sorunu bellek değildir; her hücrenin yalnız o hücreye uğrandığında öğrenilmesi ve iki komşu durum arasında hiçbir bilgi paylaşılmamasıdır. (1,0,2,0,1) durumunda öğrenilen şey (1,0,2,0,0) durumuna geçmez.

Çizelgenin yerine bir fonksiyon yaklaşımı konur: durumu girdi alan, her eyleme bir sayı döndüren küçük bir ağ. Ağ hiç görülmemiş bir durumda da cevap üretir, çünkü benzer durumlardan öğrendiğini oraya taşır. Bedeli, öğrenmenin artık kararlı olmamasıdır — ve bu dersin ölçtüğü şey kararsızlığın nereden geldiği ile deneyim tekrarının onu ne kadar düzelttiğidir.

  • PO41. Ortam 01’de kurulan kurgudur ve burada olduğu gibi sürer: beş abone, dönem başına tek ekip, ufuk 30, indirim katsayısı 0,9. Ajanın gördüğü durum gecikme sınıfıdır; arıza derecesi gizlidir.
  • PO42. Durum beş gecikme sınıfının beşlisidir, yani 35=2433^5 = 243 durum; eylem altıdır — beş aboneden birine gitmek ya da ekip çıkarmamak. Durum–eylem çifti 1.458’dir.
  • PO43. Ölçüm 01’deki aynı 300 bölümde yapılır, böylece bu dersin sayıları önceki derslerin sayılarıyla doğrudan karşılaştırılabilir. Getiri indirimli ödül toplamıdır.
  • PO44. Taban çizgisi iki tanedir: hiç ekip çıkarmamak ve rastgele eylem. Birincisi tanım gereği sıfırdır ve eylemsizliğin karşılığını verir, ikincisi sıralamasız çabanınkini. Yanlarına 01’in kural politikası da yazılır, çünkü öğrenen yöntemin geçmesi gereken sayı odur.
  • PO45. Çizelge, zaman farkı güncellemesiyle 300 bölüm boyunca öğrenilir; keşif oranı 0,60’tan 0,05’e doğrusal iner. Sabit ve düşük bir keşifle ilk denenen eylem kalıcı biçimde öne geçtiği için oran düşürülerek uygulanır.
  • PO46. Ağ M27/K05’ten girdi olarak gelir ve yordamı burada tekrarlanmaz: beş girdi, on gizli birim, altı çıktı; gizli katman hiperbolik tanjant, çıkış katmanı doğrusaldır.
  • PO47. Ağın hedefi ödülün ona bölünmüş biçimidir. Eylem en büyük çıktı seçilerek belirlendiği için bu ölçek politikayı değiştirmez; yalnız hedefleri ağın çıkış aralığına yaklaştırır.
  • PO48. Ağ kullanan her ölçü iki koşumla basılır ve koşumlar arasında yalnız başlangıç değerleri değişir.

Çizelgenin Dolduramadığı Yer

İlk blok ortamı yeniden kurar, üç karşılaştırma sayısını basar ve çizelgenin doluluğunu sayar.

# cizelge.py — Ortam 01'de kurulan KURGUDUR: bes abone, her donem tek ekip.
import math
import statistics

TOHUM, M32 = 20260218, 0xFFFFFFFF
ABONE, KAZANC, MALIYET = 5, (0, 3, 9), 2
KOTULESME = (0.30, 0.05, 0.60, 0.15, 0.45)
EYLEM, UFUK, INDIRIM = ABONE + 1, 30, 0.9


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


class Ortam:
    """Ariza derecesi d gizlidir; ajanin gordugu durum gecikme sinifidir."""

    def __init__(self, tohum):
        self.r = uretec(tohum)
        self.d, self.g = [0] * ABONE, [0] * ABONE
        for i in range(ABONE):
            self.g[i] = int(self.r() * 6)
            for _ in range(self.g[i]):
                if self.d[i] < 2 and self.r() < KOTULESME[i]:
                    self.d[i] += 1

    def durum(self):
        return tuple(min(2, x // 3) for x in self.g)

    def adim(self, a):
        odul = 0.0
        if a < ABONE:
            odul = KAZANC[self.d[a]] - MALIYET
            self.d[a] = 0
            self.g[a] = 0
        for i in range(ABONE):
            if i != a:
                self.g[i] += 1
                if self.d[i] < 2 and self.r() < KOTULESME[i]:
                    self.d[i] += 1
        return self.durum(), odul


def olc(politika, n=300):                   # 01'deki ayni 300 bolum, ayni ufuk
    g = []
    for k in range(n):
        o = Ortam(TOHUM + 1000 * k)
        s, G, c = o.durum(), 0.0, 1.0
        for _ in range(UFUK):
            s2, od = o.adim(politika(s))
            G, c, s = G + c * od, c * INDIRIM, s2
        g.append(G)
    return statistics.mean(g)


def cizelge_egit(tohum, B=300, ogrenme=0.20):
    Q, sayac, r = {}, {}, uretec(tohum)
    for b in range(B):
        kesif = 0.60 - 0.55 * b / (B - 1)
        o = Ortam(tohum + 100 * b)
        s = o.durum()
        for _ in range(UFUK):
            a = (int(r() * EYLEM) if r() < kesif
                 else max(range(EYLEM), key=lambda e: Q.get((s, e), 0.0)))
            s2, od = o.adim(a)
            eski = Q.get((s, a), 0.0)
            Q[(s, a)] = eski + ogrenme * (od + INDIRIM * max(Q.get((s2, e), 0.0)
                                                             for e in range(EYLEM)) - eski)
            sayac[(s, a)] = sayac.get((s, a), 0) + 1
            s = s2
    return Q, sayac


Q, SAYAC = cizelge_egit(TOHUM + 900)
DURUM, CIFT = 3 ** ABONE, 3 ** ABONE * EYLEM
gorulen = {s for s, _ in SAYAC}
tam = sum(all((s, e) in SAYAC for e in range(EYLEM)) for s in gorulen)
print(f"durum {DURUM}, eylem {EYLEM}, durum-eylem cifti {CIFT}")
print(f"300 bolum x {UFUK} adim = {300 * UFUK} gecis; guncellenen cift {len(SAYAC)}"
      f" ({CIFT - len(SAYAC)} hic guncellenmedi), gorulen durum {len(gorulen)}")
print(f"alti eylemi de denenmis durum {tam}, hic gorulmemis durum {DURUM - len(gorulen)}")
print(f"{'taban: hic ekip cikarmamak':<28}{olc(lambda s: ABONE):8.3f}")
rp = uretec(TOHUM + 7)
print(f"{'taban: rastgele eylem':<28}{olc(lambda s: int(rp() * EYLEM)):8.3f}")
print(f"{'kural: gecikmesi en buyuge':<28}"
      f"{olc(lambda s: ABONE if max(s) == 0 else s.index(max(s))):8.3f}")
print(f"{'cizelge':<28}{olc(lambda s: max(range(EYLEM), key=lambda e: Q.get((s, e), 0.0))):8.3f}")
durum 243, eylem 6, durum-eylem cifti 1458
300 bolum x 30 adim = 9000 gecis; guncellenen cift 780 (678 hic guncellenmedi), gorulen durum 206
alti eylemi de denenmis durum 60, hic gorulmemis durum 37
taban: hic ekip cikarmamak     0.000
taban: rastgele eylem         10.432
kural: gecikmesi en buyuge    20.621
cizelge                       24.495

Toplanan veri şudur: 9.000 geçiş yapıldı, 1.458 hücrenin 780’i güncellendi ve 678’i hiç dokunulmadan kaldı. Bu sayı keşif takvimine bağlıdır ve başka bir takvimle başka çıkar; burada bağlayıcı olan büyüklük mertebesidir. Politika kendi verisini topladığı için 243 durumun 37’si hiç görülmedi ve yalnız 60 durumda altı eylemin hepsi denendi. O 37 durumda çizelgenin altı girdisi de sıfırdır; en büyüğünü seçme kuralı orada ilk eylemi seçer ve bu seçimin öğrenilmiş bir yanı yoktur.

Çizelge yine de kazanıyor: 24,495, kural politikasının 20,621’inin üstünde. Sorun bu ölçekte sonucun kötü olması değil, ölçeğin kendisidir. Beş abone 243 durum verdi; yedi abone 2.187 durum ve 17.496 çift verir. Geçiş sayısı aynı kaldığında boş hücre oranı büyür, çünkü çizelge komşu durumlar arasında hiçbir şey paylaşmaz.

Çizelge Yerine Fonksiyon

Ağ bu paylaşımı kurar. Girdisi beş gecikme sınıfıdır, çıktısı altı eylem değeridir; hedef, önceki dersteki zaman farkı hedefinin aynısıdır — alınan ödül artı indirimli en iyi bir sonraki eylem değeri. Fark, güncellemenin tek bir hücreye değil bütün ağırlıklara yayılmasıdır. Kararsızlık da buradan gelir: bir durumda yapılan düzeltme başka durumların çıktısını da oynatır.

İkinci sorun verinin geliş sırasıdır. Ajan geçişleri ardışık üretir; bir bölümün altı ardışık adımı birbirinin devamıdır. Aşağıdaki blok ağı tanımlar ve bu ilişkiyi iki sayıyla ölçer.

OLCEK = 10.0                                # ag hedefi odul/10 olceginde tutulur


def ilklendir(tohum, gizli=10):             # kucuk ag: 5 -> 10 -> 6; yordami M27/K05'te
    r, ag = uretec(tohum), []
    for a, b in zip((ABONE, gizli, EYLEM), (gizli, EYLEM)):
        o = math.sqrt(2.0 / a)
        ag.append(([[(r() * 2 - 1) * o for _ in range(a)] for _ in range(b)], [0.0] * b))
    return ag


def ileri(ag, x):
    (W1, y1), (W2, y2) = ag
    h = [math.tanh(sum(w * v for w, v in zip(s, x)) + b) for s, b in zip(W1, y1)]
    return h, [sum(w * v for w, v in zip(s, h)) + b for s, b in zip(W2, y2)]


def giris(s):
    return [x / 2.0 for x in s]


def guncelle(ag, toplu, ogrenme):           # yalniz secilen eylemin cikisi duzeltilir
    (W1, y1), (W2, y2) = ag
    n, g = len(toplu), len(y1)
    gW1, gy1 = [[0.0] * ABONE for _ in range(g)], [0.0] * g
    gW2, gy2 = [[0.0] * g for _ in range(EYLEM)], [0.0] * EYLEM
    for x, a, hedef in toplu:
        h, q = ileri(ag, x)
        e = q[a] - hedef
        for p in range(g):
            gW2[a][p] += e * h[p]
            dh = e * W2[a][p] * (1 - h[p] * h[p])
            gy1[p] += dh
            for j in range(ABONE):
                gW1[p][j] += dh * x[j]
        gy2[a] += e
    for j in range(EYLEM):
        for p in range(g):
            W2[j][p] -= ogrenme * gW2[j][p] / n
        y2[j] -= ogrenme * gy2[j] / n
    for p in range(g):
        for j in range(ABONE):
            W1[p][j] -= ogrenme * gW1[p][j] / n
        y1[p] -= ogrenme * gy1[p] / n


def ag_egit(tohum, tampon_boy, toplu, B=120, ogrenme=0.10):
    ag, r, tmp = ilklendir(tohum), uretec(tohum + 77), []
    for b in range(B):
        kesif = 0.60 - 0.55 * b / (B - 1)
        o = Ortam(tohum + 100 * b)
        s = o.durum()
        for _ in range(UFUK):
            a = (int(r() * EYLEM) if r() < kesif
                 else max(range(EYLEM), key=lambda e: ileri(ag, giris(s))[1][e]))
            s2, od = o.adim(a)
            tmp.append((s, a, od / OLCEK, s2))
            if len(tmp) > tampon_boy:
                tmp.pop(0)
            ornek = (tmp[-toplu:] if tampon_boy == toplu       # ardisik pencere
                     else [tmp[int(r() * len(tmp))] for _ in range(toplu)])
            guncelle(ag, [(giris(ss), sa, so + INDIRIM * max(ileri(ag, giris(sy))[1]))
                          for ss, sa, so, sy in ornek], ogrenme)
            s = s2
    return ag


def ag_politika(ag):
    return lambda s: max(range(EYLEM), key=lambda e: ileri(ag, giris(s))[1][e])


r = uretec(TOHUM + 3)                       # 30 bolumluk bir iz, cizelge politikasiyla
IZ = []
for b in range(30):
    o = Ortam(TOHUM + 100000 + b)
    s = o.durum()
    for _ in range(UFUK):
        a = (int(r() * EYLEM) if r() < 0.15
             else max(range(EYLEM), key=lambda e: Q.get((s, e), 0.0)))
        IZ.append((s, a, b))
        s = o.adim(a)[0]


def dagilim(g):                             # toplu isteki durumlar arasi ortalama sinif farki
    c = [abs(x - y) for i in range(len(g)) for j in range(i + 1, len(g))
         for x, y in zip(g[i][0], g[j][0])]
    return sum(c) / (len(g) * (len(g) - 1) / 2)


N = len(IZ) - 6
ard = [sum(dagilim(IZ[i:i + 6]) for i in range(N)) / N,
       sum(len({t[2] for t in IZ[i:i + 6]}) for i in range(N)) / N]
tam2 = [0.0, 0.0]
for _ in range(N):
    g = [IZ[int(r() * len(IZ))] for _ in range(6)]
    tam2[0] += dagilim(g) / N
    tam2[1] += len({t[2] for t in g}) / N
print(f"{'altili toplu is':<26}{'ardisik':>10}{'tampondan':>12}")
print(f"{'ortalama sinif farki':<26}{ard[0]:>10.2f}{tam2[0]:>12.2f}")
print(f"{'ayri bolum sayisi':<26}{ard[1]:>10.2f}{tam2[1]:>12.2f}")
altili toplu is              ardisik   tampondan
ortalama sinif farki            2.71        2.93
ayri bolum sayisi               1.16        5.50

İkinci satır ilişkiyi doğrudan söylüyor: ardışık bir altılı ortalama 1,16 ayrı bölümden geliyor, yani neredeyse tamamı tek bir bölümün art arda gelen adımlarıdır. Tampondan çekilen altılı 5,50 ayrı bölümden geliyor. Durum tarafındaki fark daha ölçülüdür — ardışık altılıda iki durum arasındaki ortalama gecikme sınıfı farkı 2,71, tampondan çekilende 2,93. Ağ ardışık kurulumda her adımda birbirine yakın altı örneğe bakar ve ağırlıklarını o dar bölgeye göre kaydırır; birkaç adım sonra başka bir bölgeye geçtiğinde kaymayı geri alır.

Tekrar Tamponunun Kattığı Fark

Deneyim tekrarı tek satırlık bir değişikliktir: geçişler bir tampona yazılır ve güncelleme tampondan rastgele çekilen bir altılıyla yapılır. Farkın toplu iş boyundan mı yoksa örneğin nereden geldiğinden mi doğduğunu ayırmak için üçüncü bir kurulum eklenir — toplu iş kullanmayan, yalnız son geçişle güncelleyen çevrimiçi biçim. Üçünün de bütçesi aynıdır: 120 bölüm, 3.600 geçiş.

SONUC = {}
print(f"{'kurulum':<22}{'kosum 1':>9}{'kosum 2':>9}{'band':>7}")
for ad, tampon, toplu in (("cevrimici tek gecis", 1, 1),
                          ("ardisik altili", 6, 6),
                          ("tekrar tamponu", 900, 6)):
    SONUC[ad] = [olc(ag_politika(ag_egit(TOHUM + k, tampon, toplu))) for k in (1, 2)]
    g = SONUC[ad]
    print(f"{ad:<22}{g[0]:>9.3f}{g[1]:>9.3f}{max(g) - min(g):>7.3f}")

A, T = SONUC["ardisik altili"], SONUC["tekrar tamponu"]
par = ABONE * 10 + 10 + 10 * EYLEM + EYLEM
print(f"\nayni toplu is boyu, ardisik yerine tampondan: "
      f"{max(A):.3f} -> {max(T):.3f} ve {min(A):.3f} -> {min(T):.3f}")
print(f"kosum bandi {max(A) - min(A):.3f} -> {max(T) - min(T):.3f}")
print(f"ag {par} parametre; cizelge {CIFT} hucre, {CIFT - len(SAYAC)} tanesi bos")
kurulum                 kosum 1  kosum 2   band
cevrimici tek gecis      23.211   23.071  0.139
ardisik altili           22.259   20.146  2.113
tekrar tamponu           26.233   25.302  0.930

ayni toplu is boyu, ardisik yerine tampondan: 22.259 -> 26.233 ve 20.146 -> 25.302
kosum bandi 2.113 -> 0.930
ag 126 parametre; cizelge 1458 hucre, 678 tanesi bos

Üç satır sırayla okunur. Toplu iş kullanmak tek başına bir kazanç değildir: çevrimiçi tek geçiş 23,211 ve 23,071 verirken ardışık altılı 22,259 ve 20,146 veriyor, yani altı örneği ortalamak sayıyı düşürüyor. İkinci koşum 20,146 ile kural politikasının 20,621’inin de altına iniyor. Aynı toplu iş boyu tampondan çekildiğinde 26,233 ve 25,302 çıkıyor. Kazanç toplu iştan değil, örneğin nereden geldiğinden doğuyor.

İkinci sayı kararlılıktır. Ardışık kurulumun koşum bandı 2,113; tekrar tamponununki 0,930. Ardışık kurulumda tek bir koşuma bakarak karar vermek, yalnız başlangıç değerleri değişerek iki birimden fazla oynayan bir sayıya bakmaktır. Bu kursun iki koşum kuralı bu yüzden vardır.

Son satır ölçeği kapatır. Ağ 126 parametre taşıyor ve 243 durumun tamamı için altı eylem değeri üretiyor; çizelge 1.458 hücre taşıyordu ve 678’i boştu. Ağın hiç görülmemiş 37 durumda verdiği cevap doğru olmak zorunda değildir, ama keyfi de değildir: komşu durumlardan taşınmış bir tahmindir.

Özet

  • Çizelge komşu durumlar arasında hiçbir şey paylaşmaz. 9.000 geçiş sonunda 1.458 hücrenin 678’i hiç güncellenmedi, 243 durumun 37’si hiç görülmedi ve yalnız 60 durumda altı eylem de denendi.
  • Fonksiyon yaklaşımı çizelgenin yerine durumu girdi alan bir ağ koyar: 126 parametre, 1.458 hücreye karşılık, ve hiç görülmemiş durumda da bir cevap.
  • Ardışık geçişler ilişkilidir ve sayısı yazılır: ardışık altılı ortalama 1,16 ayrı bölümden, tampondan çekilen altılı 5,50 ayrı bölümden geliyor.
  • Aynı bütçede çevrimiçi tek geçiş 23,211 ve 23,071, ardışık altılı 22,259 ve 20,146, tekrar tamponu 26,233 ve 25,302 veriyor. Kazanç toplu iştan değil örneğin nereden geldiğinden gelir.
  • Deneyim tekrarı düzeyi yükseltmenin yanında kararlılık da katar: koşum bandı 2,113’ten 0,930’a iniyor, ve ardışık kurulumun kötü koşumu kural politikasının altına düşüyor.

Sonraki Adım

Beş derste ajan hep aynı yoldan karar verdi: her eylem için bir değer kestirildi ve en büyüğü seçildi. Politika, değerin bir yan ürünüydü. Bu, değer kestirimindeki küçük bir kaymanın politikayı tümüyle değiştirebileceği anlamına gelir — iki eylemin değeri birbirine yakınsa, kestirimin oynaması seçimi de oynatır. Sonraki ders politikayı doğrudan parametreleştirir ve değeri aradan çıkarır: her eyleme bir olasılık atanır ve olasılıklar getiriyi artıracak yönde güncellenir. Ölçülecek olan bu yolun bedelidir — güncelleme yönü artık örneklenmiş bölümlerden kestirilir, ve aynı politikayla aynı bütçede kaç bölümün kaç ayrı yön verdiği sayılır.

İ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