---
title: 'Anomali Tespiti'
source: 'https://academia.sh/tr/kurslar/denetimsiz-ogrenme/anomali-tespiti'
course: 'Denetimsiz Öğrenme'
language: tr
updated: '2026-08-17T18:10:23+00:00'
license: 'CC BY-SA 4.0'
---

# 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.

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.** `anomali` ile `aykırı değer` ayrı 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

```python
# 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

```python
# 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

```python
# 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.
