İçeriğe geç
academia.sh

Ders 02 / 14

Sayısal Temsil

Kısa saha notlarının sütuna çevrilmesinde her kararın kattığının aynı model ve aynı ayrılmış payla sayılması: alanın tabanı olan elle sayılmış beş sayı 0,7383 verirken en sık sınıf 0,7017'de kalıyor, 96 gövdelik sözcük torbası 0,8217'ye çıkıyor ve çizgiyi 0,0833 geçiyor. Sözlük boyu 8'den 64'e katkı ekliyor, 64'ten 96'ya tam sıfır ekliyor. Ham sayım ile ters belge sıklığı ağırlığı doğruluğu hiç oynatmıyor (0,0833), taşıyıcı sözcük atmak 0,0067 kaybettiriyor ve olay türünü bilen tavan 0,8250 — torba tavanın 0,0033 altındadır.

İçindekiler

Önceki ders metni belirteçlere böldü ve sözlüğü 96 gövdeye indirdi. Ortaya çıkan şey hâlâ bir sözcük listesiydi; bir modelin göreceği tek bir sayı üretilmemişti. Bu ders sözlüğü sütuna çevirir: her gövde bir sütun olur, notta geçip geçmediği o sütunun değeri olur. Yordamın adı sözcük torbasıdır, çünkü sıra atılır — muhur kirik ile kirik muhur aynı satırı verir.

Ölçünün çizgisi hazırdır. M27/K02 aynı not alanından elle beş sayı çıkarmış ve o beş sayı bir karar ağacına ayrılmış kümede 0,0317 katmıştı. Alanın tabanı o beş sayıdır: bir metinden sayı çıkarmanın en ucuz yolu. Sözcük torbası bu çizginin ne kadar üstüne çıkıyor, sözlük boyu büyüdükçe katkı ne yapıyor ve terim ağırlıklandırma üstüne ne koyuyor.

  • NL9. Kurgu, küme ve tohum nlp/01‘deki gibidir. Belirteçleme kararı 01’in üçüncü kararıdır — noktalama atma, küçük harfe inme, gövdeleme, sayı katlama — ve bu derste sabittir.
  • NL10. Görev ikili kaçak şüphesi kestirimidir. Ölçüt ayrılmış paydaki doğruluktur (büyük iyi) ve yanına şüpheli sınıfın duyarlılığı yazılır. Ölçüt tanımları M27/K03’te kuruldu, tekrarlanmaz.
  • NL11. Bütün temsiller aynı modeli kullanır: tek katmanlı doğrusal model, tam toplu eğim inişi, 120 tur, adım 1,5, eşik sıfır. Model ve ölçüt sabit olduğu için fark yalnız temsilden gelebilir.
  • NL12. Boru hattının her adımı yalnız eğitim payından öğrenilir: sözlük, belge sıklığı, ortalama ve standart sapma. M27/K02’nin kuralı sürer.
  • NL13. Alanın tabanı elle sayılmış beş sayıdır: not uzunluğu, sözcük sayısı ve üç anahtar sözcük göstergesi (mühür, erişim, araç). İlk ikisi eğitim payının ortalaması ve standart sapmasıyla ölçeklenir. En sık sınıf mutlak tabandır ve duyarlılığı sıfırdır.
  • NL14. Sözlük boyu süpürmesi altı adaydır: 8, 16, 32, 48, 64, 96. Sözlük, eğitim payının en sık gövdelerinden sırayla alınır.
  • NL15. Terim ağırlıklandırma biçimiyle anılır: ham sayım, ve sayımın ters belge sıklığıyla çarpımı — ikincisi belge başına birim uzunluğa getirilir.
  • NL16. Tavan, olay türünü bilen bir yordamın aynı ölçütteki sayısıdır; etiket yalnız türden üretildiği için metinden okunabilecek en yüksek sayı budur.

Kurulum

Notlar nlp/01’in kurgusuyla aynı tohumdan yeniden üretilir.

# ORTAK — KURGUDUR. Saha notlari ders icinde uretilir, tohum 20260218; kaynak
# sistemden gelmez. Sozluk 45 cekimli kok ve 40 seyrek addan olusur.
TOHUM, NOT_SAYISI, M32 = 20260218, 1800, 0xFFFFFFFF

AD = {  # 0 yalin, 1 ilgi, 2 bulunma, 3 iyelik, 4 cogul
    "sayac": "sayac sayacin sayacta sayaci sayaclar",
    "kapak": "kapak kapagin kapakta kapagi kapaklar",
    "muhur": "muhur muhurun muhurde muhuru muhurler",
    "vana": "vana vananin vanada vanasi vanalar",
    "kelepce": "kelepce kelepcenin kelepcede kelepcesi kelepceler",
    "boru": "boru borunun boruda borusu borular",
    "pano": "pano panonun panoda panosu panolar",
    "kapi": "kapi kapinin kapida kapisi kapilar",
    "zil": "zil zilin zilde zili ziller",
    "bahce": "bahce bahcenin bahcede bahcesi bahceler",
    "apartman": "apartman apartmanin apartmanda apartmani apartmanlar",
    "bodrum": "bodrum bodrumun bodrumda bodrumu bodrumlar",
    "giris": "giris girisin giriste girisi girisler",
    "adres": "adres adresin adreste adresi adresler",
    "okuma": "okuma okumanin okumada okumasi okumalar",
    "olcum": "olcum olcumun olcumde olcumu olcumler",
    "erisim": "erisim erisimin erisimde erisimi erisimler",
    "ziyaret": "ziyaret ziyaretin ziyarette ziyareti ziyaretler",
    "abone": "abone abonenin abonede abonesi aboneler",
    "arac": "arac aracin aracta araci araclar",
    "kir": "kir kirin kirde kiri kirler",
    "iz": "iz izin izde izi izler",
    "sokak": "sokak sokagin sokakta sokagi sokaklar",
    "ev": "ev evin evde evi evler",
}
NITELIK = "kirik gevsek kirli normal bozuk acik kapali eksik temiz yeni yok".split()
EYLEM = {  # 0 edilgen gecmis, 1 olumsuz
    "calis": "calisiyor calismiyor", "don": "donuyor donmuyor", "oku": "okundu okunmadi",
    "ac": "acildi acilmadi", "gir": "girildi girilemedi", "ulas": "ulasildi ulasilamadi",
    "tekrarla": "tekrarlandi tekrarlanmadi", "bul": "bulundu bulunmadi",
    "sagla": "saglandi saglanamadi", "degil": "degil degildi",
}
NADIR = """kablo kablosu kabloda|cam cami camda|tel teli telde|mandal mandali mandalda
merdiven merdiveni merdivende|tahta tahtasi tahtada|cukur cukuru cukurda|kar kari karda
buz buzu buzda|cop copu copta|duvar duvari duvarda|kutu kutusu kutuda|vida vidasi vidada
conta contasi contada|filtre filtresi filtrede|bant banti bantta|etiket etiketi etikette
kilit kiliti kilitte|asansor asansoru asansorde|zemin zemini zeminde|tavan tavani tavanda
kuyu kuyusu kuyuda|depo deposu depoda|ocak ocagi ocakta|direk diregi direkte
kanal kanali kanalda|numara numarasi numarada|cati catisi catida|baca bacasi bacada
kova kovasi kovada|levha levhasi levhada|somun somunu somunda|tapa tapasi tapada
izolasyon izolasyonu izolasyonda|supap supabi supapta|menfez menfezi menfezde
kayit kaydi kayitta|temel temeli temelde|kose kosesi kosede|koruma korumasi korumada"""
OBEK = {
    "olagan": ["{sayac.0} {calis.0}", "{okuma.0} normal", "{olcum.0} {tekrarla.0}",
               "{sayac.1} {erisim.3} {sagla.0}", "{kapak.0} temiz", "{vana.0} acik",
               "{sayac.2} {iz.0} {bul.1}", "{olcum.0} icin {erisim.0} {sagla.0}",
               "{sayac.1} {kapak.3} yeni", "{muhur.0} ile {kapak.0} temiz"],
    "ariza": ["{sayac.0} {don.1}", "{kapak.0} kirik", "{pano.0} bozuk",
              "{sayac.1} {kapak.3} kirik", "{olcum.0} {oku.1}", "{vana.0} bozuk",
              "{sayac.2} {kir.0} {bul.0}", "{sayac.4} {calis.1}",
              "{sayac.0} {calis.0} ama {okuma.0} yok",
              "{pano.1} {kapak.3} eksik"],
    "erisilemedi": ["{kapi.0} {ac.1}", "{zil.0} {calis.1}", "{abone.0} {ev.2} {degil.1}",
                    "{erisim.0} {sagla.1}", "{bodrum.0} {kapi.3} kapali",
                    "{apartman.1} {giris.3} kapali", "{adres.2} {ulas.1}",
                    "{bahce.1} {kapi.3} kapali", "{apartman.2} {zil.0} {calis.1}",
                    "{sayac.2} {erisim.0} yok"],
    "kacak": ["{muhur.0} kirik", "{kelepce.0} gevsek", "{muhur.2} {iz.0} {bul.0}",
              "{sayac.1} {muhur.3} kirik", "{kelepce.2} {iz.0} {bul.0}",
              "{muhur.0} eksik", "{vana.1} {kelepce.3} gevsek",
              "{muhur.1} {iz.3} {bul.0}", "{boru.2} {kelepce.0} eksik",
              "{kapak.2} bir {iz.0} {bul.0}"],
}
EK_OBEK = ["{ziyaret.0} {tekrarla.0}", "{sokak.2} {arac.0} {bul.0}", "{adres.0} yeni",
           "{bahce.1} {kapi.3} acik", "{apartman.2} {gir.0}", "{ev.1} {kapi.3} acik",
           "{kapak.0} kirli", "{olcum.0} {tekrarla.1}", "{arac.0} {sokak.2}",
           "bu {ziyaret.2} {olcum.0} {tekrarla.0}"]
TUR = [("olagan", 0.36, 0.04), ("ariza", 0.26, 0.28),
       ("erisilemedi", 0.16, 0.15), ("kacak", 0.22, 0.82)]
BICIM = {k: v.split() for d in (AD, EYLEM) for k, v in d.items()}
SEYREK = [s.split() for s in NADIR.replace("\n", "|").split("|")]
AGIRLIK = [1 / (i + 1) ** 1.6 for i in range(len(SEYREK))]
AGIRLIK = [w / sum(AGIRLIK) for w in AGIRLIK]
KOKU = {f: k for k, fs in BICIM.items() for f in fs}
KOKU.update({f: fs[0] for fs in SEYREK for f in fs})
KOKU.update({w: w for w in NITELIK})
TASIYICI = ["ve", "ile", "bir", "bu", "ama", "icin"]
KOKU.update({w: w for w in TASIYICI})


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 ayrik(u, w):
    t = 0.0
    for i, x in enumerate(w):
        t += x
        if u < t:
            return i
    return len(w) - 1


def obek_yaz(sablon):
    p = []
    for s in sablon.split():
        if s.startswith("{"):
            kok, _, i = s[1:-1].partition(".")
            p.append(BICIM[kok][int(i)])
        else:
            p.append(s)
    return " ".join(p)


VERI = []
for i in range(NOT_SAYISI):
    r = uretec(TOHUM + i)
    t = TUR[ayrik(r(), [x[1] for x in TUR])]
    c = [obek_yaz(OBEK[t[0]][int(r() * 10)])]
    if r() < 0.55:
        c.append(obek_yaz(EK_OBEK[int(r() * 10)]))
    if r() < 0.30:
        c.append(obek_yaz(OBEK[t[0]][int(r() * 10)]))
    if r() < 0.22:
        f, nit = SEYREK[ayrik(r(), AGIRLIK)], NITELIK[int(r() * len(NITELIK))]
        c.append(f[2] + " kir bulundu" if r() < 0.34 else f[int(r() * 2)] + " " + nit)
    n = c[0]
    for x in c[1:]:
        n += (" ve " if r() < 0.22 else ", ") + x
    if r() < 0.52:
        n += ", okuma " + str(240 + int(r() * 1760))
    VERI.append({"no": 10001 + i, "not": n[0].upper() + n[1:] + ".",
                 "tur": t[0], "supheli": int(r() < t[2])})

EGT, AYR = VERI[:1200], VERI[1200:]
print(f"{len(VERI)} kurgu not, {len(BICIM) + len(SEYREK) + len(NITELIK)} kok, "
      f"supheli orani {sum(x['supheli'] for x in VERI) / len(VERI):.4f}")
print(VERI[3]["not"])
1800 kurgu not, 85 kok, supheli orani 0.2956
Olcum icin erisim saglandi, sayacin kapagi yeni, mandalda kir bulundu.

Sözcük Torbası ve Sözlük Boyu

Model bir kez yazılır ve bütün satırlarda aynı kalır. Öznitelikler seyrek verilir: bir notta on birkaç gövde bulunduğu için, sütun 96’ya çıksa da satır başına birkaç çarpma yapılır.

import math
from collections import Counter

EKLER = ["lari", "leri", "lar", "ler", "nin", "nun", "dan", "den", "tan", "ten",
         "dir", "tir", "dur", "da", "de", "ta", "te", "in", "un", "yi", "yu",
         "si", "su", "li", "lu", "di", "du", "ti", "tu", "i", "u", "a", "e"]


def govdele(b):
    for e in EKLER:
        if b.endswith(e) and len(b) - len(e) >= 3:
            return b[:-len(e)]
    return b


for x in VERI:  # nlp/01'in ucuncu karari: noktalama atma, kucuk harf, govdeleme, sayi katlama
    x["bel"] = [("<sayi>" if b.isdigit() else govdele(b))
                for b in (s.strip(",.").lower() for s in x["not"].split()) if b]


def egit(ozn, y, boyut, tur=120, adim=1.5):
    w = [0.0] * (boyut + 1)
    for _ in range(tur):
        g = [0.0] * (boyut + 1)
        for x, t in zip(ozn, y):
            z = w[boyut] + sum(w[i] * v for i, v in x)
            d = 1 / (1 + math.exp(-max(-30.0, min(30.0, z)))) - t
            for i, v in x:
                g[i] += d * v
            g[boyut] += d
        for i in range(boyut + 1):
            w[i] -= adim * g[i] / len(y)
    return w


def olc(w, ozn, y, boyut):
    d = p = 0
    for x, e in zip(ozn, y):
        k = int(w[boyut] + sum(w[i] * v for i, v in x) > 0)
        d, p = d + (k == e), p + (k == 1 and e == 1)
    return d / len(y), p / sum(y)


def kur(ad, yap, boyut):  # ilk cagri cizgiyi kurar
    ye, ya = [x["supheli"] for x in EGT], [x["supheli"] for x in AYR]
    w = egit([yap(x) for x in EGT], ye, boyut)
    de, _ = olc(w, [yap(x) for x in EGT], ye, boyut)
    da, dy = olc(w, [yap(x) for x in AYR], ya, boyut)
    if not CIZGI:
        CIZGI.append(da)
    print(f"{ad:<24} {boyut:>6} {de:>9.4f} {da:>9.4f} {dy:>10.4f} {da - CIZGI[0]:>+8.4f}")
    return da


ANAHTAR, CIZGI = ["muhur", "erisim", "arac"], []
ham = [[len(x["not"]), len(x["bel"])] for x in EGT]
ORT = [sum(h[i] for h in ham) / len(ham) for i in (0, 1)]
SAP = [math.sqrt(sum((h[i] - ORT[i]) ** 2 for h in ham) / len(ham)) for i in (0, 1)]


def elle(x):  # M27/K02'nin bes sayisi: iki bicim olcusu, uc anahtar sozcuk gostergesi
    o = [(0, (len(x["not"]) - ORT[0]) / SAP[0]), (1, (len(x["bel"]) - ORT[1]) / SAP[1])]
    for i, a in enumerate(ANAHTAR):
        o.append((2 + i, float(any(b.startswith(a) for b in x["bel"]))))
    return o


TABAN = sum(x["supheli"] == 0 for x in AYR) / len(AYR)
print(f"{'temsil':<24} {'sutun':>6} {'egitimde':>9} {'ayrilmis':>9} {'duyarlilik':>10}"
      f" {'cizgiden':>8}")
kur("elle sayilmis bes sayi", elle, 5)
print(f"{'en sik sinif':<24} {0:>6} {'':>9} {TABAN:>9.4f} {0.0:>10.4f}"
      f" {TABAN - CIZGI[0]:>+8.4f}")

SIK = Counter(b for x in EGT for b in x["bel"])
SIRA = sorted(SIK, key=lambda b: (-SIK[b], b))
BELGE = Counter(b for x in EGT for b in set(x["bel"]))
TASIYICI_G = {govdele(w) for w in TASIYICI}


def torba(terim, kip="gosterge"):
    d = {b: i for i, b in enumerate(terim)}
    ters = {b: math.log(len(EGT) / BELGE.get(b, 1)) for b in d}

    def yap(x):
        c = Counter(b for b in x["bel"] if b in d)
        if kip == "gosterge":
            return [(d[b], 1.0) for b in c]
        if kip == "sayim":
            return [(d[b], float(v)) for b, v in c.items()]
        u = math.sqrt(sum((v * ters[b]) ** 2 for b, v in c.items())) or 1.0
        return [(d[b], v * ters[b] / u) for b, v in c.items()]
    return yap


print()
for n in (8, 16, 32, 48, 64, 96):
    kur(f"sozcuk torbasi {n}", torba(SIRA[:n]), n)
temsil                    sutun  egitimde  ayrilmis duyarlilik cizgiden
elle sayilmis bes sayi        5    0.7608    0.7383     0.3408  +0.0000
en sik sinif                  0              0.7017     0.0000  -0.0367

sozcuk torbasi 8              8    0.7783    0.7667     0.3296  +0.0283
sozcuk torbasi 16            16    0.7908    0.7700     0.3911  +0.0317
sozcuk torbasi 32            32    0.8208    0.8067     0.5140  +0.0683
sozcuk torbasi 48            48    0.8300    0.8133     0.5363  +0.0750
sozcuk torbasi 64            64    0.8333    0.8217     0.5698  +0.0833
sozcuk torbasi 96            96    0.8350    0.8217     0.5698  +0.0833

Çizgi 0,7383’tür ve en sık sınıfı 0,0366 geçiyor. M27/K02’de aynı beş sayı bir karar ağacına 0,0317 katmıştı; iki sayının yakınlığı tesadüf değildir, çünkü katkının kaynağı her iki kurulumda da aynı üç anahtar göstergedir. Duyarlılık sütunu tabanın niçin okunması gerektiğini gösteriyor: en sık sınıf 0,7017 doğruluk verirken şüphelilerin hiçbirini bulmuyor.

Sözcük torbası çizgiyi 0,0833 geçiyor — elle sayılan beş sayının kattığının iki katından fazla. Sekiz sütun bile 0,0283 katıyor, yani en sık sekiz gövde elle seçilmiş beş göstergeye yakın iş görüyor. Katkı 64 sütunda doyuyor: 64 ile 96 arasında ayrılmış küme sayısı tam olarak aynı kalırken eğitim sayısı 0,8333’ten 0,8350’ye çıkıyor. Sütun eklemek eğitim sayısını her zaman artırır; bu bir ölçüm değil, tanımın gereğidir.

Ağırlıklandırma ve Tavan

Torbanın hücresine ne yazıldığı ayrı bir karardır: varlık göstergesi, ham sayım ya da sıklığın belgeler arası seyrekliğiyle ağırlıklandırılmış hâli.

kur("sayim agirligi", torba(SIRA, "sayim"), len(SIRA))
kur("ters belge sikligi", torba(SIRA, "agirlik"), len(SIRA))
SUZ = [b for b in SIRA if b not in TASIYICI_G]
kur("tasiyici sozcuk atilmis", torba(SUZ), len(SUZ))

TUR_ET = {}
for a, _, _ in TUR:
    p = [x["supheli"] for x in EGT if x["tur"] == a]
    TUR_ET[a] = int(sum(p) * 2 > len(p))
tavan = sum(TUR_ET[x["tur"]] == x["supheli"] for x in AYR) / len(AYR)
print(f"\n{'olay turunu bilen tavan':<24} {'':>6} {'':>9} {tavan:>9.4f} {'':>10}"
      f" {tavan - CIZGI[0]:>+8.4f}")
sayim agirligi               96    0.8333    0.8217     0.5698  +0.0833
ters belge sikligi           96    0.8150    0.8217     0.5363  +0.0833
tasiyici sozcuk atilmis      90    0.8292    0.8150     0.5419  +0.0767

olay turunu bilen tavan                      0.8250             +0.0867

Terim ağırlıklandırma bu derlemde hiçbir şey katmıyor: üç satır da 0,8217 veriyor. Nedeni metnin kendisindedir. Notlar kısadır ve bir gövde bir notta neredeyse hep bir kez geçer, bu yüzden ham sayım gösterge sütunundan ayrışmaz. Ters belge sıklığı ağırlığı sütunları yeniden ölçeklendirir ama sıralamayı bozmaz; doğruluk aynı kalırken duyarlılık 0,5698’den 0,5363’e düşüyor. Kattığı fark 0,0000’dır.

Taşıyıcı sözcük atmak 0,0067 kaybettiriyor. Altı taşıyıcı sözcüğün üçü bu kurguda belirli kalıpların işaretidir: ile yalnız olağan öbekte, ama yalnız arıza öbeğinde geçer. Taşıyıcı sözcük listesi dilden değil görevden okunur; genel bir liste burada bilgi atıyor.

Son satır kalan boşluğu kapatıyor. Olay türünü bilen bir yordam 0,8250 veriyor ve sözcük torbası 0,8217 ile bunun 0,0033 altında. Etiket yalnız türden üretildiği için metinden okunabilecek en yüksek sayı budur: daha iyi bir temsil bu kurguda 0,0033’ten fazlasını kazanamaz. Farkın kaynağı da böylece yazılabilir — model bütün satırlarda aynı, ölçüt ve ayrılmış pay aynı, fark temsilden gelir.

Özet

  • Alanın tabanı elle sayılmış beş sayıdır ve 0,7383 verir; en sık sınıf 0,7017’de kalır ve şüphelilerin hiçbirini bulmaz.
  • 96 gövdelik sözcük torbası 0,8217 verir ve çizgiyi 0,0833 geçer — elle sayılan beş sayının kattığının iki katından fazla. Model ile ölçüt sabit olduğu için farkın tamamı temsilden gelir.
  • Sözlük boyu 8’den 64’e katkı ekler ve orada doyar: 64 ile 96 arasındaki fark tam sıfırken eğitim sayısı 0,8333’ten 0,8350’ye çıkar.
  • Terim ağırlıklandırma 0,0000 katar; notlar kısa olduğu için sayım göstergeden ayrışmaz, ters belge sıklığı ağırlığı doğruluğu değil duyarlılığı oynatır (0,5698’den 0,5363’e). Taşıyıcı sözcük atmak 0,0067 kaybettirir, çünkü listedeki üç sözcük bu kurguda kalıp işaretidir.
  • Olay türünü bilen tavan 0,8250’dir; torba tavanın 0,0033 altındadır ve kalan boşluk metinde değildir.

Sonraki Adım

Sözcük torbası bir notu 96 sütuna çevirdi, ama sütunlar birbirine tümüyle yabancıdır: muhur ile kelepce sütunları, muhur ile <sayi> sütunları kadar uzaktır. Modelin öğrendiği tek şey her sütunun etiketle ilişkisidir ve bu ilişki her sütun için sıfırdan öğrenilir. Oysa notlarda muhur ile kelepce benzer sözcüklerin yanında geçiyor. Sonraki ders bunu kullanır: her gövde bir sayı yerine bir vektörle temsil edilir ve vektör bağlamdan öğrenilir. Ölçü, öğrenilen komşuluğun anlamlı çıkıp çıkmadığı ve vektör aritmetiğinin kaç durumda tuttuğudur.

İ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