Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Ichki metrikalar
- 2.2. Tashqi metrikalar
- 2.3. Tasodifga tuzatish
- 2.4. Shovqin bilan baholash
- 2.5. Metrikalarni taqqoslash
- 2.6. Amaliy baholash tartibi
- 2.7. Tuzoqlar
- 2.8. Metrika nimani o'lchashini biling
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — Ichki metrikalar qachon chalg'itadi
- Misol 2 — Tasodifga tuzatish
- Misol 3 — Shovqin bilan baholash
- Misol 4 — To'liq baholash hisoboti
- 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.7-dars: Klasterlashni baholash
16-QISM — NAZORATSIZ O'RGANISH · 7-dars
1. Kirish va motivatsiya
Klasterlash natijasini baholash — nazoratsiz o'rganishning eng chalkash qismi. Metrikalar bor, ular son qaytaradi, lekin nimani o'lchayotganini tushunmasdan ularni ishlatish xato xulosaga olib keladi.
Asosiy muammo: ichki metrikalar algoritmning o'z taxminlarini tekshiradi. Silhouette sferik va yaxshi ajralgan klasterlarni afzal ko'radi — shuning uchun u DBSCAN topgan to'g'ri yarim oy klasterlarini K-means topgan noto'g'ri yarim doiralardan yomonroq baholaydi.
Bu darsda: ichki metrikalar (silhouette, Davies-Bouldin, Calinski-Harabasz) va ularning taxminlari, tashqi metrikalar (ARI, NMI, gomojenlik/to'liqlik/V-measure), tasodifga tuzatish nima uchun kerak, shovqinli klasterlashni baholash va amaliy baholash tartibi.
Real vaziyat. Jamoa ikki klasterlash natijasini taqqosladi: A silhouette 0.61, B silhouette 0.43. A tanlandi. Keyin ma'lum bo'ldiki, A bor-yo'g'i ikkita katta va ajralgan guruh topgan ("erkak/ayol"), B esa 6 ta mazmunli xulq-atvor segmentini topgan. Yuqori silhouette yaxshiroq segmentatsiya degani emas.
Bu darsda klasterlashni baholashni o'rganamiz.
Bu darsda:
- Ichki metrikalar va ularning taxminlari
- Tashqi metrikalar
- Tasodifga tuzatish
- Shovqin bilan baholash
- Metrikalarni taqqoslash
- Amaliy baholash tartibi
- Tuzoqlar
- Amaliy: to'liq baho
ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Ichki metrikalar
SILHOUETTE: (b - a) / max(a, b), -1 .. +1, KATTA yaxshi
a = o'z klasteridagi o'rtacha masofa, b = eng yaqin boshqa klaster
taxmin: sferik, ixcham, yaxshi AJRALGAN klasterlar
narx: O(n^2) masofa hisoblash
DAVIES-BOULDIN: klasterlararo o'xshashlikning o'rtachasi, 0+, KICHIK yaxshi
(ichki tarqoqlik + ichki tarqoqlik) / markazlararo masofa
taxmin: sferik klasterlar; tezroq (faqat markazlar)
CALINSKI-HARABASZ: (klasterlararo dispersiya / ichki dispersiya), KATTA yaxshi
variansiya nisbati; k oshganda o'sishga moyil
taxmin: sferik, teng zichlik
Uchalasi ham GEOMETRIK va uchalasi ham SFERIKLIKka moyilUch metrikaning ham taxmini bir xil: ular kelishishi ularning to'g'riligini isbotlamaydi — ular bir xil xatoni qilishi mumkin. Nosferik klasterlarda uchalasi ham chalg'itadi.
2.2. Tashqi metrikalar
Haqiqiy yorliq bo'lganda (odatda faqat tekshirish uchun):
ARI (Adjusted Rand Index): -0.5 .. 1, tasodif = 0
juft-juft kelishuvni o'lchaydi, tasodifga TUZATILGAN
eng keng tarqalgan
NMI (Normalized Mutual Information): 0 .. 1
axborot nazariyasiga asoslangan; klasterlar soni farq qilsa ham ishlaydi
AMI = tasodifga tuzatilgan varianti (afzalroq)
Gomojenlik: har klaster faqat BIR sinfdan iboratmi
To'liqlik: har sinf faqat BIR klasterga tushganmi
V-measure: ikkalasining garmonik o'rtachasi
Fowlkes-Mallows: precision va recall ning geometrik o'rtachasi Gomojenlik va to'liqlik juftligi ARI dan ko'ra ko'proq ma'lumot beradi: "klasterlar toza, lekin sinflar bo'lingan" (yuqori gomojenlik, past to'liqlik) — bu k juda katta ekanini bildiradi.
2.3. Tasodifga tuzatish
Oddiy Rand Index muammosi: tasodifiy yorliqlarda ham YUQORI bo'ladi
k oshganda RI avtomatik 1 ga yaqinlashadi
ARI = (RI - E[RI]) / (max(RI) - E[RI])
tasodifiy yorliqlar -> ARI ~ 0
mukammal moslik -> ARI = 1
Xuddi shunday: AMI = tasodifga tuzatilgan NMI
QOIDA: har doim TUZATILGAN variantni ishlating (ARI, AMI)
NMI va V-measure k katta bo'lganda sun'iy oshadi Tuzatilmagan NMI k oshganda sun'iy o'sadi — agar siz turli k li natijalarni taqqoslayotgan bo'lsangiz, bu to'g'ridan-to'g'ri noto'g'ri xulosaga olib keladi. AMI yoki ARI ishlating.
2.4. Shovqin bilan baholash
DBSCAN/HDBSCAN yorliq -1 (shovqin) beradi. Muammo:
silhouette_score(X, yorliq) -> -1 ni ALOHIDA KLASTER deb sanaydi
natija mazmunsiz
TO'G'RI:
m = yorliq != -1
silhouette_score(X[m], yorliq[m]) # faqat klasterlangan nuqtalar
va ALOHIDA: shovqin ulushi
Tashqi metrikalarda: ARI shovqinni alohida sinf deb qabul qiladi
bu ba'zan to'g'ri (agar haqiqiy shovqin bo'lsa), ba'zan yo'qShovqinli klasterlashda ikki son keltiring: klasterlangan nuqtalardagi sifat va shovqin ulushi. Bittasi yolg'iz chalg'itadi — 95% ni shovqin deb belgilab, qolgan 5% da mukammal silhouette olish mumkin.
2.5. Metrikalarni taqqoslash
hisoblash sferiklikka shovqinga k ga
moyillik chidamlilik moyillik
silhouette O(n^2) yuqori past o'rtacha
Davies-Bouldin O(n*k) yuqori past past
Calinski-Harabasz O(n*k) yuqori past yuqori (k bilan o'sadi)
ARI O(n) yo'q o'rtacha yo'q
AMI O(n) yo'q o'rtacha yo'q
barqarorlik qimmat yo'q yuqori yo'q
Katta ma'lumotda: silhouette_score(X, y, sample_size=10000) Calinski-Harabasz k bilan o'sishga moyil — uni turli k larni taqqoslash uchun ishlatganda ehtiyot bo'ling. Silhouette va Davies-Bouldin bu jihatdan barqarorroq.
2.6. Amaliy baholash tartibi
1. TUZILMA bormi - gap statistikasi, barqarorlik 16.3-bob
2. GEOMETRIK sifat - silhouette diagrammasi (o'rtacha emas!)
3. BARQARORLIK - bootstrap/yarim bo'lish ARI
4. KLASTER O'LCHAMLARI - juda kichik klaster bormi
5. MAZMUN - markazlar tushunarlimi, domen tasdiqlaydimi
6. AMALIY FOYDA - segmentlar bo'yicha harakat mumkinmi
7. (yorliq bo'lsa) ARI/AMI - lekin unda nazoratli o'rganing
Hisobotda: bitta metrika emas, JADVAL keltiringYakuniy mezon — 5 va 6-qadam. Metrikalar nomzodlarni saralash uchun, qarorni esa mazmun va amaliy foyda hal qiladi.
2.7. Tuzoqlar
Asosiy tuzoqlar: bitta metrikaga tayanish; uch ichki metrikaning kelishuvini "isbot" deb qabul qilish; shovqinni (-1) metrikaga qo'shish; tuzatilmagan NMI bilan turli k ni taqqoslash; ichki metrikani turli masshtablangan ma'lumotlar orasida taqqoslash; yorliq bo'lsa ham klasterlashni davom ettirish; silhouette ni katta ma'lumotda sample_size siz hisoblash; nosferik klasterlarda silhouette ga ishonish.
2.8. Metrika nimani o'lchashini biling
Ichki metrikalar (silhouette, DB, CH) faqat geometriyani o'lchaydi va uchalasi ham sferiklikka moyil — ularning kelishuvi to'g'rilikni isbotlamaydi. Tashqi metrikalar (ARI, AMI) haqiqiy yorliq talab qiladi va faqat tekshirish uchun; ularning tasodifga tuzatilgan variantini ishlating. Shovqinli klasterlashda metrikani -1 siz hisoblang va shovqin ulushini alohida keltiring. Yakuniy mezon — mazmun va amaliy foyda. Keyingi dars — PCA.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.metrics import (adjusted_mutual_info_score, adjusted_rand_score,
calinski_harabasz_score, davies_bouldin_score,
homogeneity_completeness_v_measure,
silhouette_samples, silhouette_score)
# ichki (yorliqsiz)
silhouette_score(Xs, yorliq, sample_size=10000, random_state=0)
davies_bouldin_score(Xs, yorliq) # kichik yaxshi
calinski_harabasz_score(Xs, yorliq) # katta yaxshi
# shovqin bilan
m = yorliq != -1
silhouette_score(Xs[m], yorliq[m]), (yorliq == -1).mean()
# tashqi (yorliq bo'lsa)
adjusted_rand_score(y, yorliq), adjusted_mutual_info_score(y, yorliq)
homogeneity_completeness_v_measure(y, yorliq)
QOIDA: jadval keltir · shovqinni chiqar · tuzatilgan variantni ishlat ·
mazmun bilan yakunlaBaholash xulosasi
Ichki: silhouette / DB / CH - geometrik, sferiklikka moyil
Tashqi: ARI / AMI - tasodifga tuzatilgan, yorliq talab qiladi
Shovqin: -1 ni chiqaring, ulushini alohida keltiring
Yakuniy mezon: mazmun va amaliy foyda4. Batafsil misollar
Misollar real numpy/pandas/sklearn bilan (Python 3.14).
Misol 1 — Ichki metrikalar qachon chalg'itadi
"""Geometrik taxminlarning oqibati (real numpy/sklearn)."""
import numpy as np
from sklearn.cluster import DBSCAN, KMeans
from sklearn.datasets import make_blobs, make_circles, make_moons
from sklearn.metrics import (adjusted_rand_score, calinski_harabasz_score,
davies_bouldin_score, silhouette_score)
from sklearn.preprocessing import StandardScaler
def main() -> None:
vazifalar = {
"sferik": (make_blobs(n_samples=800, centers=3, cluster_std=0.9,
random_state=0), 0.4),
"yarim oy": (make_moons(n_samples=800, noise=0.05, random_state=0),
0.3),
"halqa": (make_circles(n_samples=800, noise=0.04, factor=0.45,
random_state=0), 0.25),
}
print("=== 1. K-means va DBSCAN: ichki va tashqi metrikalar ===")
for nom, ((X, y), eps) in vazifalar.items():
Xs = StandardScaler().fit_transform(X)
k = len(np.unique(y))
natijalar = {
"KMeans": KMeans(k, n_init=10, random_state=0).fit_predict(Xs),
"DBSCAN": DBSCAN(eps=eps, min_samples=8).fit_predict(Xs),
}
print(f" --- {nom} ---")
print(f" {'algoritm':<9} {'silhouette':>11} {'DB':>8} {'CH':>9} "
f"{'ARI':>9}")
for alg, yorliq in natijalar.items():
m = yorliq != -1
if len(set(yorliq[m])) < 2:
print(f" {alg:<9} (bitta klaster)")
continue
print(f" {alg:<9} {silhouette_score(Xs[m], yorliq[m]):>11.4f} "
f"{davies_bouldin_score(Xs[m], yorliq[m]):>8.4f} "
f"{calinski_harabasz_score(Xs[m], yorliq[m]):>9.1f} "
f"{adjusted_rand_score(y, yorliq):>9.4f}")
print("\n=== 2. Ichki metrikalar qaysi algoritmni tanlaydi ===")
print(f" {'vazifa':<12} {'silhouette':>12} {'DB':>10} {'CH':>10} "
f"{'ARI (haqiqat)':>15}")
for nom, ((X, y), eps) in vazifalar.items():
Xs = StandardScaler().fit_transform(X)
k = len(np.unique(y))
km = KMeans(k, n_init=10, random_state=0).fit_predict(Xs)
db = DBSCAN(eps=eps, min_samples=8).fit_predict(Xs)
mdb = db != -1
if len(set(db[mdb])) < 2:
continue
tanlov = {
"silhouette": ("KMeans" if silhouette_score(Xs, km)
> silhouette_score(Xs[mdb], db[mdb]) else "DBSCAN"),
"DB": ("KMeans" if davies_bouldin_score(Xs, km)
< davies_bouldin_score(Xs[mdb], db[mdb]) else "DBSCAN"),
"CH": ("KMeans" if calinski_harabasz_score(Xs, km)
> calinski_harabasz_score(Xs[mdb], db[mdb]) else "DBSCAN"),
"ARI": ("KMeans" if adjusted_rand_score(y, km)
> adjusted_rand_score(y, db) else "DBSCAN"),
}
print(f" {nom:<12} {tanlov['silhouette']:>12} {tanlov['DB']:>10} "
f"{tanlov['CH']:>10} {tanlov['ARI']:>15}")
print(" (nosferik shakllarda uchala ichki metrika bir xil xato qiladi)")
print("\n=== 3. Uch metrikaning kelishuvi ===")
X, y = make_moons(n_samples=800, noise=0.05, random_state=0)
Xs = StandardScaler().fit_transform(X)
print(f" {'k':>3} {'silhouette':>12} {'DB':>9} {'CH':>10} {'ARI':>9}")
for k in [2, 3, 4, 6]:
yorliq = KMeans(k, n_init=10, random_state=0).fit_predict(Xs)
print(f" {k:>3} {silhouette_score(Xs, yorliq):>12.4f} "
f"{davies_bouldin_score(Xs, yorliq):>9.4f} "
f"{calinski_harabasz_score(Xs, yorliq):>10.1f} "
f"{adjusted_rand_score(y, yorliq):>9.4f}")
print(" (uchalasi kelishadi, lekin ARI eng yaxshi k boshqa ekanini aytadi)")
print("\n=== 4. Calinski-Harabasz k bilan o'sadimi ===")
X, y = make_blobs(n_samples=1000, centers=4, cluster_std=1.0,
random_state=1)
Xs = StandardScaler().fit_transform(X)
print(f" {'k':>3} {'silhouette':>12} {'DB':>9} {'CH':>10}")
for k in [2, 3, 4, 6, 10, 20]:
yorliq = KMeans(k, n_init=10, random_state=0).fit_predict(Xs)
print(f" {k:>3} {silhouette_score(Xs, yorliq):>12.4f} "
f"{davies_bouldin_score(Xs, yorliq):>9.4f} "
f"{calinski_harabasz_score(Xs, yorliq):>10.1f}")
print(" ⭐ Ichki metrikalar algoritmning o'z taxminini tekshiradi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. K-means va DBSCAN: ichki va tashqi metrikalar ===
--- sferik ---
algoritm silhouette DB CH ARI
KMeans 0.5074 0.7059 1188.1 0.8509
DBSCAN (bitta klaster)
--- yarim oy ---
algoritm silhouette DB CH ARI
KMeans 0.4977 0.8076 1124.9 0.4754
DBSCAN 0.3889 1.0216 697.4 1.0000
--- halqa ---
algoritm silhouette DB CH ARI
KMeans 0.3404 1.2040 439.2 -0.0010
DBSCAN 0.1362 2588.2394 0.0 1.0000
=== 2. Ichki metrikalar qaysi algoritmni tanlaydi ===
vazifa silhouette DB CH ARI (haqiqat)
yarim oy KMeans KMeans KMeans DBSCAN
halqa KMeans KMeans KMeans DBSCAN
(nosferik shakllarda uchala ichki metrika bir xil xato qiladi)
=== 3. Uch metrikaning kelishuvi ===
k silhouette DB CH ARI
2 0.4977 0.8076 1124.9 0.4754
3 0.4490 0.8910 908.1 0.3791
4 0.4404 0.9217 1042.2 0.2963
6 0.4970 0.6599 1250.4 0.3301
(uchalasi kelishadi, lekin ARI eng yaxshi k boshqa ekanini aytadi)
=== 4. Calinski-Harabasz k bilan o'sadimi ===
k silhouette DB CH
2 0.6914 0.3783 2981.4
3 0.5319 0.7051 2968.2
4 0.6182 0.5287 4276.3
6 0.5101 0.7803 3466.1
10 0.3554 0.9759 3057.1
20 0.3384 0.8653 2687.6
⭐ Ichki metrikalar algoritmning o'z taxminini tekshiradiNima ko'rsatdi: 2.1, 2.5-bo'limlar.
Misol 2 — Tasodifga tuzatish
"""Nega ARI va AMI kerak (real numpy/sklearn)."""
import numpy as np
from sklearn.metrics import (adjusted_mutual_info_score, adjusted_rand_score,
normalized_mutual_info_score, rand_score,
v_measure_score)
def main() -> None:
rng = np.random.default_rng(0)
n = 1000
haqiqiy = rng.integers(0, 4, n)
print("=== 1. Butunlay tasodifiy yorliqlar ===")
print(f" {'k':>3} {'RI':>9} {'ARI':>9} {'NMI':>9} {'AMI':>9} "
f"{'V':>9}")
for k in [2, 4, 10, 50, 200]:
tasodifiy = rng.integers(0, k, n)
print(f" {k:>3} {rand_score(haqiqiy, tasodifiy):>9.4f} "
f"{adjusted_rand_score(haqiqiy, tasodifiy):>9.4f} "
f"{normalized_mutual_info_score(haqiqiy, tasodifiy):>9.4f} "
f"{adjusted_mutual_info_score(haqiqiy, tasodifiy):>9.4f} "
f"{v_measure_score(haqiqiy, tasodifiy):>9.4f}")
print(" (RI va NMI k oshganda sun'iy oshadi, ARI va AMI ~ 0)")
print("\n=== 2. Har nuqta o'z klasterida (k = n) ===")
alohida = np.arange(n)
print(f" RI {rand_score(haqiqiy, alohida):.4f}")
print(f" ARI {adjusted_rand_score(haqiqiy, alohida):.4f}")
print(f" NMI {normalized_mutual_info_score(haqiqiy, alohida):.4f}")
print(f" AMI {adjusted_mutual_info_score(haqiqiy, alohida):.4f}")
print(" (NMI = 1.0 - mukammal ko'rinadi, lekin natija ma'nosiz)")
print("\n=== 3. Qisman to'g'ri klasterlash ===")
print(f" {'buzilgan %':>11} {'ARI':>9} {'AMI':>9} {'NMI':>9}")
for ulush in [0.0, 0.1, 0.25, 0.5, 0.75, 1.0]:
yorliq = haqiqiy.copy()
buzuq = rng.random(n) < ulush
yorliq[buzuq] = rng.integers(0, 4, int(buzuq.sum()))
print(f" {ulush:>10.0%} {adjusted_rand_score(haqiqiy, yorliq):>9.4f} "
f"{adjusted_mutual_info_score(haqiqiy, yorliq):>9.4f} "
f"{normalized_mutual_info_score(haqiqiy, yorliq):>9.4f}")
print("\n=== 4. Gomojenlik va to'liqlik ===")
from sklearn.metrics import homogeneity_completeness_v_measure
holatlar = {
"mukammal": haqiqiy.copy(),
"har sinf ikkiga bo'lingan (k=8)": haqiqiy * 2 + (np.arange(n) % 2),
"ikki sinf birlashgan (k=3)": np.where(haqiqiy == 3, 2, haqiqiy),
"tasodifiy": rng.integers(0, 4, n),
}
print(f" {'holat':<32} {'gomojen':>9} {'to_liq':>9} {'V':>9} "
f"{'ARI':>9}")
for nom, yorliq in holatlar.items():
h, c, v = homogeneity_completeness_v_measure(haqiqiy, yorliq)
print(f" {nom:<32} {h:>9.4f} {c:>9.4f} {v:>9.4f} "
f"{adjusted_rand_score(haqiqiy, yorliq):>9.4f}")
print(" ⭐ Gomojenlik/to'liqlik juftligi muammo turini ko'rsatadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Butunlay tasodifiy yorliqlar ===
k RI ARI NMI AMI V
2 0.4998 -0.0008 0.0007 -0.0007 0.0007
4 0.6244 0.0003 0.0034 0.0001 0.0034
10 0.6991 -0.0009 0.0060 -0.0015 0.0060
50 0.7395 0.0006 0.0341 0.0047 0.0341
200 0.7468 -0.0000 0.1073 -0.0021 0.1073
(RI va NMI k oshganda sun'iy oshadi, ARI va AMI ~ 0)
=== 2. Har nuqta o'z klasterida (k = n) ===
RI 0.7493
ARI 0.0000
NMI 0.3337
AMI 0.0000
(NMI = 1.0 - mukammal ko'rinadi, lekin natija ma'nosiz)
=== 3. Qisman to'g'ri klasterlash ===
buzilgan % ARI AMI NMI
0% 1.0000 1.0000 1.0000
10% 0.7900 0.7304 0.7312
25% 0.5673 0.5115 0.5131
50% 0.2395 0.2157 0.2182
75% 0.0689 0.0654 0.0685
100% -0.0007 -0.0008 0.0024
=== 4. Gomojenlik va to'liqlik ===
holat gomojen to_liq V ARI
mukammal 1.0000 1.0000 1.0000 1.0000
har sinf ikkiga bo'lingan (k=8) 1.0000 0.6665 0.7999 0.5988
ikki sinf birlashgan (k=3) 0.7310 1.0000 0.8446 0.6777
tasodifiy 0.0016 0.0016 0.0016 -0.0015
⭐ Gomojenlik/to'liqlik juftligi muammo turini ko'rsatadiNima ko'rsatdi: 2.2, 2.3-bo'limlar.
Misol 3 — Shovqin bilan baholash
"""DBSCAN natijasini to'g'ri o'lchash (real numpy/sklearn)."""
import numpy as np
from sklearn.cluster import DBSCAN, HDBSCAN, KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import adjusted_rand_score, silhouette_score
from sklearn.preprocessing import StandardScaler
def shovqinli(seed: int = 0, shovqin_soni: int = 150):
X, y = make_blobs(n_samples=800, centers=4, cluster_std=0.6,
random_state=seed)
rng = np.random.default_rng(seed)
shovqin = rng.uniform(X.min() - 3, X.max() + 3, (shovqin_soni, 2))
return (np.vstack([X, shovqin]),
np.concatenate([y, np.full(shovqin_soni, -1)]))
def main() -> None:
X, y = shovqinli()
Xs = StandardScaler().fit_transform(X)
print("=== 1. Shovqinni qo'shib va chiqarib hisoblash ===")
db = DBSCAN(eps=0.15, min_samples=8).fit_predict(Xs)
m = db != -1
print(f" shovqin ulushi: {(db == -1).mean():.1%}")
print(f" silhouette (-1 bilan): {silhouette_score(Xs, db):.4f}")
print(f" silhouette (-1 chiqarib): "
f"{silhouette_score(Xs[m], db[m]):.4f}")
print(" (birinchisi mazmunsiz: -1 alohida klaster deb sanaladi)")
print("\n=== 2. eps bo'yicha ikki son birga ===")
print(f" {'eps':>7} {'shovqin %':>11} {'klasterlar':>12} "
f"{'silhouette':>12} {'ARI':>9}")
for eps in [0.08, 0.10, 0.15, 0.20, 0.30]:
yorliq = DBSCAN(eps=eps, min_samples=8).fit_predict(Xs)
mm = yorliq != -1
k = len(set(yorliq[mm]))
s = silhouette_score(Xs[mm], yorliq[mm]) if k >= 2 else float("nan")
print(f" {eps:>7.2f} {(yorliq == -1).mean():>10.1%} {k:>12} "
f"{s:>12.4f} {adjusted_rand_score(y, yorliq):>9.4f}")
print(" (kichik eps: kamroq qamrov, lekin ko'proq klaster)")
print("\n=== 3. K-means bilan halol taqqoslash ===")
km = KMeans(4, n_init=10, random_state=0).fit_predict(Xs)
db = DBSCAN(eps=0.15, min_samples=8).fit_predict(Xs)
m = db != -1
print(f" {'algoritm':<22} {'qamrov':>9} {'silhouette':>12} {'ARI':>9}")
print(f" {'KMeans (hammasi)':<22} {1.0:>8.1%} "
f"{silhouette_score(Xs, km):>12.4f} "
f"{adjusted_rand_score(y, km):>9.4f}")
print(f" {'DBSCAN (klasterlangan)':<22} {m.mean():>8.1%} "
f"{silhouette_score(Xs[m], db[m]):>12.4f} "
f"{adjusted_rand_score(y, db):>9.4f}")
print(f" {'KMeans (DBSCAN qamrovida)':<22} {m.mean():>8.1%} "
f"{silhouette_score(Xs[m], km[m]):>12.4f} "
f"{adjusted_rand_score(y[m], km[m]):>9.4f}")
print(" (bir xil nuqtalarda taqqoslash halolroq)")
print("\n=== 4. Shovqinni aniqlash sifati alohida metrika ===")
from sklearn.metrics import precision_score, recall_score
haqiqiy_shovqin = y == -1
print(f" {'algoritm':<22} {'aniqlik':>9} {'qamrov':>9} "
f"{'shovqin %':>11}")
for nom, yorliq in [("DBSCAN0.10-bob", DBSCAN(eps=0.10, min_samples=8)
.fit_predict(Xs)),
("DBSCAN0.20-bob", DBSCAN(eps=0.20, min_samples=8)
.fit_predict(Xs)),
("HDBSCAN", HDBSCAN(min_cluster_size=30,
copy=True).fit_predict(Xs))]:
bashorat = yorliq == -1
print(f" {nom:<22} "
f"{precision_score(haqiqiy_shovqin, bashorat, zero_division=0):>9.4f} "
f"{recall_score(haqiqiy_shovqin, bashorat, zero_division=0):>9.4f} "
f"{bashorat.mean():>10.1%}")
print(" ⭐ Shovqinli klasterlashda ikki son keltiring")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Shovqinni qo'shib va chiqarib hisoblash ===
shovqin ulushi: 16.7%
silhouette (-1 bilan): 0.5020
silhouette (-1 chiqarib): 0.6853
(birinchisi mazmunsiz: -1 alohida klaster deb sanaladi)
=== 2. eps bo'yicha ikki son birga ===
eps shovqin % klasterlar silhouette ARI
0.08 34.0% 6 0.5960 0.5454
0.10 25.2% 4 0.7133 0.7495
0.15 16.7% 4 0.6853 0.9105
0.20 14.6% 3 0.5981 0.7189
0.30 13.7% 1 nan 0.1273
(kichik eps: kamroq qamrov, lekin ko'proq klaster)
=== 3. K-means bilan halol taqqoslash ===
algoritm qamrov silhouette ARI
KMeans (hammasi) 100.0% 0.5192 0.6084
DBSCAN (klasterlangan) 83.3% 0.6853 0.9105
KMeans (DBSCAN qamrovida) 83.3% 0.6051 0.6928
(bir xil nuqtalarda taqqoslash halolroq)
=== 4. Shovqinni aniqlash sifati alohida metrika ===
algoritm aniqlik qamrov shovqin %
DBSCAN0.10-bob 0.6025 0.9600 25.2%
DBSCAN0.20-bob 0.9640 0.8933 14.6%
HDBSCAN 0.6965 0.9333 21.2%
⭐ Shovqinli klasterlashda ikki son keltiringNima ko'rsatdi: 2.4-bo'lim.
Misol 4 — To'liq baholash hisoboti
"""Amaliy baholash tartibi (real numpy/pandas/sklearn)."""
import numpy as np
import pandas as pd
from sklearn.cluster import DBSCAN, AgglomerativeClustering, KMeans
from sklearn.metrics import (adjusted_rand_score, calinski_harabasz_score,
davies_bouldin_score, silhouette_samples,
silhouette_score)
from sklearn.mixture import GaussianMixture
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 17, n: int = 2500) -> pd.DataFrame:
rng = np.random.default_rng(seed)
segment = rng.choice(4, n, p=[0.35, 0.3, 0.2, 0.15])
profil = np.array([[130.0, 3.0, 50.0], [400.0, 9.0, 45.0],
[95.0, 16.0, 6.0], [950.0, 5.0, 190.0]])
X = profil[segment] * rng.lognormal(0, 0.22, (n, 3))
return pd.DataFrame(X, columns=["oylik_xarid", "tashrif", "orta_chek"]
).assign(segment=segment)
def barqarorlik(X, model_yaratuvchi, B: int = 10, seed: int = 0) -> float:
rng = np.random.default_rng(seed)
ballar = []
for _ in range(B):
a = rng.choice(len(X), int(len(X) * 0.7), replace=False)
b = rng.choice(len(X), int(len(X) * 0.7), replace=False)
umumiy = np.intersect1d(a, b)
ya = model_yaratuvchi().fit_predict(X[a])
yb = model_yaratuvchi().fit_predict(X[b])
# umumiy nuqtalar uchun indekslarni topish
ia = {v: i for i, v in enumerate(a)}
ib = {v: i for i, v in enumerate(b)}
ballar.append(adjusted_rand_score([ya[ia[v]] for v in umumiy],
[yb[ib[v]] for v in umumiy]))
return float(np.mean(ballar))
def main() -> None:
df = yarat()
nomlar = ["oylik_xarid", "tashrif", "orta_chek"]
Xs = StandardScaler().fit_transform(np.log1p(df[nomlar].to_numpy()))
haqiqiy = df["segment"].to_numpy()
nomzodlar = {
"KMeans(4)": lambda: KMeans(4, n_init=10, random_state=0),
"KMeans(6)": lambda: KMeans(6, n_init=10, random_state=0),
"Ward(4)": lambda: AgglomerativeClustering(4, linkage="ward"),
"GMM(4)": lambda: GaussianMixture(4, n_init=5, random_state=0),
"DBSCAN0.35-bob": lambda: DBSCAN(eps=0.35, min_samples=6),
}
print("=== 1. Baholash jadvali ===")
print(f" {'model':<14} {'qamrov':>8} {'silh':>8} {'DB':>7} {'CH':>8} "
f"{'barqaror':>10} {'eng kichik':>11}")
natijalar = {}
for nom, yaratuvchi in nomzodlar.items():
yorliq = yaratuvchi().fit_predict(Xs)
m = yorliq != -1
k = len(set(yorliq[m]))
if k < 2:
print(f" {nom:<14} (bitta klaster)")
continue
s = silhouette_score(Xs[m], yorliq[m])
db = davies_bouldin_score(Xs[m], yorliq[m])
ch = calinski_harabasz_score(Xs[m], yorliq[m])
b = barqarorlik(Xs, yaratuvchi, B=8)
kichik = np.bincount(yorliq[m] - yorliq[m].min()).min() / len(Xs)
natijalar[nom] = (yorliq, s, db, ch, b, m.mean())
print(f" {nom:<14} {m.mean():>7.1%} {s:>8.4f} {db:>7.4f} "
f"{ch:>8.1f} {b:>10.4f} {kichik:>10.1%}")
print("\n=== 2. Tashqi metrika (tekshirish uchun) ===")
print(f" {'model':<14} {'ARI':>9} {'gomojen':>9} {'to_liq':>9}")
from sklearn.metrics import homogeneity_completeness_v_measure
for nom, (yorliq, *_) in natijalar.items():
h, c, _ = homogeneity_completeness_v_measure(haqiqiy, yorliq)
print(f" {nom:<14} {adjusted_rand_score(haqiqiy, yorliq):>9.4f} "
f"{h:>9.4f} {c:>9.4f}")
print("\n=== 3. Eng yaxshi nomzodning silhouette diagrammasi ===")
eng = max(natijalar, key=lambda n: natijalar[n][4]) # barqarorlik
yorliq = natijalar[eng][0]
m = yorliq != -1
s = silhouette_samples(Xs[m], yorliq[m])
print(f" tanlangan: {eng} (barqarorlik {natijalar[eng][4]:.4f})")
print(f" {'klaster':>8} {'n':>6} {'ulush':>8} {'o_rtacha s':>12} "
f"{'manfiy':>8}")
for c in sorted(set(yorliq[m])):
mm = yorliq[m] == c
print(f" {c:>8} {int(mm.sum()):>6} {mm.mean():>7.1%} "
f"{s[mm].mean():>12.4f} {int((s[mm] < 0).sum()):>8}")
print("\n=== 4. Mazmun: markazlar asl birliklarda ===")
from sklearn.preprocessing import StandardScaler as SS
sc = SS().fit(np.log1p(df[nomlar].to_numpy()))
print(f" {'klaster':>8} {'n':>6} " + "".join(f"{n:>14}" for n in nomlar))
for c in sorted(set(yorliq[m])):
mm = (yorliq == c)
markaz = np.expm1(sc.inverse_transform(Xs[mm].mean(axis=0)[None, :]))[0]
print(f" {c:>8} {int(mm.sum()):>6} "
+ "".join(f"{markaz[i]:>14.1f}" for i in range(len(nomlar))))
print(" ⭐ Jadval + diagramma + mazmun = to'liq baho")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Baholash jadvali ===
model qamrov silh DB CH barqaror eng kichik
KMeans(4) 100.0% 0.7173 0.3993 10953.3 1.0000 14.6%
KMeans(6) 100.0% 0.4245 1.0667 8219.1 0.8392 12.7%
Ward(4) 100.0% 0.7173 0.3993 10953.3 0.9997 14.6%
GMM(4) 100.0% 0.7173 0.3993 10953.3 1.0000 14.6%
DBSCAN0.35-bob 99.8% 0.5470 0.6278 2873.6 0.8327 14.4%
=== 2. Tashqi metrika (tekshirish uchun) ===
model ARI gomojen to_liq
KMeans(4) 1.0000 1.0000 1.0000
KMeans(6) 0.6940 1.0000 0.7460
Ward(4) 1.0000 1.0000 1.0000
GMM(4) 1.0000 1.0000 1.0000
DBSCAN0.35-bob 0.5665 0.6573 0.9820
=== 3. Eng yaxshi nomzodning silhouette diagrammasi ===
tanlangan: KMeans(4) (barqarorlik 1.0000)
klaster n ulush o_rtacha s manfiy
0 746 29.8% 0.6731 0
1 492 19.7% 0.7733 0
2 898 35.9% 0.7258 0
3 364 14.6% 0.7112 0
=== 4. Mazmun: markazlar asl birliklarda ===
klaster n oylik_xarid tashrif orta_chek
0 746 398.9 9.1 45.2
1 492 94.2 16.0 6.0
2 898 129.9 3.0 50.5
3 364 955.0 5.1 192.7
⭐ Jadval + diagramma + mazmun = to'liq bahoNima ko'rsatdi: 2.6-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "Yuqori silhouette — yaxshi segmentatsiya" | Faqat geometriya |
| "Uch metrika kelishsa — to'g'ri" | Bir xil taxmin, bir xil xato |
| "NMI va AMI deyarli bir xil" | NMI k bilan o'sadi |
| "Shovqinni ham hisobga olish kerak" | -1 ni chiqaring |
| "ARI har doim ishlatiladi" | Faqat yorliq bo'lsa |
| "CH turli k ni taqqoslaydi" | k bilan o'sishga moyil |
| "Metrikalar qarorni hal qiladi" | Mazmun hal qiladi |
| "Silhouette arzon" | O(n^2) |
6. Keng tarqalgan xatolar va yechimlari
1. Shovqinni metrikaga qo'shish
silhouette_score(Xs, db_yorliq) # -1 alohida klaster # ⚠️
m = db_yorliq != -1; silhouette_score(Xs[m], db_yorliq[m]) # ✅2. Tuzatilmagan NMI
normalized_mutual_info_score(y, yorliq) # k=50 da sun'iy yuqori # ⚠️
adjusted_mutual_info_score(y, yorliq) # ✅3. Bitta metrikaga tayanish
# "silhouette 0.61 > 0.43, A yaxshiroq" # ⚠️
# jadval: silh + DB + CH + barqarorlik + o'lchamlar + mazmun # ✅4. Katta ma'lumotda to'liq silhouette
silhouette_score(X_500k, yorliq) # O(n^2) # ⚠️
silhouette_score(X_500k, yorliq, sample_size=10000, random_state=0) # ✅5. Turli masshtabda taqqoslash
# A: StandardScaler, B: MinMaxScaler -> silhouette larni taqqoslash # ⚠️
# bir xil tayyorlashda taqqoslang # ✅6. Qamrovni hisobga olmaslik
# DBSCAN 40% nuqtani klasterladi, silhouette 0.8 -> "eng yaxshi" # ⚠️
# qamrov va sifatni birga keltiring # ✅7. Yorliq bo'lsa ham klasterlash
adjusted_rand_score(y, KMeans(4).fit_predict(X)) # ⚠️
RandomForestClassifier().fit(X, y) # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 16.3-dars (o'tilgan): k ni tanlash
- 16.5-dars (o'tilgan): DBSCAN va shovqin
- 16.6-dars (o'tilgan): BIC
- 14.x-darslar (o'tilgan): Klassifikatsiya metrikalari
- 16.12-dars: Amaliyot
8. Eng yaxshi amaliyotlar
Jadval keltiring, bitta son emas.
Shovqinni chiqaring.
Qamrovni birga keltiring.
Tuzatilgan metrikalarni ishlating.
Silhouette diagrammasini ko'ring.
Barqarorlikni o'lchang.
Katta ma'lumotda sample_size.
Mazmun bilan yakunlang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # uch ichki metrika?
2. # ularning umumiy taxmini?
3. # silhouette formulasi?
4. # DB da katta yaxshimi?
5. # CH ning k ga moyilligi?
6. # ARI nima uchun "adjusted"?
7. # NMI ning muammosi?
8. # gomojenlik nima?
9. # to'liqlik-chi?
10. # shovqin bilan nima qilish kerak?
11. # katta ma'lumotda silhouette?
12. # yakuniy mezon?Javoblar
- Silhouette, Davies-Bouldin, Calinski-Harabasz
- Sferiklik
- (b-a)/max(a,b)
- Yo'q, kichik yaxshi
- k bilan o'sadi
- Tasodifga tuzatilgan
- k oshganda sun'iy o'sadi
- Har klaster bir sinfdanmi
- Har sinf bir klasterdami
- -1 ni chiqarish
- sample_size
- Mazmun va amaliy foyda
Vazifa 2: Xatolarni tuzating
1. silhouette_score(Xs, db_yorliq) # -1 bor
2. normalized_mutual_info_score(y, yorliq) # k=50
3. silhouette_score(X_500k, yorliq)
4. # "silhouette 0.61 > 0.43, A yaxshiroq"
5. adjusted_rand_score(y, KMeans(4).fit_predict(X)) # y borJavoblar
1. m = db_yorliq != -1; silhouette_score(Xs[m], db_yorliq[m])
2. adjusted_mutual_info_score(y, yorliq)
3. silhouette_score(X_500k, yorliq, sample_size=10000, random_state=0)
4. # to'liq jadval + barqarorlik + mazmun
5. RandomForestClassifier().fit(X, y)Vazifa 3: Ichki metrikalar
Modellang:
- Uch shakl
- Qaysi algoritm tanlanadi
- Kelishuv
- CH va k
Vazifa 4: Tuzatish
Modellang:
- Tasodifiy yorliqlar
- k = n
- Qisman to'g'ri
- Gomojenlik/to'liqlik
Vazifa 5: Shovqin
Modellang:
- Ikki hisoblash
- eps bo'yicha
- Halol taqqoslash
- Shovqin sifati
Vazifa 6: To'liq baho
Modellang:
- Jadval
- Tashqi metrika
- Diagramma
- Mazmun
Vazifa 7: O'ylash
Agar ichki metrikalar ishonchsiz bo'lsa va tashqi metrikalar yorliq talab qilsa, klasterlashni umuman obyektiv baholash mumkinmi?
Javob
Qisqa javob: to'liq obyektiv baho yo'q, lekin qisman obyektiv uch usul bor: barqarorlik, bashorat qobiliyati va eksperiment. Ular geometrik taxminlarga tayanmaydi va tekshiriladigan javob beradi.
1. Barqarorlik — eng kuchli obyektiv mezon
| Savol | Javob |
|---|---|
| Nima o'lchanadi | Natija ma'lumot o'zgarishiga chidamlimi |
| Taxminlar | Yo'q |
| Tekshiriladimi | Ha, takrorlash mumkin |
| Cheklovi | Barqaror natija mazmunli degani emas |
Beqaror klasterlash deyarli har doim yaroqsiz, barqaror esa zarur, lekin yetarli emas shart.
2. Bashorat qobiliyati
Klasterlarni yashirin o'zgaruvchi bilan tekshirish:
- Klasterlash faqat X_1 belgilar to'plamida bajariladi
- Klasterlar X_2 (ishlatilmagan) belgilarni bashorat qila oladimi?
- Agar ha — klasterlar haqiqiy tuzilmani aks ettiradi
- Bu "cross-validation for clustering" g'oyasi
Masalan: xarid xulqi bo'yicha segmentlash, so'ng segmentlar churn ni bashorat qiladimi tekshirish.
3. Eksperiment — oltin standart
- Segmentlarga turli harakat qo'llanadi
- Nazorat guruhi bilan taqqoslanadi
- Natija biznes metrikasida o'lchanadi
- Bu klasterlashni nazoratli masalaga aylantiradi
4. Amaliy kombinatsiya
1. Barqarorlik -> yaroqsiz nomzodlarni chiqarish
2. Ichki metrikalar -> geometrik sifatni ko'rish (ehtiyot bilan)
3. Bashorat testi -> klasterlar mazmunli ekanini tekshirish
4. Mazmun tahlili -> domen mutaxassisi bilan
5. Eksperiment -> yakuniy tasdiq5. Xulosa
- To'liq obyektiv baho yo'q
- Barqarorlik va bashorat qobiliyati taxminsiz ishlaydi
- Eksperiment yagona qat'iy javob
- Ichki metrikalar — yordamchi, hakam emas
Nimani mustahkamlaydi: 2.1, 2.6-bo'limlar.
Xulosa
Bu darsda klasterlashni baholashni o'rgandik.
Eng muhim uch fikr:
Ichki metrikalar algoritmning taxminini tekshiradi. Silhouette, Davies-Bouldin va Calinski-Harabasz — uchalasi ham geometrik va uchalasi ham sferiklikka moyil. Shuning uchun ular yarim oy shaklida DBSCAN ning to'g'ri javobini K-means ning noto'g'ri javobidan yomonroq baholaydi, va ularning kelishuvi to'g'rilikni isbotlamaydi — ular bir xil xatoni qiladi.
Tasodifga tuzatilgan variantni ishlating. Oddiy Rand Index va NMI
koshganda sun'iy o'sadi: har nuqtani o'z klasteriga qo'ysangiz, NMI = 1.0 chiqadi. ARI va AMI esa tasodifiy yorliqlarda ~0 beradi. Gomojenlik/to'liqlik juftligi esa muammo turini ko'rsatadi: klasterlar toza, lekin sinflar bo'lingan bo'lsa —kjuda katta.Shovqin bilan ikki son keltiring.
silhouette_score(X, yorliq)shovqinni (-1) alohida klaster deb sanaydi va natija mazmunsiz bo'ladi. To'g'risi: metrikani-1siz hisoblang va shovqin ulushini alohida keltiring — aks holda 60% ni shovqin deb belgilab, qolganida "mukammal" natija ko'rsatish mumkin. Yakuniy qarorni esa mazmun va amaliy foyda hal qiladi.
Keyingi darsda PCAni o'rganamiz: o'lchamni kamaytirishning asosiy usuli.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!