14-bo‘lim
Klasterlash
K-means, ierarxik klasterlash va DBSCAN - javobsiz ma'lumotdan guruhlarni topish.
Ushbu bo‘lim mundarijasi
Endi nazoratsiz o'qitishga o'tamiz: bizda javoblar yo'q, model ma'lumotdagi tuzilmani o'zi topishi kerak.
Klasterlash nima? #
Qo'llanilishi:
| Soha | Vazifa |
|---|---|
| Marketing | Mijozlarni segmentlarga bo'lish |
| Tibbiyot | Bemorlarni o'xshash guruhlarga ajratish |
| Xavfsizlik | Odatiy bo'lmagan xatti-harakatni topish |
| Kontent | Maqolalarni mavzular bo'yicha guruhlash |
| Logistika | Yetkazish hududlarini belgilash |
| Rasm | Ranglarni kamaytirish, siqish |
K-means #
Eng mashhur klasterlash algoritmi.
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
np.random.seed(42)
mijozlar = pd.DataFrame({
"yosh": np.concatenate([
np.random.normal(25, 4, 100),
np.random.normal(45, 6, 100),
np.random.normal(60, 5, 100),
]),
"yillik_xarid": np.concatenate([
np.random.normal(2, 0.6, 100),
np.random.normal(8, 1.5, 100),
np.random.normal(5, 1.2, 100),
]),
"tashrif_soni": np.concatenate([
np.random.normal(30, 8, 100),
np.random.normal(12, 4, 100),
np.random.normal(6, 2, 100),
]),
})
masshtab = StandardScaler()
X = masshtab.fit_transform(mijozlar)
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
mijozlar["guruh"] = kmeans.fit_predict(X)
print(mijozlar.groupby("guruh").mean().round(1))
print(mijozlar["guruh"].value_counts().sort_index())
yosh yillik_xarid tashrif_soni
guruh
0 25.1 2.0 29.8
1 45.3 8.1 11.9
2 59.8 5.0 6.1
guruh
0 100
1 100
2 99
Model raqamlar berdi, ma'nosini siz topasiz:
| Guruh | Xarakteristika | Nom |
|---|---|---|
| 0 | Yosh, kam xarid, tez-tez keladi | Yosh tadqiqotchilar |
| 1 | O'rta yosh, katta xarid | Asosiy mijozlar |
| 2 | Katta yosh, kam tashrif | Kamdan-kam xaridorlar |
Endi marketing bo'limi har bir guruh uchun alohida taklif tayyorlaydi.
K-means Yevklid masofasi bilan ishlaydi.
yosh 20-70, yillik_xarid 1-10 oralig'ida bo'lsa, guruhlar deyarli
faqat yosh bo'yicha shakllanadi.
k ni qanday tanlash? #
Algoritm klaster sonini o'zi topa olmaydi - uni siz berasiz.
Tirsak usuli #
inersiya = []
k_qiymatlari = range(1, 11)
for k in k_qiymatlari:
model = KMeans(n_clusters=k, random_state=42, n_init=10)
model.fit(X)
inersiya.append(model.inertia_)
for k, qiymat in zip(k_qiymatlari, inersiya):
print(f"k={k}: {qiymat:8.1f}")
k=1: 900.0
k=2: 448.2
k=3: 206.5
k=4: 178.3
k=5: 156.1
k=6: 140.2
Har bir nuqtaning o'z klaster markazigacha bo'lgan masofasi kvadratlari yig'indisi.
k oshgani sari u har doim kamayadi. k = n bo'lsa nolga teng
bo'ladi - lekin bunday "klasterlash" foydasiz.
Shuning uchun eng kichik inersiyani emas, tirsakni qidiramiz.
Siluet koeffitsiyenti #
Aniqroq usul:
from sklearn.metrics import silhouette_score
for k in range(2, 8):
model = KMeans(n_clusters=k, random_state=42, n_init=10)
belgilar = model.fit_predict(X)
ball = silhouette_score(X, belgilar)
print(f"k={k}: siluet = {ball:.3f}")
k=2: siluet = 0.478
k=3: siluet = 0.612
k=4: siluet = 0.481
k=5: siluet = 0.412
k=6: siluet = 0.385
k=7: siluet = 0.361
| Siluet | Ma'nosi |
|---|---|
1.0 ga yaqin | Klasterlar aniq ajralgan |
0.5 atrofida | Qoniqarli tuzilma |
0 ga yaqin | Klasterlar bir-biriga tegib turibdi |
| Manfiy | Nuqtalar noto'g'ri klasterga tushgan |
Tirsak ba'zan noaniq bo'ladi ("egilish qayerda?"). Siluet esa aniq
raqam beradi - eng yuqori qiymatli k ni tanlaysiz.
K-means kamchiliklari #
| Kamchilik | Yechim |
|---|---|
k ni oldindan berish kerak | Tirsak, siluet |
| Faqat sharsimon klasterlar | DBSCAN, GMM |
| Boshlang'ich markazlarga sezgir | n_init=10 (standart) |
| Chetdagi qiymatlarga sezgir | Avval ularni tozalash |
| Masshtablash majburiy | StandardScaler |
Ierarxik klasterlash #
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
import matplotlib.pyplot as plt
model = AgglomerativeClustering(n_clusters=3, linkage="ward")
belgilar = model.fit_predict(X)
# Dendrogramma
bogliqlik = linkage(X[:50], method="ward")
plt.figure(figsize=(12, 5))
dendrogram(bogliqlik)
plt.title("Dendrogramma")
plt.xlabel("Namunalar")
plt.ylabel("Masofa")
plt.show()
linkage | Qanday o'lchaydi |
|---|---|
ward | Ichki tarqoqlikni minimallashtiradi (standart) |
complete | Eng uzoq juftlik masofasi |
average | O'rtacha masofa |
single | Eng yaqin juftlik masofasi |
k ni oldindan berish shart emas - dendrogrammani ko'rib, keyin
qaror qabul qilasiz.
Kamchiligi: O(n³) murakkablik - 10 000 dan ko'p namunada juda sekin.
DBSCAN #
Zichlikka asoslangan klasterlash.
from sklearn.cluster import DBSCAN
model = DBSCAN(eps=0.5, min_samples=5)
belgilar = model.fit_predict(X)
print(f"Klasterlar: {len(set(belgilar)) - (1 if -1 in belgilar else 0)}")
print(f"Shovqin nuqtalari: {list(belgilar).count(-1)}")
Klasterlar: 3
Shovqin nuqtalari: 12
kni berish shart emas - o'zi topadi- Istalgan shakldagi klasterlarni topa oladi
- Chetdagi qiymatlarni
-1deb belgilaydi - anomaliya aniqlash uchun ajoyib
Ikki parametr:
| Parametr | Ma'nosi |
|---|---|
eps | Qo'shni deb hisoblanadigan maksimal masofa |
min_samples | Zich hudud uchun minimal nuqtalar soni |
# eps ni tanlash uchun
from sklearn.neighbors import NearestNeighbors
izlovchi = NearestNeighbors(n_neighbors=5).fit(X)
masofalar, _ = izlovchi.kneighbors(X)
beshinchi = np.sort(masofalar[:, 4])
plt.plot(beshinchi)
plt.ylabel("5-qo'shnigacha masofa")
plt.title("eps ni tirsak nuqtasidan tanlang")
plt.show()
Agar bir klaster zich, ikkinchisi siyrak bo'lsa, bitta eps ikkalasiga
ham mos kelmaydi.
Bunday holatda HDBSCAN ni sinab ko'ring - u zichlik farqini
o'zi hisobga oladi.
Uchta usulni solishtirish #
| K-means | Ierarxik | DBSCAN | |
|---|---|---|---|
k kerakmi | Ha | Yo'q (keyin tanlanadi) | Yo'q |
| Klaster shakli | Sharsimon | Har xil | Har xil |
| Chetdagi qiymatlar | Klasterga qo'shiladi | Klasterga qo'shiladi | Alohida belgilanadi |
| Tezlik | Juda tez | Sekin | O'rtacha |
| Katta ma'lumot | Ha | Yo'q | Qisman |
| Takrorlanuvchanlik | random_state bilan | Ha | Ha |
Amaliy misol - rasm siqish #
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
rasm = mpimg.imread("rasm.jpg")
shakl = rasm.shape
# Har bir piksel - RGB nuqta
piksellar = rasm.reshape(-1, 3)
# 16 ta asosiy rangga qisqartiramiz
kmeans = KMeans(n_clusters=16, random_state=42, n_init=10)
kmeans.fit(piksellar)
yangi_piksellar = kmeans.cluster_centers_[kmeans.labels_]
siqilgan = yangi_piksellar.reshape(shakl).astype("uint8")
print(f"Asl ranglar: {len(np.unique(piksellar, axis=0))}")
print(f"Siqilgan: 16")
Asl ranglar: 147832
Siqilgan: 16
Rasm 147 832 rangdan 16 rangga qisqardi - hajmi sezilarli kamaydi, lekin ko'rinishi tanib bo'ladigan darajada qoldi.
GIF formati aynan shu prinsipda ishlaydi.
Klasterlash natijasini baholash #
from sklearn.metrics import (
silhouette_score, calinski_harabasz_score, davies_bouldin_score,
)
belgilar = KMeans(n_clusters=3, random_state=42, n_init=10).fit_predict(X)
print(f"Siluet: {silhouette_score(X, belgilar):.3f} (yuqori yaxshi)")
print(f"Calinski-Harabasz: {calinski_harabasz_score(X, belgilar):.1f} (yuqori yaxshi)")
print(f"Davies-Bouldin: {davies_bouldin_score(X, belgilar):.3f} (past yaxshi)")
Metrikalar foydali, lekin yakuniy savol boshqa:
"Bu guruhlar biznes uchun ma'noli va foydalimi?"
Agar marketing bo'limi topilgan segmentlar bilan ishlay olsa - klasterlash
muvaffaqiyatli. Siluet 0.72 bo'lgani bilan guruhlar tushunarsiz bo'lsa -
foydasi yo'q.
- Uch guruhli sun'iy mijozlar ma'lumotini yarating.
- Masshtablang va K-means bilan klasterlang.
- Har bir guruhning o'rtacha ko'rsatkichlarini chiqaring.
- Guruhlarga ma'noli nom bering.
- Tirsak usuli grafigini chizing.
- Siluet koeffitsiyentini 2 dan 8 gacha hisoblang.
- Masshtablashsiz klasterlang - natija qanday o'zgardi?
AgglomerativeClusteringbilan solishtiring va dendrogramma chizing.DBSCANbilan sinang,epsni sozlang, shovqin nuqtalarini sanang.- Ikki belgi bilan klasterlarni rangli nuqtali diagrammada chizing.
Xulosa #
- Klasterlash - javobsiz ma'lumotdan guruhlarni topish.
- Model guruhlarni topadi, ma'nosini siz berasiz.
- K-means: markazlarni tasodifiy qo'y, biriktir, ko'chir, takrorla.
- Masshtablash majburiy - algoritm masofa bilan ishlaydi.
- Tirsak usuli va siluet koeffitsiyenti
kni tanlashga yordam beradi. - Siluet aniqroq: eng yuqori qiymatli
kni tanlang. - K-means faqat sharsimon klasterlarni topadi.
- Ierarxik klasterlash dendrogramma beradi,
kni keyin tanlaysiz. - DBSCAN
kni talab qilmaydi, istalgan shaklni topadi va chetdagi qiymatlarni belgilaydi. - Yakuniy baho - metrika emas, amaliy foyda.
Keyingi bo'limda o'lchamni kamaytirishni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.