Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Anomaliya turlari
- 2.2. Isolation Forest
- 2.3. LOF va mahalliy zichlik
- 2.4. One-Class SVM
- 2.5. Zichlik va qayta tiklash
- 2.6. contamination va baholash
- 2.7. Tuzoqlar
- 2.8. Kam, xilma-xil, yorliqsiz
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — To'rt usulni taqqoslash
- Misol 2 — Isolation Forest ichkarisi
- Misol 3 — Zichlik va qayta tiklash
- Misol 4 — Tranzaksiyalar: kontekstual anomaliya
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
16.10-dars: Anomaliya aniqlash
16-QISM — NAZORATSIZ O'RGANISH · 10-dars
1. Kirish va motivatsiya
Firibgar tranzaksiya, ishdan chiqayotgan uskuna, tarmoq hujumi, ma'lumot bazasidagi buzilgan yozuv — bularning hammasi anomaliya: qolganlardan tubdan farq qiladigan kuzatuvlar. Ularni topish nazoratsiz o'rganishning eng amaliy qo'llanilishi.
Nima uchun bu klassifikatsiya emas? Uchta sabab: anomaliyalar kam (0.1-2%), ular xilma-xil (har biri o'zicha g'alati) va eng muhimi — yorliq yo'q yoki juda kech keladi. Firibgarlik uch oydan keyin ma'lum bo'ladi, model esa bugun kerak.
Bu darsda: anomaliya turlari, Isolation Forest (izolyatsiya g'oyasi), LOF (mahalliy zichlik), One-Class SVM, zichlikka asoslangan usullar (GMM, PCA qayta tiklash xatosi), contamination ni tanlash va yorliqsiz baholash.
Real vaziyat. To'lov tizimida firibgarlikni aniqlash uchun qoidalar yozilgan edi: "summa > 5 mln" va "kechasi". Isolation Forest esa kombinatsiyalarni topdi — kichik summa, lekin g'ayrioddiy vaqt va yangi qurilma. Qoidalar 41% firibgarlikni topgan bo'lsa, model 78% ini topdi, noto'g'ri ogohlantirishlar soni esa o'zgarmadi.
Bu darsda anomaliya aniqlashni o'rganamiz.
Bu darsda:
- Anomaliya turlari
- Isolation Forest
- LOF va mahalliy zichlik
- One-Class SVM
- Zichlik va qayta tiklash
- contamination va baholash
- Tuzoqlar
- Amaliy: tranzaksiyalar
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Anomaliya turlari
1. NUQTAVIY (point): alohida kuzatuv g'ayrioddiy
misol: 50 mln so'mlik tranzaksiya (odatda 200 ming)
eng ko'p uchraydigan tur
2. KONTEKSTUAL (contextual): kontekstda g'ayrioddiy
misol: yozda 40 daraja - normal; qishda 40 daraja - anomaliya
kontekst belgilarini modelga qo'shish kerak
3. JAMOAVIY (collective): alohida normal, birga g'ayrioddiy
misol: 100 ta kichik tranzaksiya bir daqiqada
agregatsiya va vaqt oynalari kerak
BUNDAN TASHQARI:
novelty detection - toza ma'lumotda o'qitib, YANGI turdagi nuqtani topish
outlier detection - ma'lumotning o'zida anomaliya bor deb faraz qilishKontekstual va jamoaviy anomaliyalar belgi muhandisligini talab qiladi: algoritm o'zi kontekstni bilmaydi. "Oxirgi 1 soatdagi tranzaksiyalar soni" kabi belgilar ularni nuqtaviy anomaliyaga aylantiradi.
2.2. Isolation Forest
G'OYA: anomaliyani IZOLYATSIYA qilish oson
tasodifiy belgi va tasodifiy chegara bilan ma'lumotni bo'lamiz
anomaliya kam bo'linishdan keyin ajraladi (daraxtda SAYOZ)
normal nuqta ko'p bo'linish talab qiladi (CHUQUR)
ball = o'rtacha yo'l uzunligiga asoslangan (0..1, katta = anomaliyaroq)
AFZALLIKLARI:
+ masshtablash KERAK EMAS (daraxtga asoslangan)
+ chiziqli murakkablik, katta ma'lumotda tez
+ yuqori o'lchamda yaxshi ishlaydi
+ predict va decision_function bor
KAMCHILIK: mahalliy anomaliyalarni (zich klaster chetidagi) yomon topadiMasshtablash kerak emasligi — Isolation Forest ning katta amaliy afzalligi: u aralash birliklardagi ma'lumotda to'g'ridan-to'g'ri ishlaydi va odatiy birinchi tanlov bo'ladi.
2.3. LOF va mahalliy zichlik
LOF (Local Outlier Factor): nuqtaning zichligini QO'SHNILARINIKI bilan taqqoslaydi
LOF ~ 1 - qo'shnilar bilan bir xil zichlikda (normal)
LOF >> 1 - qo'shnilaridan siyrakroq joyda (anomaliya)
NEGA MAHALLIY: global zichlik chalg'itishi mumkin
zich klaster chetidagi nuqta global jihatdan normal, mahalliy jihatdan anomaliya
sklearn:
LocalOutlierFactor(n_neighbors=20) # fit_predict, novelty=False
LocalOutlierFactor(n_neighbors=20, novelty=True) # predict bor, fit da anomaliya yo'q
MASSHTABLASH MAJBURIY (masofaga asoslangan) novelty=False (standart) da predict yo'q — faqat fit_predict. Yangi nuqtalarni baholash kerak bo'lsa, novelty=True qo'ying va toza ma'lumotda o'qiting.
2.4. One-Class SVM
G'OYA: ma'lumotni o'rab oladigan eng kichik chegarani topish 14.5-bob
nu - anomaliyalar ulushining yuqori chegarasi (0..1)
gamma - RBF yadrosi kengligi
kernel - odatda "rbf"
AFZALLIK: moslashuvchan, murakkab shakllarni o'rab oladi
KAMCHILIK:
- O(n^2) .. O(n^3) - katta ma'lumotda sekin
- gamma va nu ga juda sezgir
- masshtablash majburiy
SGDOneClassSVM - chiziqli yaqinlashish, katta ma'lumot uchun tezOne-Class SVM parametrlarga juda sezgir va sekin — amalda u Isolation Forest va LOF dan kamroq ishlatiladi. Uni kichik, toza va murakkab shaklli ma'lumotlarda sinab ko'ring.
2.5. Zichlik va qayta tiklash
# 1. GMM zichligi (16.6)
g = GaussianMixture(n_components=5).fit(Xs)
ball = -g.score_samples(Xs) # past zichlik -> anomaliya
# 2. PCA qayta tiklash xatosi
p = PCA(n_components=10).fit(Xs)
xato = ((Xs - p.inverse_transform(p.transform(Xs))) ** 2).sum(axis=1)
# 3. EllipticEnvelope - Gauss taxmini, Mahalanobis masofasi
EllipticEnvelope(contamination=0.02, support_fraction=0.9)
# 4. KNN masofasi - k-chi qo'shnigacha masofaPCA qayta tiklash xatosi — sodda va samarali usul: agar nuqta asosiy komponentlar bilan yomon tiklansa, u umumiy tuzilmaga mos kelmaydi. Bu autoencoder asosidagi zamonaviy usullarning chiziqli ko'rinishi.
2.6. contamination va baholash
contamination - kutilayotgan anomaliyalar ulushi
"auto" (Isolation Forest) yoki aniq son (0.01, 0.05)
faqat CHEGARAni belgilaydi, ballarni emas
-> decision_function / score_samples ballari contamination ga bog'liq emas
-> chegarani keyin ham o'zgartirish mumkin
BAHOLASH (yorliqsiz):
1. ballar taqsimoti - aniq "dum" bormi
2. eng yuqori ballilarni QO'LDA ko'rib chiqish
3. turli usullar KELISHUVI (bir xil nuqtalarni belgilaydimi)
4. barqarorlik (bootstrap)
BAHOLASH (ozgina yorliq bo'lsa):
ROC AUC, PR AUC 14.9-bob - nomutanosiblik tufayli PR AUC afzalroq
precision@k - eng yuqori k ta orasida nechtasi haqiqiy precision@k — amaliy eng foydali metrika: tekshiruvchilar kuniga 50 ta hodisani ko'ra oladi, demak muhimi "eng yuqori 50 ta orasida nechtasi haqiqiy" degan savol.
2.7. Tuzoqlar
Asosiy tuzoqlar: LOF va One-Class SVM ni masshtablamasdan ishlatish; contamination ni haqiqiy ulushdan katta qo'yish; LocalOutlierFactor da novelty ni unutish; anomaliyalarni avtomatik o'chirish (ular eng qimmatli ma'lumot bo'lishi mumkin); kontekstual anomaliyani belgi qo'shmasdan topishga urinish; accuracy bilan baholash (99% anomaliyasiz ham chiqadi); bitta usulga tayanish; yorliq bo'lsa ham nazoratsiz usulda qolish.
2.8. Kam, xilma-xil, yorliqsiz
Anomaliya aniqlash kam uchraydigan, xilma-xil va ko'pincha yorliqsiz hodisalarni topadi. Isolation Forest — odatiy birinchi tanlov (masshtablash kerak emas, tez, yuqori o'lchamda ishlaydi), LOF mahalliy zichlikni ko'radi, One-Class SVM moslashuvchan lekin sekin, PCA qayta tiklash xatosi va GMM zichligi esa sodda muqobillar. contamination faqat chegarani belgilaydi. Baholashda PR AUC va precision@k ishlating. Keyingi dars — qo'llanilishi.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.covariance import EllipticEnvelope
from sklearn.decomposition import PCA
from sklearn.ensemble import IsolationForest
from sklearn.neighbors import LocalOutlierFactor
from sklearn.svm import OneClassSVM
izo = IsolationForest(contamination=0.02, n_estimators=200,
random_state=0, n_jobs=-1).fit(X) # masshtablash shart emas
izo.predict(X) # -1 = anomaliya
-izo.score_samples(X) # katta = anomaliyaroq
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.02)
yorliq = lof.fit_predict(Xs) # masshtablang!
-lof.negative_outlier_factor_
LocalOutlierFactor(n_neighbors=20, novelty=True) # predict uchun
OneClassSVM(kernel="rbf", nu=0.02, gamma="scale")
EllipticEnvelope(contamination=0.02, support_fraction=0.9)
QOIDA: IF dan boshla · LOF/SVM uchun masshtabla · PR AUC bilan bahola ·
anomaliyalarni ko'rib chiqAnomaliya xulosasi
Turlari: nuqtaviy, kontekstual, jamoaviy
IsolationForest: izolyatsiya, masshtabsiz, tez - birinchi tanlov
LOF: mahalliy zichlik; OneClassSVM: moslashuvchan lekin sekin
contamination faqat chegara; baholash PR AUC va precision@k4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — To'rt usulni taqqoslash
"""Isolation Forest, LOF, One-Class SVM va EllipticEnvelope (real sklearn)."""
import numpy as np
from sklearn.covariance import EllipticEnvelope
from sklearn.datasets import make_blobs, make_moons
from sklearn.ensemble import IsolationForest
from sklearn.metrics import average_precision_score, roc_auc_score
from sklearn.neighbors import LocalOutlierFactor
from sklearn.preprocessing import StandardScaler
from sklearn.svm import OneClassSVM
def global_anomaliya(seed: int = 0, n: int = 1000, ulush: float = 0.03):
rng = np.random.default_rng(seed)
X, _ = make_blobs(n_samples=n, centers=3, cluster_std=0.8,
random_state=seed)
k = int(n * ulush)
anomaliya = rng.uniform(X.min() - 6, X.max() + 6, (k, 2))
return (np.vstack([X, anomaliya]),
np.concatenate([np.zeros(n), np.ones(k)]).astype(int))
def mahalliy_anomaliya(seed: int = 0):
"""Zich klaster chetidagi nuqtalar - global jihatdan normal."""
rng = np.random.default_rng(seed)
zich = rng.normal([0, 0], 0.3, (600, 2))
siyrak = rng.normal([5, 5], 1.5, (400, 2))
# zich klaster chetidagi anomaliyalar
burchak = rng.uniform(0, 2 * np.pi, 25)
chekka = np.column_stack([1.3 * np.cos(burchak), 1.3 * np.sin(burchak)])
X = np.vstack([zich, siyrak, chekka])
y = np.concatenate([np.zeros(1000), np.ones(25)]).astype(int)
return X, y
def egri_anomaliya(seed: int = 0):
X, _ = make_moons(n_samples=800, noise=0.05, random_state=seed)
rng = np.random.default_rng(seed)
anomaliya = rng.uniform(-1.5, 2.5, (25, 2))
return (np.vstack([X, anomaliya]),
np.concatenate([np.zeros(800), np.ones(25)]).astype(int))
def main() -> None:
vazifalar = {
"global": global_anomaliya(),
"mahalliy": mahalliy_anomaliya(),
"egri shakl": egri_anomaliya(),
}
print("=== 1. ROC AUC bo'yicha ===")
print(f" {'vazifa':<12} {'IsoForest':>11} {'LOF':>9} {'OC-SVM':>9} "
f"{'Elliptic':>10}")
for nom, (X, y) in vazifalar.items():
Xs = StandardScaler().fit_transform(X)
ballar = {}
ballar["IsoForest"] = -IsolationForest(
contamination=0.03, n_estimators=200, random_state=0,
n_jobs=1).fit(X).score_samples(X)
lof = LocalOutlierFactor(n_neighbors=20)
lof.fit_predict(Xs)
ballar["LOF"] = -lof.negative_outlier_factor_
ballar["OC-SVM"] = -OneClassSVM(nu=0.03, gamma="scale").fit(
Xs).score_samples(Xs)
ballar["Elliptic"] = -EllipticEnvelope(
contamination=0.03, support_fraction=0.9,
random_state=0).fit(Xs).score_samples(Xs)
print(f" {nom:<12} " + "".join(
f"{roc_auc_score(y, ballar[k]):>11.4f}" if k == "IsoForest"
else f"{roc_auc_score(y, ballar[k]):>{9 if k != 'Elliptic' else 10}.4f}"
for k in ["IsoForest", "LOF", "OC-SVM", "Elliptic"]))
print("\n=== 2. PR AUC (nomutanosiblikda ishonchliroq) ===")
print(f" {'vazifa':<12} {'musbat %':>10} {'IsoForest':>11} {'LOF':>9}")
for nom, (X, y) in vazifalar.items():
Xs = StandardScaler().fit_transform(X)
b1 = -IsolationForest(contamination=0.03, n_estimators=200,
random_state=0, n_jobs=1).fit(X).score_samples(X)
lof = LocalOutlierFactor(n_neighbors=20)
lof.fit_predict(Xs)
b2 = -lof.negative_outlier_factor_
print(f" {nom:<12} {y.mean():>9.2%} "
f"{average_precision_score(y, b1):>11.4f} "
f"{average_precision_score(y, b2):>9.4f}")
print("\n=== 3. Mahalliy anomaliyada LOF ustunligi ===")
X, y = mahalliy_anomaliya()
Xs = StandardScaler().fit_transform(X)
izo_ball = -IsolationForest(contamination=0.025, n_estimators=200,
random_state=0, n_jobs=1).fit(X).score_samples(X)
lof = LocalOutlierFactor(n_neighbors=20)
lof.fit_predict(Xs)
lof_ball = -lof.negative_outlier_factor_
print(f" {'k':>5} {'IsoForest precision@k':>23} {'LOF precision@k':>18}")
for k in [10, 25, 50, 100]:
i1 = np.argsort(-izo_ball)[:k]
i2 = np.argsort(-lof_ball)[:k]
print(f" {k:>5} {y[i1].mean():>22.1%} {y[i2].mean():>17.1%}")
print("\n=== 4. Masshtablashning ta'siri ===")
X, y = global_anomaliya()
X2 = X.copy()
X2[:, 0] *= 500 # bitta belgining birligi o'zgardi
print(f" {'usul':<12} {'asl birlik':>12} {'500x birlik':>13}")
for nom in ["IsoForest", "LOF"]:
qator = []
for Xa in [X, X2]:
if nom == "IsoForest":
b = -IsolationForest(contamination=0.03, n_estimators=200,
random_state=0,
n_jobs=1).fit(Xa).score_samples(Xa)
else:
lof = LocalOutlierFactor(n_neighbors=20)
lof.fit_predict(Xa)
b = -lof.negative_outlier_factor_
qator.append(roc_auc_score(y, b))
print(f" {nom:<12} {qator[0]:>12.4f} {qator[1]:>13.4f}")
print(" ⭐ Isolation Forest masshtablashsiz ham ishlaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. ROC AUC bo'yicha ===
vazifa IsoForest LOF OC-SVM Elliptic
global 1.0000 0.9999 0.9147 1.0000
mahalliy 0.9426 0.9975 0.8934 0.6378
egri shakl 0.8753 0.9918 0.7549 0.7635
=== 2. PR AUC (nomutanosiblikda ishonchliroq) ===
vazifa musbat % IsoForest LOF
global 2.91% 0.9989 0.9978
mahalliy 2.44% 0.1802 0.8859
egri shakl 3.03% 0.7104 0.9179
=== 3. Mahalliy anomaliyada LOF ustunligi ===
k IsoForest precision@k LOF precision@k
10 0.0% 90.0%
25 8.0% 80.0%
50 20.0% 50.0%
100 17.0% 25.0%
=== 4. Masshtablashning ta'siri ===
usul asl birlik 500x birlik
IsoForest 1.0000 1.0000
LOF 0.9999 0.8884
⭐ Isolation Forest masshtablashsiz ham ishlaydiNima ko'rsatdi: 2.2, 2.3, 2.4-bo'limlar.
Misol 2 — Isolation Forest ichkarisi
"""Izolyatsiya g'oyasi va parametrlar (real numpy/sklearn)."""
import numpy as np
from sklearn.ensemble import IsolationForest
from sklearn.metrics import average_precision_score, roc_auc_score
def yarat(seed: int = 5, n: int = 2000, p: int = 8, ulush: float = 0.02):
rng = np.random.default_rng(seed)
X = rng.normal(0, 1, (n, p))
k = int(n * ulush)
anomaliya = rng.normal(0, 1, (k, p))
# bir nechta belgida g'ayrioddiy
for i in range(k):
nechta = min(3, p)
belgilar = rng.choice(p, nechta, replace=False)
anomaliya[i, belgilar] += (rng.choice([-1, 1], nechta)
* rng.uniform(4, 7, nechta))
return (np.vstack([X, anomaliya]),
np.concatenate([np.zeros(n), np.ones(k)]).astype(int))
def main() -> None:
X, y = yarat()
print("=== 1. Yo'l uzunligi va anomaliya bali ===")
izo = IsolationForest(contamination=0.02, n_estimators=200,
random_state=0, n_jobs=1).fit(X)
ball = -izo.score_samples(X)
print(f" normal nuqtalar bali: o'rtacha {ball[y == 0].mean():.4f}, "
f"std {ball[y == 0].std():.4f}")
print(f" anomaliyalar bali: o'rtacha {ball[y == 1].mean():.4f}, "
f"std {ball[y == 1].std():.4f}")
print(f" ROC AUC: {roc_auc_score(y, ball):.4f}")
print(f" PR AUC: {average_precision_score(y, ball):.4f}")
print("\n=== 2. n_estimators va max_samples ===")
print(f" {'n_est':>7} {'max_samples':>13} {'ROC AUC':>10} {'PR AUC':>9}")
for ne in [20, 50, 100, 300]:
for ms in [64, 256]:
m = IsolationForest(n_estimators=ne, max_samples=ms,
contamination=0.02, random_state=0,
n_jobs=1).fit(X)
b = -m.score_samples(X)
print(f" {ne:>7} {ms:>13} {roc_auc_score(y, b):>10.4f} "
f"{average_precision_score(y, b):>9.4f}")
print("\n=== 3. contamination faqat chegarani belgilaydi ===")
ballar = {}
for c in [0.01, 0.02, 0.05, 0.10]:
m = IsolationForest(contamination=c, n_estimators=200,
random_state=0, n_jobs=1).fit(X)
ballar[c] = -m.score_samples(X)
belgilangan = (m.predict(X) == -1)
print(f" contamination={c:<5}: belgilangan {belgilangan.mean():>6.2%}, "
f"ROC AUC {roc_auc_score(y, ballar[c]):.4f}")
juft = list(ballar)
print(f" ballar bir xilmi (0.01 va 0.10): "
f"{np.allclose(ballar[juft[0]], ballar[juft[-1]])}")
print("\n=== 4. Belgilar soni ortganda ===")
print(f" {'p':>4} {'ROC AUC':>10} {'PR AUC':>9}")
for p in [2, 5, 10, 30, 100]:
Xp, yp = yarat(p=p)
m = IsolationForest(contamination=0.02, n_estimators=200,
random_state=0, n_jobs=1).fit(Xp)
b = -m.score_samples(Xp)
print(f" {p:>4} {roc_auc_score(yp, b):>10.4f} "
f"{average_precision_score(yp, b):>9.4f}")
print(" ⭐ contamination ballarni emas, chegarani belgilaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Yo'l uzunligi va anomaliya bali ===
normal nuqtalar bali: o'rtacha 0.4106, std 0.0306
anomaliyalar bali: o'rtacha 0.6046, std 0.0225
ROC AUC: 1.0000
PR AUC: 0.9981
=== 2. n_estimators va max_samples ===
n_est max_samples ROC AUC PR AUC
20 64 0.9874 0.6910
20 256 0.9951 0.9071
50 64 0.9922 0.7408
50 256 0.9998 0.9888
100 64 0.9960 0.8326
100 256 0.9999 0.9969
300 64 0.9982 0.8963
300 256 1.0000 0.9994
=== 3. contamination faqat chegarani belgilaydi ===
contamination=0.01 : belgilangan 1.03%, ROC AUC 1.0000
contamination=0.02 : belgilangan 2.01%, ROC AUC 1.0000
contamination=0.05 : belgilangan 5.00%, ROC AUC 1.0000
contamination=0.1 : belgilangan 10.00%, ROC AUC 1.0000
ballar bir xilmi (0.01 va 0.10): True
=== 4. Belgilar soni ortganda ===
p ROC AUC PR AUC
2 1.0000 1.0000
5 1.0000 1.0000
10 0.9999 0.9961
30 0.9891 0.6578
100 0.7986 0.0857
⭐ contamination ballarni emas, chegarani belgilaydiNima ko'rsatdi: 2.2, 2.6-bo'limlar.
Misol 3 — Zichlik va qayta tiklash
"""GMM, PCA va KNN asosidagi usullar (real numpy/sklearn)."""
import numpy as np
from sklearn.decomposition import PCA
from sklearn.ensemble import IsolationForest
from sklearn.metrics import average_precision_score, roc_auc_score
from sklearn.mixture import GaussianMixture
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 9, n: int = 2000, p: int = 20, ulush: float = 0.02):
"""5 ta yashirin omil; anomaliyalar manifolddan tashqarida."""
rng = np.random.default_rng(seed)
omil = rng.normal(0, 1, (n, 5))
A = rng.normal(0, 1, (5, p))
X = omil @ A + rng.normal(0, 0.3, (n, p))
k = int(n * ulush)
# anomaliyalar: tasodifiy yo'nalishda, manifoldga mos kelmaydi
anomaliya = rng.normal(0, X.std(), (k, p))
return (np.vstack([X, anomaliya]),
np.concatenate([np.zeros(n), np.ones(k)]).astype(int))
def main() -> None:
X, y = yarat()
Xs = StandardScaler().fit_transform(X)
print("=== 1. Besh usul ===")
ballar = {}
ballar["IsolationForest"] = -IsolationForest(
contamination=0.02, n_estimators=200, random_state=0,
n_jobs=1).fit(X).score_samples(X)
g = GaussianMixture(3, covariance_type="diag", n_init=5,
reg_covar=1e-4, random_state=0).fit(Xs)
ballar["GMM zichligi"] = -g.score_samples(Xs)
p = PCA(n_components=5, random_state=0).fit(Xs)
tiklangan = p.inverse_transform(p.transform(Xs))
ballar["PCA qayta tiklash"] = ((Xs - tiklangan) ** 2).sum(axis=1)
nn = NearestNeighbors(n_neighbors=21).fit(Xs)
d, _ = nn.kneighbors(Xs)
ballar["KNN masofasi"] = d[:, -1]
ballar["KNN o'rtacha"] = d[:, 1:].mean(axis=1)
print(f" {'usul':<20} {'ROC AUC':>10} {'PR AUC':>9} "
f"{'precision@40':>14}")
for nom, b in ballar.items():
top = np.argsort(-b)[:40]
print(f" {nom:<20} {roc_auc_score(y, b):>10.4f} "
f"{average_precision_score(y, b):>9.4f} {y[top].mean():>13.1%}")
print("\n=== 2. PCA komponentlari soni ===")
print(f" {'komponentlar':>13} {'saqlangan %':>13} {'ROC AUC':>10}")
pt = PCA(random_state=0).fit(Xs)
jamlangan = np.cumsum(pt.explained_variance_ratio_)
for k in [2, 5, 10, 15]:
pk = PCA(n_components=k, random_state=0).fit(Xs)
xato = ((Xs - pk.inverse_transform(pk.transform(Xs))) ** 2).sum(axis=1)
print(f" {k:>13} {jamlangan[k - 1]:>12.1%} "
f"{roc_auc_score(y, xato):>10.4f}")
print("\n=== 3. Usullar kelishuvi ===")
belgilangan = {}
for nom, b in ballar.items():
chegara = np.quantile(b, 0.98)
belgilangan[nom] = b >= chegara
nomlar = list(belgilangan)
print(f" {'':<20}" + "".join(f"{n[:9]:>11}" for n in nomlar))
for a in nomlar:
qator = []
for c in nomlar:
kesishma = (belgilangan[a] & belgilangan[c]).sum()
birlashma = (belgilangan[a] | belgilangan[c]).sum()
qator.append(kesishma / max(birlashma, 1))
print(f" {a[:19]:<20}" + "".join(f"{v:>11.3f}" for v in qator))
print("\n=== 4. Ansambl: ballarni birlashtirish ===")
from scipy.stats import rankdata
darajalar = np.array([rankdata(b) / len(b) for b in ballar.values()])
ansambl = darajalar.mean(axis=0)
print(f" {'usul':<20} {'ROC AUC':>10} {'PR AUC':>9}")
for nom, b in ballar.items():
print(f" {nom:<20} {roc_auc_score(y, b):>10.4f} "
f"{average_precision_score(y, b):>9.4f}")
print(f" {'ANSAMBL (daraja)':<20} {roc_auc_score(y, ansambl):>10.4f} "
f"{average_precision_score(y, ansambl):>9.4f}")
print(" ⭐ Turli usullar turli anomaliyalarni topadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Besh usul ===
usul ROC AUC PR AUC precision@40
IsolationForest 0.8064 0.0499 2.5%
GMM zichligi 0.9069 0.1111 5.0%
PCA qayta tiklash 1.0000 1.0000 100.0%
KNN masofasi 0.9909 0.7244 70.0%
KNN o'rtacha 0.9959 0.8669 77.5%
=== 2. PCA komponentlari soni ===
komponentlar saqlangan % ROC AUC
2 54.2% 0.9375
5 96.0% 1.0000
10 98.4% 1.0000
15 99.4% 1.0000
=== 3. Usullar kelishuvi ===
Isolation GMM zichl PCA qayta KNN masof KNN o'rta
IsolationForest 1.000 0.608 0.012 0.188 0.155
GMM zichligi 0.608 1.000 0.038 0.224 0.188
PCA qayta tiklash 0.012 0.038 1.000 0.547 0.608
KNN masofasi 0.188 0.224 0.547 1.000 0.907
KNN o'rtacha 0.155 0.188 0.608 0.907 1.000
=== 4. Ansambl: ballarni birlashtirish ===
usul ROC AUC PR AUC
IsolationForest 0.8064 0.0499
GMM zichligi 0.9069 0.1111
PCA qayta tiklash 1.0000 1.0000
KNN masofasi 0.9909 0.7244
KNN o'rtacha 0.9959 0.8669
ANSAMBL (daraja) 0.9822 0.5809
⭐ Turli usullar turli anomaliyalarni topadiNima ko'rsatdi: 2.5-bo'lim.
Misol 4 — Tranzaksiyalar: kontekstual anomaliya
"""Belgi muhandisligi anomaliya aniqlashda (real pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.ensemble import IsolationForest
from sklearn.metrics import average_precision_score, roc_auc_score
def yarat(seed: int = 3, n: int = 8000) -> pd.DataFrame:
"""Tranzaksiyalar: firibgarlik KONTEKSTUAL (odat bilan solishtirilganda)."""
rng = np.random.default_rng(seed)
mijoz = rng.integers(0, 400, n)
# har mijozning o'z odati
odat_summa = rng.lognormal(12.0, 0.6, 400)
odat_soat = rng.integers(8, 20, 400)
summa = odat_summa[mijoz] * rng.lognormal(0, 0.35, n)
soat = np.clip(odat_soat[mijoz] + rng.normal(0, 2, n), 0, 23)
qurilma = rng.integers(0, 3, n) # 0 = odatiy qurilma
qurilma = np.where(rng.random(n) < 0.9, 0, qurilma)
firibgar = rng.random(n) < 0.015
# firibgarlik: mijozning odatidan 6-15 barobar katta summa, kechasi, yangi qurilma
summa[firibgar] = odat_summa[mijoz[firibgar]] * rng.uniform(6, 15,
firibgar.sum())
soat[firibgar] = rng.uniform(1, 5, firibgar.sum())
qurilma[firibgar] = rng.integers(1, 3, firibgar.sum())
return pd.DataFrame({"mijoz": mijoz, "summa": summa, "soat": soat,
"qurilma": qurilma, "firibgar": firibgar.astype(int)})
def main() -> None:
df = yarat()
print("=== 1. Ma'lumot ===")
print(f" {len(df)} tranzaksiya, {df['mijoz'].nunique()} mijoz")
print(f" firibgarlik: {int(df['firibgar'].sum())} "
f"({df['firibgar'].mean():.2%})")
print(f" summa: mediana {df['summa'].median():,.0f}, "
f"max {df['summa'].max():,.0f}")
y = df["firibgar"].to_numpy()
print("\n=== 2. Xom belgilar bilan ===")
xom = df[["summa", "soat", "qurilma"]].to_numpy()
b1 = -IsolationForest(contamination=0.02, n_estimators=200,
random_state=0, n_jobs=1).fit(xom).score_samples(xom)
print(f" ROC AUC {roc_auc_score(y, b1):.4f}, "
f"PR AUC {average_precision_score(y, b1):.4f}")
print("\n=== 3. Kontekstual belgilar qo'shilgandan keyin ===")
ortacha = df.groupby("mijoz")["summa"].transform("median")
ortacha_soat = df.groupby("mijoz")["soat"].transform("median")
df["summa_nisbati"] = df["summa"] / ortacha
df["soat_farqi"] = (df["soat"] - ortacha_soat).abs()
df["yangi_qurilma"] = (df["qurilma"] > 0).astype(int)
kontekst = df[["summa_nisbati", "soat_farqi", "yangi_qurilma",
"summa"]].to_numpy()
b2 = -IsolationForest(contamination=0.02, n_estimators=200,
random_state=0,
n_jobs=1).fit(kontekst).score_samples(kontekst)
print(f" ROC AUC {roc_auc_score(y, b2):.4f}, "
f"PR AUC {average_precision_score(y, b2):.4f}")
print(f" yaxshilanish: ROC {roc_auc_score(y, b2) - roc_auc_score(y, b1):+.4f}, "
f"PR {average_precision_score(y, b2) - average_precision_score(y, b1):+.4f}")
print("\n=== 4. precision@k: tekshiruvchilar uchun ===")
print(f" {'k':>5} {'xom belgilar':>15} {'kontekst bilan':>17} "
f"{'qamrov (kontekst)':>19}")
jami = int(y.sum())
for k in [20, 50, 100, 200]:
i1 = np.argsort(-b1)[:k]
i2 = np.argsort(-b2)[:k]
print(f" {k:>5} {y[i1].mean():>14.1%} {y[i2].mean():>16.1%} "
f"{y[i2].sum() / jami:>18.1%}")
print(f" (jami {jami} ta firibgarlik)")
print(" ⭐ Kontekstual belgilar anomaliyani ko'rinadigan qiladi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Ma'lumot ===
8000 tranzaksiya, 400 mijoz
firibgarlik: 137 (1.71%)
summa: mediana 166,245, max 11,268,431
=== 2. Xom belgilar bilan ===
ROC AUC 0.9994, PR AUC 0.9683
=== 3. Kontekstual belgilar qo'shilgandan keyin ===
ROC AUC 1.0000, PR AUC 0.9998
yaxshilanish: ROC +0.0006, PR +0.0315
=== 4. precision@k: tekshiruvchilar uchun ===
k xom belgilar kontekst bilan qamrov (kontekst)
20 100.0% 100.0% 14.6%
50 100.0% 100.0% 36.5%
100 96.0% 100.0% 73.0%
200 67.5% 68.5% 100.0%
(jami 137 ta firibgarlik)
⭐ Kontekstual belgilar anomaliyani ko'rinadigan qiladiNima ko'rsatdi: 2.1, 2.6-bo'limlar.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Anomaliya = katta qiymat" | Kombinatsiya ham bo'ladi |
| "Isolation Forest masshtablash talab qiladi" | Yo'q |
| "LOF masshtablashsiz ishlaydi" | Masshtablang |
| "contamination ballarni o'zgartiradi" | Faqat chegarani |
| "Anomaliyalarni o'chirish kerak" | Ular qimmatli bo'lishi mumkin |
| "Accuracy yaxshi metrika" | 99% anomaliyasiz ham chiqadi |
| "Bitta usul yetarli" | Ansambl yaxshiroq |
| "Kontekstni algoritm o'zi biladi" | Belgi qo'shish kerak |
6. Keng tarqalgan xatolar va yechimlari
1. LOF ni masshtablamasdan
LocalOutlierFactor(20).fit_predict(X) # turli birliklar # ⚠️
LocalOutlierFactor(20).fit_predict(StandardScaler().fit_transform(X)) # ✅2. contamination ni katta qo'yish
IsolationForest(contamination=0.2) # haqiqiy ulush 1% # ⚠️
IsolationForest(contamination=0.01) # yoki "auto" + qo'lda chegara # ✅3. LOF da novelty ni unutish
lof = LocalOutlierFactor(20).fit(Xtr); lof.predict(Xte) # xato # ⚠️
LocalOutlierFactor(20, novelty=True).fit(Xtr).predict(Xte) # ✅4. Accuracy bilan baholash
accuracy_score(y, bashorat) # 99% anomaliyasiz ham # ⚠️
average_precision_score(y, ball) # ✅5. Anomaliyalarni avtomatik o'chirish
X = X[izo.predict(X) == 1] # eng qimmatli ma'lumot yo'qoldi # ⚠️
# avval ko'rib chiqing, keyin qaror qiling # ✅6. Kontekstni hisobga olmaslik
IsolationForest().fit(df[["summa", "soat"]]) # ⚠️
# "mijoz odatiga nisbatan" belgilarini qo'shing # ✅7. Bitta usulga tayanish
ball = -izo.score_samples(X) # ⚠️
# 3-4 usul ballarini darajaga aylantirib o'rtachalang # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 16.5-dars (o'tilgan): DBSCAN shovqini
- 16.6-dars (o'tilgan): GMM zichligi
- 16.8-dars (o'tilgan): PCA qayta tiklash
- 14.9-dars (o'tilgan): Nomutanosib sinflar
- 06-qism (o'tilgan): Ma'lumot sifati
8. Eng yaxshi amaliyotlar
Isolation Forest dan boshlang.
Masofaga asoslangan usullarni masshtablang.
Kontekstual belgilar qo'shing.
PR AUC va precision@k bilan baholang.
Anomaliyalarni ko'rib chiqing.
Bir necha usulni birlashtiring.
contamination ni oqilona qo'ying.
Yorliq kelsa, nazoratli modelga o'ting.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # anomaliya turlari?
2. # Isolation Forest g'oyasi?
3. # anomaliya daraxtda qayerda?
4. # IF masshtablash talab qiladimi?
5. # LOF nimani taqqoslaydi?
6. # LOF ~ 1 nimani anglatadi?
7. # novelty=True qachon kerak?
8. # One-Class SVM ning kamchiligi?
9. # PCA qayta tiklash xatosi nima?
10. # contamination nimani belgilaydi?
11. # qaysi metrika afzal?
12. # precision@k nima?Javoblar
- Nuqtaviy, kontekstual, jamoaviy
- Anomaliyani izolyatsiya qilish oson
- Sayoz (kam bo'linishdan keyin)
- Yo'q
- Nuqta zichligini qo'shnilarniki bilan
- Normal
- Yangi nuqtalarni baholash uchun
- Sekin, parametrga sezgir
- Komponentlar bilan tiklash xatosi
- Faqat chegarani
- PR AUC
- Eng yuqori k ta orasidagi haqiqiylar ulushi
Vazifa 2: Xatolarni tuzating
1. LocalOutlierFactor(20).fit_predict(X) # turli birliklar
2. IsolationForest(contamination=0.2) # haqiqiy 1%
3. lof = LocalOutlierFactor(20).fit(Xtr); lof.predict(Xte)
4. accuracy_score(y, bashorat)
5. X = X[izo.predict(X) == 1]Javoblar
1. LocalOutlierFactor(20).fit_predict(StandardScaler().fit_transform(X))
2. IsolationForest(contamination=0.01)
3. LocalOutlierFactor(20, novelty=True).fit(Xtr).predict(Xte)
4. average_precision_score(y, ball)
5. # avval ko'rib chiqing, keyin qaror qilingVazifa 3: To'rt usul
Modellang:
- ROC AUC
- PR AUC
- Mahalliy anomaliya
- Masshtablash
Vazifa 4: Isolation Forest
Modellang:
- Ballar
- Parametrlar
- contamination
- Belgilar soni
Vazifa 5: Zichlik
Modellang:
- Besh usul
- PCA komponentlari
- Kelishuv
- Ansambl
Vazifa 6: Tranzaksiyalar
Modellang:
- Ma'lumot
- Xom belgilar
- Kontekst
- precision@k
Vazifa 7: O'ylash
Anomaliya aniqlash modeli ishga tushdi va kuniga 200 ta ogohlantirish beradi. Tekshiruvchilar 30 tasini ko'ra oladi. Nima qilish kerak?
Javob
Qisqa javob: modelni emas, chegarani va tartiblashni sozlang. Muammo aniqlikda emas — quvvat cheklovida. Maqsad: eng yuqori 30 ta orasida haqiqiy hodisalar ulushini maksimallashtirish (precision@30).
1. Darhol qilinadigan ishlar
| Harakat | Natija |
|---|---|
| Chegarani ko'tarish | 200 → 30 ogohlantirish |
precision@30 ni o'lchash |
Joriy holat ma'lum bo'ladi |
| Ballar taqsimotini ko'rish | Aniq "dum" bormi |
| Ogohlantirishlarni tartiblash | Eng ishonchlilari birinchi |
2. precision@30 ni oshirish
- Ansambl: 3-4 usul ballarini darajaga aylantirib o'rtachalang (Misol 3)
- Kontekstual belgilar: "odatga nisbatan" belgilari ko'pincha eng katta foyda beradi (Misol 4)
- Qoidalar bilan filtrlash: aniq normal holatlarni oldindan chiqarib tashlash
- Yorliqlardan foydalanish: tekshiruvchilar qarorlari — bu yorliq, ularni to'plang
3. Uzoq muddatli: nazoratli modelga o'tish
1. Tekshiruvchilar qarorlarini saqlang (tasdiqlandi / rad etildi)
2. 500-1000 yorliq to'planganda nazoratli model quring (14.9)
3. Nazoratsiz ball - shu modelning BELGISI bo'ladi
4. Natija odatda sezilarli yaxshilanadiBu — anomaliya aniqlashning tabiiy evolyutsiyasi: nazoratsizdan yarim nazoratliga, keyin nazoratliga.
4. Biznes tomonidan
- Har ogohlantirishning qiymatini hisoblang (topilgan firibgarlik qancha saqlaydi)
- Tekshiruvchi vaqtining narxini hisoblang
- Optimal chegara — chegaraviy foyda chegaraviy narxga teng bo'lgan nuqta
- Ba'zan javob: ko'proq tekshiruvchi yollash
5. Xulosa
- Chegarani quvvatga moslang
- precision@k ni asosiy metrika qiling
- Ansambl va kontekstual belgilar bilan yaxshilang
- Yorliq to'plab, nazoratli modelga o'ting
Nimani mustahkamlaydi: 2.6-bo'lim.
Xulosa
Bu darsda anomaliya aniqlashni o'rgandik.
Eng muhim uch fikr:
Isolation Forest — odatiy birinchi tanlov. U anomaliyani izolyatsiya qilish oson degan g'oyaga asoslanadi: tasodifiy bo'linishlarda anomaliya sayoz darajada ajraladi. Afzalliklari: masshtablash kerak emas, chiziqli murakkablik, yuqori o'lchamda ishlaydi. Kamchiligi — mahalliy anomaliyalarni (zich klaster chetidagi) yomon topadi; u yerda LOF ustun.
contaminationfaqat chegarani belgilaydi.score_samplesballari undan bog'liq emas — shuning uchun modelni bir marta o'qitib, chegarani keyin quvvatga qarab sozlash mumkin. Baholashdaaccuracyyaroqsiz (99% anomaliyasiz ham chiqadi): PR AUC va ayniqsaprecision@kishlating — tekshiruvchilar kuniga cheklangan sonda hodisani ko'radi.Kontekstual belgilar hal qiluvchi. Algoritm kontekstni bilmaydi: "50 ming so'm" normalmi yoki yo'qmi — bu mijozning odatiga bog'liq. "Mijoz medianasiga nisbati", "odatiy soatdan farqi" kabi belgilar kontekstual anomaliyani nuqtaviy anomaliyaga aylantiradi va natijani sezilarli yaxshilaydi. Turli usullar turli anomaliyalarni topadi — ballarni darajaga aylantirib birlashtiring.
Keyingi darsda nazoratsiz o'rganishning qo'llanilishini ko'rib chiqamiz: segmentatsiya, tavsiya, mavzu modellashtirish va siqish.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!