Ders 10 / 11
Anomali Tespiti
Kurgu abone tablosunun 1.260 satırına bilerek yerleştirilmiş 63 anomali üzerinde işaretlemenin ölçülmesi: rastgele işaretleme yüzde 5'lik oranda 0,0488 kesinlik verirken tek sütuna göre işaretleme 0,3968, her sütuna tek tek bakan yordam 0,6190, dört bileşenle geri kurma hatası 0,4921 verir. Kesinlik sıralaması yanıltıcıdır — en yüksek kesinlikli üç işaretleyici hiçbir sütunda uca gitmeyen 24 çok değişkenli anomalinin sıfırını bulurken, en düşük kesinlikli olan on beşini bulur ve işaretleme oranı yüzde 10'a çıkınca yirmi dördünü de bulur. Oran yüzde 2'de üç işaretleyici 1,0000 kesinlik verir ve aynı anda 63 anomalinin yalnız 25'ini yakalar.
İçindekiler
Bu konunun ilk üç dersi aynı işi üç ayrı yoldan yaptı: noktalar daha az sayıya indirildi ve her seferinde ne kaybedildiği ölçüldü — geri kurma hatası, rankın bedeli, komşuluk korunma oranı. Üç ölçü de bütün noktalar birlikte ele alınarak okundu. Tek başına duran bir noktanın ne olduğu, hatta böyle bir noktanın var olup olmadığı sorulmadı.
Anomali tespiti bu soruyu sorar ve etiketsiz bir problem olarak sorar: hiçbir sütun bir satırın anomali olduğunu söylemez, dolayısıyla “anomali” tanımı yöntemin kendisinden gelir. Böyle bir kurulumda hangi işaretlemenin iyi olduğunu söylemenin tek yolu, işaretlenenlerin kaçının gerçek olduğunu sayabilmektir. Bu ders bunu, anomalileri kurgu kümeye bilerek yerleştirerek yapar.
- BA31. Küme M27/K01–K03’ün kurgu abone tablosudur, tohum 20260218, 1.260 satır ve beş sayısal sütun. Etiket sütunu bu kursta okunmaz ve burada da hesaplanmaz.
- BA32. Anomaliler tabloya bilerek yerleştirilmiştir. Hangi satırın yerleştirildiği yalnız ölçüm için bilinir; hiçbir işaretleyici bu listeyi görmez. Kurgunun yeri burasıdır: gerçek bir kümede bu liste yoktur ve bu dersin sayıları orada hesaplanamaz.
- BA33.
anomaliileaykırı değerayrı tutulur. Aykırı değer M26/K03’ün terimidir ve bir sütundaki tek bir değerin uçta durmasını anlatır. Anomali burada satırın bütününün kümeye uymamasıdır; hiçbir değeri uçta olmayan bir satır anomali olabilir. - BA34. Taban çizgisi M26/K03’ün çeyrekler açıklığı, çit ve standart puan yordamıdır. Yordam orada kuruldu, burada tekrarlanmaz; sabit sayıda satır işaretlemek gerektiği için çit yerine aynı yordamın sürekli biçimi, standart puanın büyüklüğü, sıralama ölçütü olarak çağrılır.
- BA35. İşaretleme oranı bir ayar değişkenidir: kaç satırın anomali sayılacağı veriden çıkmaz. Süpürülür ve her oranın sayısı ayrı yazılır.
Yerleştirilmiş Anomali
# ORTAK — KURGUDUR. M27/K01-K03'un abone tablosu ayni tohumla yeniden kurulur; # etiket sutunu bu kursta hic okunmaz. Anomaliler tabloya BILEREK yerlestirilir. import math TOHUM, HAM, M32 = 20260218, 1400, 0xFFFFFFFF BOLGE = [("kuzey", 0.28, 21), ("guney", 0.22, 17), ("dogu", 0.18, 26), ("bati", 0.14, 14), ("merkez", 0.18, 23)] 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 ABONE, VERI = [], [] for i in range(HAM): r = uretec(TOHUM + i) b = BOLGE[ayrik(r(), [x[1] for x in BOLGE])] hane = 1 + ayrik(r(), [0.06, 0.24, 0.30, 0.24, 0.11, 0.05]) memnun = 1 + ayrik(r(), [0.08, 0.14, 0.27, 0.34, 0.17]) if r() >= 0.046: ABONE.append({"no": 10001 + i, "bolge": b, "hane": hane, "memnuniyet": memnun}) for k in ABONE: r, v = uretec(TOHUM + 7000 + k["no"]), [] for d in range(ayrik(r(), [0.05, 0.12, 0.21, 0.62])): v.append(0.0 if r() < 0.038 else math.floor( k["bolge"][2] * math.exp((r() + r() + r() - 1.5) * 0.62) * (1 - d * 0.05) * 100 + 0.5) / 100) r() if v: VERI.append({"no": k["no"], "hane": k["hane"], "memnuniyet": k["memnuniyet"], "donem": len(v), "ort_tuketim": round(sum(v) / len(v), 2), "oynaklik": round(max(v) - min(v), 2)}) # Yerlestirme. Uc tur: A ve B tek sutunda uca tasinir, C hicbir sutunda uca # gitmeden sutunlar arasi iliskiyi bozar (uc okuma, aralarinda neredeyse fark yok). r, alinan, YER = uretec(TOHUM + 31000), set(), {} def sec(kosul, adet): s = [i for i in range(len(VERI)) if kosul(VERI[i]) and i not in alinan] for i in range(len(s) - 1, 0, -1): j = int(r() * (i + 1)) s[i], s[j] = s[j], s[i] alinan.update(s[:adet]) return s[:adet] for i in sec(lambda x: 12 <= x["ort_tuketim"] <= 30 and x["donem"] >= 2, 24): VERI[i]["ort_tuketim"], YER[i] = round(VERI[i]["ort_tuketim"] * 5.0, 2), "A" for i in sec(lambda x: x["donem"] == 3 and 12 <= x["oynaklik"] <= 20, 15): VERI[i]["oynaklik"], YER[i] = round(VERI[i]["oynaklik"] * 5.0, 2), "B" for i in sec(lambda x: x["donem"] == 3 and 22 <= x["ort_tuketim"] <= 33, 24): VERI[i]["oynaklik"], YER[i] = round(VERI[i]["ort_tuketim"] * 0.02, 2), "C" ALAN = ["ort_tuketim", "oynaklik", "hane", "memnuniyet", "donem"] n, p = len(VERI), len(ALAN) ORT = [sum(x[a] for x in VERI) / n for a in ALAN] SAP = [math.sqrt(sum((x[a] - ORT[j]) ** 2 for x in VERI) / n) for j, a in enumerate(ALAN)] P = [[(x[a] - ORT[j]) / SAP[j] for j, a in enumerate(ALAN)] for x in VERI] print(f"kurgu tablo {n} satir, {p} sutun; yerlestirilen anomali {len(YER)} " f"({len(YER) / n:.4f})") for t, ad in (("A", "olcek kaymasi"), ("B", "oynaklik sicramasi"), ("C", "duragan yuksek okuma")): g = [i for i in YER if YER[i] == t] print(f" tur {t} {ad:<21} {len(g):>3} satir " f"ort_tuketim {min(VERI[i]['ort_tuketim'] for i in g):>6.2f}-" f"{max(VERI[i]['ort_tuketim'] for i in g):<6.2f} " f"oynaklik {min(VERI[i]['oynaklik'] for i in g):>5.2f}-" f"{max(VERI[i]['oynaklik'] for i in g):.2f}") print(f" yerlestirilmemis satirlarda ort_tuketim en cok " f"{max(VERI[i]['ort_tuketim'] for i in range(n) if i not in YER):.2f}, " f"oynaklik en cok " f"{max(VERI[i]['oynaklik'] for i in range(n) if i not in YER):.2f}")
kurgu tablo 1260 satir, 5 sutun; yerlestirilen anomali 63 (0.0500) tur A olcek kaymasi 24 satir ort_tuketim 62.45-144.40 oynaklik 1.71-23.22 tur B oynaklik sicramasi 15 satir ort_tuketim 9.50-35.29 oynaklik 61.10-98.55 tur C duragan yuksek okuma 24 satir ort_tuketim 22.09-31.68 oynaklik 0.44-0.63 yerlestirilmemis satirlarda ort_tuketim en cok 43.48, oynaklik en cok 51.15
Üç tür arasındaki fark son satırda duruyor. A türünün tüketimi 62,45 ile 144,40 arasında, yerleştirilmemişlerin en büyüğü 43,48; B türünün oynaklığı 61,10 ile 98,55, yerleştirilmemişlerin en büyüğü 51,15. İkisi de bir sütunda uçta duruyor ve M26/K03’ün terimiyle o sütunda birer aykırı değer taşıyor.
C türü hiçbir sütunda uca gitmiyor. Tüketimi 22,09 ile 31,68 arasında, kümenin üst çeyreğinde ama sınırın hayli içinde. Oynaklığı 0,44 ile 0,63 arasında ve kümede oynaklığı 1’in altında 187 satır var, çünkü tek okuması olan abonede oynaklık tanımı gereği sıfırdır. Anomali değerlerde değil, değerlerin birlikteliğinde: üç dönemde okunmuş, tüketimi yüksek ve üç okuması arasında neredeyse hiç fark olmayan bir abone.
Beş İşaretleyici, Üç Taban
# Bes isaretleyici. Ilk ucu taban cizgisi, son ikisi cok degiskenli. def bilesenler(k, tohum): # Esdegisim dizeyi ve ilk k ozvektor: guc yinelemesi ve ayirma. # Bilesenin kendisi bu konunun ilk iki dersinde kuruldu, burada girdidir. C = [[sum(P[i][a] * P[i][b] for i in range(n)) / n for b in range(p)] for a in range(p)] rr, cikan = uretec(tohum), [] for _ in range(k): v = [rr() - 0.5 for _ in range(p)] for _ in range(300): w = [sum(C[a][b] * v[b] for b in range(p)) for a in range(p)] u = math.sqrt(sum(x * x for x in w)) or 1.0 v = [x / u for x in w] lam = sum(v[a] * sum(C[a][b] * v[b] for b in range(p)) for a in range(p)) cikan.append(v) C = [[C[a][b] - lam * v[a] * v[b] for b in range(p)] for a in range(p)] return cikan def geri_kurma(k): V = bilesenler(k, TOHUM + 31500) s = [] for i in range(n): pr = [sum(P[i][a] * v[a] for a in range(p)) for v in V] gk = [sum(pr[j] * V[j][a] for j in range(k)) for a in range(p)] s.append(math.sqrt(sum((P[i][a] - gk[a]) ** 2 for a in range(p)))) return s UZAK = [] for i in range(n): d = sorted(sum((P[i][a] - P[j][a]) ** 2 for a in range(p)) for j in range(n) if j != i) UZAK.append(math.sqrt(d[9])) # 10. komsunun uzakligi SKOR = [("rastgele", "rastgele isaretleme", None), ("tek sutun", "tek sutuna gore: ort_tuketim", [abs(P[i][0]) for i in range(n)]), ("sutun sutun", "her sutuna tek tek: en buyuk standart puan", [max(abs(P[i][a]) for a in range(p)) for i in range(n)]), ("komsu", "10. komsunun uzakligi", UZAK), ("geri kurma 2", "iki bilesenle geri kurma hatasi", geri_kurma(2)), ("geri kurma 4", "dort bilesenle geri kurma hatasi", geri_kurma(4))] def isaretle(skor, m, tohum=0): if skor is None: rr, s = uretec(tohum), list(range(n)) for i in range(n - 1, 0, -1): j = int(rr() * (i + 1)) s[i], s[j] = s[j], s[i] return s[:m] return sorted(range(n), key=lambda i: (-skor[i], i))[:m] M = 63 print(f"isaretleme orani 0,0500 -> {M} satir isaretleniyor; yerlestirilen 63\n") print(f"{'isaretleyici':<42} {'gercek':>7} {'kesinlik':>9} " f"{'A':>4} {'B':>4} {'C':>4}") for _, ad, skor in SKOR: if skor is None: d = [sum(1 for i in isaretle(None, M, TOHUM + 32000 + t) if i in YER) for t in range(200)] g = sum(d) / len(d) print(f"{ad:<42} {g:>7.2f} {g / M:>9.4f} {'':>4} {'':>4} {'':>4}") continue s = isaretle(skor, M) say = {t: sum(1 for i in s if YER.get(i) == t) for t in "ABC"} print(f"{ad:<42} {sum(say.values()):>7} {sum(say.values()) / M:>9.4f} " f"{say['A']:>4} {say['B']:>4} {say['C']:>4}")
isaretleme orani 0,0500 -> 63 satir isaretleniyor; yerlestirilen 63 isaretleyici gercek kesinlik A B C rastgele isaretleme 3.08 0.0488 tek sutuna gore: ort_tuketim 25 0.3968 24 1 0 her sutuna tek tek: en buyuk standart puan 39 0.6190 24 15 0 10. komsunun uzakligi 39 0.6190 24 15 0 iki bilesenle geri kurma hatasi 40 0.6349 23 15 2 dort bilesenle geri kurma hatasi 31 0.4921 1 15 15
Taban çizgisi ilk satırda: 63 satır rastgele işaretlendiğinde 200 çekilişin ortalaması 3,08 gerçek anomali, kesinlik 0,0488 — işaretleme oranının kendisi. Bu sayının yanında kalan hiçbir işaretleyici bir şey bulmuş sayılmaz.
İkinci taban tek bir sütuna bakıyor ve 0,3968 veriyor — rastgelenin sekiz katı. Ne bulduğu üçüncü sütunda: A türünün 24’ünü de yakalamış, B türünden yalnız birini, C türünden hiçbirini. Üçüncü taban aynı yordamı beş sütuna tek tek uyguluyor ve en büyük standart puana göre sıralıyor; kesinlik 0,6190’a çıkıyor ve eksik kalan B türü de tamamlanıyor. C türü hâlâ sıfır.
Son üç satır çok değişkenli. Onuncu komşunun uzaklığı sütun sütun bakan tabanla aynı sayıyı veriyor: 39 gerçek, aynı dağılım. İki bileşenle geri kurma hatası biraz daha iyi, 0,6349. Dört bileşenle geri kurma hatası ise kesinlikte hepsinden geride, 0,4921 — ve C türünün on beşini tek başına buluyor.
Kesinlik sıralaması bu tabloda yanıltıcıdır. En yüksek kesinlikli üç işaretleyici, hiçbir sütunda uca gitmeyen 24 anomalinin sıfırını görüyor; en düşük kesinlikli olan on beşini görüyor. Fark yöntemin duyarlılığından değil, neye baktığından geliyor. A türü kümenin en güçlü bileşeni boyunca uzağa gitmiştir ve dört bileşen onu neredeyse tam geri kurar, artığı sıfıra yakındır. C türü ise hiçbir bileşen boyunca uzakta değildir; bileşenlerin dışında kalan yönde durur, çünkü bozduğu şey bir değer değil, dönem sayısı ile oynaklık ve tüketim arasındaki ilişkidir. Aynı nedenle dört bileşenle geri kurma A türünü kaçırır: aradığı artık, A’nın hiç ürettiği bir artık değildir.
İşaretleme Oranı Süpürülünce
# Isaretleme orani bir ayar degiskenidir: kac satirin anomali sayilacagi # veriden degil karardan cikar. Bes oran suprulur. ORANLAR = [0.02, 0.05, 0.10, 0.15, 0.20] BASLIK = f"{'oran':>5} {'isaret':>7} " + " ".join(f"{a:>13}" for a, _, _ in SKOR) print("kesinlik: isaretlenenin kaci yerlestirilmis anomali\n" + BASLIK) for o in ORANLAR: m, satir = int(round(o * n)), [] for _, _, skor in SKOR: if skor is None: d = [sum(1 for i in isaretle(None, m, TOHUM + 32000 + t) if i in YER) for t in range(200)] satir.append(sum(d) / len(d) / m) else: satir.append(sum(1 for i in isaretle(skor, m) if i in YER) / m) print(f"{o:>5.2f} {m:>7} " + " ".join(f"{x:>13.4f}" for x in satir)) print("\nyakalama: 63 anomalinin kaci / bunlarin 24 C turunun kaci\n" + BASLIK) for o in ORANLAR: m, satir = int(round(o * n)), [] for _, _, skor in SKOR: s = isaretle(skor, m, TOHUM + 32000) if skor is None else isaretle(skor, m) satir.append(f"{sum(1 for i in s if i in YER)}/" f"{sum(1 for i in s if YER.get(i) == 'C')}") print(f"{o:>5.2f} {m:>7} " + " ".join(f"{x:>13}" for x in satir))
kesinlik: isaretlenenin kaci yerlestirilmis anomali oran isaret rastgele tek sutun sutun sutun komsu geri kurma 2 geri kurma 4 0.02 25 0.0506 0.9600 1.0000 1.0000 1.0000 0.6000 0.05 63 0.0488 0.3968 0.6190 0.6190 0.6349 0.4921 0.10 126 0.0496 0.2143 0.3175 0.3175 0.3333 0.3333 0.15 189 0.0501 0.1534 0.2116 0.2169 0.2275 0.2328 0.20 252 0.0501 0.1230 0.1587 0.1706 0.1706 0.1865 yakalama: 63 anomalinin kaci / bunlarin 24 C turunun kaci oran isaret rastgele tek sutun sutun sutun komsu geri kurma 2 geri kurma 4 0.02 25 1/1 24/0 25/0 25/0 25/0 15/0 0.05 63 2/1 25/0 39/0 39/0 40/2 31/15 0.10 126 3/1 27/0 40/1 40/1 42/3 42/24 0.15 189 6/3 29/1 40/1 41/2 43/4 44/24 0.20 252 7/3 31/2 40/1 43/4 43/4 47/24
İlk satır kesinliğin ne kadar kolay büyütüldüğünü gösteriyor. Oran yüzde 2’ye çekilince üç işaretleyici 1,0000 veriyor: işaretlenen 25 satırın 25’i de gerçek. İkinci tabloda aynı satır tersini söylüyor — 63 anomalinin yalnız 25’i bulunmuş, C türünden hiçbiri. Kusursuz kesinlik dar bir eşiğin ürünüdür ve 38 anomaliyi hiç görmemekle satın alınmıştır.
Oran büyüdükçe her işaretleyicinin kesinliği düşüyor, çünkü işaretlenen satır sayısı yerleştirilen anomali sayısını geçiyor ve fazlası zorunlu olarak yanlış oluyor. Tek sabit kalan rastgele işaretlemedir: 0,0506, 0,0488, 0,0496, 0,0501, 0,0501. Taban çizgisi orandan bağımsızdır ve kesinlik ancak bu sayının yanında okunabilir.
İkinci tablo tek değişkenli yordamların sınırını sayıyor. Tek sütuna göre işaretleme yakalanan anomaliyi yüzde 20’lik oranda bile ancak 24’ten 31’e taşıyor; sütun sütun bakan yordam 40’ta duruyor ve yüzde 10’dan sonra hiç ilerlemiyor. Bu iki yordamda oranı büyütmek görülmeyeni göstermiyor, yalnız yanlış işaretlenen satırı çoğaltıyor. Dört bileşenle geri kurma hatası ise yüzde 10’da C türünün 24’ünü de bulmuş oluyor.
Yüzde 20 oranında en iyi kesinlik 0,1865’tir: 252 satır işaretlenmiş, 47’si gerçek. Geri kalan 205 satır incelenmek üzere ayrılmış ve hiçbirinde yerleştirilmiş bir anomali yok. İşaretleme oranını seçmek, bu 205 satırın bedelini kabul etmektir; ölçüt oranı seçmez, oran ölçütün sayısını belirler.
Özet
- Kurgu tabloya bilerek yerleştirilen 63 anomalinin 24’ü hiçbir sütunda uca gitmez: anomali değerlerde değil, değerlerin birlikteliğindedir.
- Yüzde 5’lik işaretleme oranında taban 0,0488’dir; tek sütuna göre işaretleme 0,3968, her sütuna tek tek bakan yordam 0,6190, onuncu komşunun uzaklığı 0,6190, dört bileşenle geri kurma hatası 0,4921 verir.
- Kesinlik sıralaması yanıltıcıdır: en yüksek kesinlikli üç işaretleyici çok değişkenli 24 anomalinin sıfırını, en düşük kesinlikli olan on beşini bulur; yüzde 10 oranında yirmi dördünü de bulur.
- Oran yüzde 2’ye çekilince üç işaretleyici 1,0000 kesinlik verir ve aynı anda 63 anomalinin yalnız 25’ini yakalar; kusursuz kesinlik dar eşiğin ürünüdür.
- Rastgele işaretlemenin kesinliği bütün oranlarda 0,0488 ile 0,0506 arasında kalır; taban orandan bağımsızdır ve öbür sayılar ancak onun yanında okunur.
Sonraki Adım
Bu derste satır beş sayısal sütunla ele alındı ve bir noktanın tek başına durup durmadığı ölçüldü. Abone kayıtlarının sayı olmayan bir yanı daha var: hangi olayların birlikte geçtiği. İki olayın aynı abonede birlikte görülmesi bir kural mıdır, yoksa ikisinin ayrı ayrı ne kadar sık olduğuyla zaten açıklanabilir mi. Sonraki ders birliktelik kurallarını kurar, yüksek güvenli kuralların kaçının yalnız sık öğeden geldiğini sayar ve tabanı rastgele eşleşmenin ürettiği destekten okur.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.