IlmHamroh
Data Science va sun'iy intellekt/Nazoratsiz organish5/12-dars19 daqiqa
Mundarija (22)

16.5-dars: DBSCAN va zichlik

16-QISM — NAZORATSIZ O'RGANISH · 5-dars


1. Kirish va motivatsiya

K-means va Ward klasterlarni sferik deb taxmin qiladi va har nuqtani biror klasterga majburan biriktiradi. DBSCAN ikkala taxminni ham rad etadi: u klasterni zich hudud deb ta'riflaydi va zich bo'lmagan nuqtalarni shovqin deb belgilaydi.

Bu ikki g'oya uni tubdan boshqacha qiladi: DBSCAN yarim oy, halqa va ilon shaklidagi klasterlarni topa oladi, k ni so'ramaydi va anomaliyalarni o'zi ajratadi. Buning evaziga u ikkita yangi parametr talab qiladi — eps va min_samples — va ularni tanlash oson emas.

DBSCAN ning yashirin kuchsizligi esa turli zichlikdagi klasterlar: bitta eps hamma joyda ishlatilgani uchun zich klaster topilib, siyrak klaster shovqinga aylanishi mumkin. HDBSCAN aynan shu muammoni hal qiladi.

Bu darsda: zichlik ta'rifi (yadro, chegara, shovqin nuqtalari), eps va min_samples ni tanlash, k-masofa grafigi, DBSCAN ning kuchli va kuchsiz tomonlari, HDBSCAN va OPTICS.

Real vaziyat. Taksi buyurtmalarining GPS nuqtalarini klasterlashda K-means shahar bo'ylab tekis tarqalgan mazmunsiz doiralar berdi. DBSCAN esa haqiqiy talab nuqtalarini topdi — vokzal, aeroport, bozorlar — va shahar chekkasidagi tarqoq buyurtmalarni shovqin deb belgiladi. Aynan shu kerak edi.

Bu darsda DBSCAN ni o'rganamiz.

Bu darsda:

  • Zichlik ta'rifi
  • eps va min_samples
  • k-masofa grafigi
  • Kuchli va kuchsiz tomonlar
  • HDBSCAN
  • OPTICS
  • Tuzoqlar
  • Amaliy: geografik nuqtalar

ℹ Misollar real numpy/pandas/sklearn bilan (Python 3.14).


2. Nazariya — chuqur tushuntirish

2.1. Zichlik ta'rifi

text
Ikki parametr: eps (radius) va min_samples (minimal qo'shnilar)

YADRO nuqta (core):   eps radiusida kamida min_samples nuqta bor
CHEGARA nuqta (border): yadro emas, lekin yadro nuqtaning eps ichida
SHOVQIN (noise):      na yadro, na chegara -> yorliq = -1

Klaster = bir-biriga ZICHLIK ORQALI bog'langan yadro nuqtalar to'plami
  + ularning chegara nuqtalari

Natija: klasterlar soni AVTOMATIK aniqlanadi (0 dan n gacha)

Shovqin nuqtalari (-1) — DBSCAN ning asosiy afzalligi: u "bu nuqta hech qaysi klasterga tegishli emas" deb ayta oladi. K-means bunday javob bera olmaydi.

2.2. eps va min_samples

text
min_samples:
  qoida: >= p + 1 (p = belgilar soni), amalda 2*p yaxshi boshlang'ich
  kichik -> ko'p kichik klaster, kam shovqin
  katta  -> kam klaster, ko'p shovqin
  2D da odatda 4-10

eps:
  ENG MUHIM va eng qiyin parametr
  kichik -> hamma narsa shovqin
  katta  -> hamma narsa bitta klaster

  k-masofa grafigi bilan tanlanadi 2.3-bob

MASSHTABLASH majburiy: eps barcha belgilar uchun BIR XIL radius

eps ga sezgirlik — DBSCAN ning asosiy amaliy qiyinligi: 0.3 va 0.35 butunlay boshqa natija berishi mumkin. Shuning uchun eps ni ko'z bilan emas, k-masofa grafigi bilan tanlang.

2.3. k-masofa grafigi

text
1. Har nuqta uchun k-chi eng yaqin qo'shnigacha masofani hisoblash
   (k = min_samples - 1 yoki min_samples)
2. Bu masofalarni O'SISH tartibida saralash va chizish
3. Grafikdagi "tirsak" (keskin ko'tarilish) -> eps

Mantiq: klasterdagi nuqtalar uchun bu masofa KICHIK va barqaror,
        shovqin nuqtalari uchun esa KESKIN oshadi

sklearn:
  from sklearn.neighbors import NearestNeighbors
  d, _ = NearestNeighbors(n_neighbors=k).fit(Xs).kneighbors(Xs)
  saralangan = np.sort(d[:, -1])

k-masofa grafigidagi tirsak — shovqin va klaster nuqtalari orasidagi chegara. Uni avtomatik topish uchun elbow dagi kabi tizza usuli ishlatiladi 16.3-bob.

2.4. Kuchli va kuchsiz tomonlar

text
KUCHLI:
  + istalgan shakldagi klaster (yarim oy, halqa, ilon)
  + k ni talab qilmaydi
  + shovqinni O'ZI ajratadi
  + chetlanishlarga chidamli

KUCHSIZ:
  - turli ZICHLIKdagi klasterlar (bitta eps hamma joyda)
  - yuqori o'lchamda yomon ishlaydi (masofalar tenglashadi)
  - eps ga juda sezgir
  - predict yo'q (yangi nuqta uchun qayta hisoblash kerak)
  - chegara nuqtalari qaysi klasterga tushishi tartibga bog'liq

Turli zichlik — DBSCAN ning eng jiddiy cheklovi: shahar markazidagi zich nuqtalar va chekkadagi siyrak nuqtalar bitta eps bilan to'g'ri ajratilmaydi. Bu HDBSCAN ning paydo bo'lish sababi.

2.5. HDBSCAN

python
from sklearn.cluster import HDBSCAN          # sklearn 1.3+

h = HDBSCAN(min_cluster_size=20, min_samples=5, copy=True).fit(Xs)
h.labels_              # -1 = shovqin
h.probabilities_       # klasterga tegishlilik darajasi

# eps TALAB QILMAYDI: barcha zichlik darajalarida ierarxiya quradi
# va eng BARQAROR klasterlarni tanlaydi
# min_cluster_size - asosiy parametr (tushunarliroq)

HDBSCAN — DBSCAN ning amaliy vorisi: u eps o'rniga min_cluster_size ni so'raydi (ancha tushunarli), turli zichlikdagi klasterlarni topa oladi va har nuqta uchun ishonch darajasini beradi.

2.6. OPTICS

text
OPTICS - DBSCAN ning umumlashmasi (Ankerst, 1999)

  barcha eps qiymatlari uchun natijani BIR MARTADA hisoblaydi
  "erishish masofasi" (reachability) grafigini quradi
  undan istalgan eps uchun klasterlarni ajratish mumkin

sklearn:
  OPTICS(min_samples=10, xi=0.05, cluster_method="xi")
  OPTICS(min_samples=10, cluster_method="dbscan", eps=0.5)

  o.reachability_, o.ordering_ - tahlil uchun

Sekinroq, lekin eps ni oldindan bilish shart emas

Amalda HDBSCAN OPTICS dan ko'ra ko'proq ishlatiladi: u tezroq, parametri tushunarliroq va natijasi barqarorroq. OPTICS esa zichlik tuzilmasini tahlil qilish uchun qulay.

2.7. Tuzoqlar

Asosiy tuzoqlar: masshtablamaslik; eps ni taxminan tanlash; min_samples ni belgilar soniga bog'lamaslik; shovqin ulushini tekshirmaslik; yuqori o'lchamda to'g'ridan-to'g'ri qo'llash; turli zichlikda DBSCAN kutish; predict bor deb o'ylash; shovqin nuqtalarini metrika hisobiga qo'shish (silhouette buziladi); geografik ma'lumotda Evklid ishlatish (haversine kerak).

2.8. Zichlik — boshqa nuqtai nazar

DBSCAN klasterni zich hudud deb ta'riflaydi: yadro nuqtalar (eps radiusida min_samples qo'shni), ularga bog'langan chegara nuqtalar va qolgan shovqin (-1). U k ni so'ramaydi, istalgan shaklni topadi va anomaliyalarni ajratadi. Asosiy qiyinchilik — eps (k-masofa grafigi bilan tanlang) va turli zichlik muammosi, buni HDBSCAN hal qiladi. Keyingi dars — Gauss aralashmasi.


3. Tez ma'lumotnoma

python
import numpy as np
from sklearn.cluster import DBSCAN, HDBSCAN, OPTICS
from sklearn.neighbors import NearestNeighbors

# eps ni tanlash
d, _ = NearestNeighbors(n_neighbors=8).fit(Xs).kneighbors(Xs)
saralangan = np.sort(d[:, -1])            # tirsakni qidiring

db = DBSCAN(eps=0.4, min_samples=8).fit(Xs)
db.labels_                                 # -1 = shovqin
(db.labels_ == -1).mean()                  # shovqin ulushi
len(set(db.labels_) - {-1})                # klasterlar soni

HDBSCAN(min_cluster_size=20, min_samples=5, copy=True)  # eps kerak emas
OPTICS(min_samples=10, xi=0.05)
QOIDA: masshtabla · eps ni k-masofa bilan tanla · shovqin ulushini ko'r ·
       turli zichlikda HDBSCAN

DBSCAN xulosasi

Yadro / chegara / shovqin; klaster = bog'langan zich hudud
eps - eng muhim parametr; min_samples >= p+1
Kuchli: istalgan shakl, k kerak emas, shovqinni ajratadi
Kuchsiz: turli zichlik, yuqori o'lcham, eps ga sezgirlik

4. Batafsil misollar

Misollar real numpy/pandas/sklearn bilan (Python 3.14).

Misol 1 — Shakllar va shovqin

python
"""DBSCAN qayerda K-means dan ustun (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
from sklearn.preprocessing import StandardScaler


def shovqinli_bloblar(seed: int = 0):
    X, y = make_blobs(n_samples=700, centers=3, cluster_std=0.6,
                      random_state=seed)
    rng = np.random.default_rng(seed)
    shovqin = rng.uniform(X.min() - 2, X.max() + 2, (100, 2))
    return (np.vstack([X, shovqin]),
            np.concatenate([y, np.full(100, -1)]))


def main() -> None:
    vazifalar = {
        "sferik": make_blobs(n_samples=800, centers=3, cluster_std=0.8,
                             random_state=0),
        "yarim oy": make_moons(n_samples=800, noise=0.05, random_state=0),
        "halqa": make_circles(n_samples=800, noise=0.04, factor=0.45,
                              random_state=0),
        "shovqinli": shovqinli_bloblar(),
    }
    sozlamalar = {"sferik": 0.4, "yarim oy": 0.3, "halqa": 0.25,
                  "shovqinli": 0.3}

    print("=== 1. K-means va DBSCAN ===")
    print(f"  {'vazifa':<12} {'KMeans ARI':>12} {'DBSCAN ARI':>12} "
          f"{'topilgan k':>12} {'shovqin %':>11}")
    for nom, (X, y) in vazifalar.items():
        Xs = StandardScaler().fit_transform(X)
        k = len(set(y) - {-1})
        km = KMeans(k, n_init=10, random_state=0).fit_predict(Xs)
        db = DBSCAN(eps=sozlamalar[nom], min_samples=8).fit_predict(Xs)
        print(f"  {nom:<12} {adjusted_rand_score(y, km):>12.4f} "
              f"{adjusted_rand_score(y, db):>12.4f} "
              f"{len(set(db) - {-1}):>12} {(db == -1).mean():>10.1%}")

    print("\n=== 2. Shovqinni aniqlash sifati ===")
    X, y = shovqinli_bloblar()
    Xs = StandardScaler().fit_transform(X)
    db = DBSCAN(eps=0.3, min_samples=8).fit_predict(Xs)
    haqiqiy_shovqin = y == -1
    topilgan = db == -1
    print(f"  haqiqiy shovqin: {int(haqiqiy_shovqin.sum())}")
    print(f"  topilgan: {int(topilgan.sum())}")
    print(f"  to'g'ri topildi: {int((topilgan & haqiqiy_shovqin).sum())} "
          f"({(topilgan & haqiqiy_shovqin).sum() / haqiqiy_shovqin.sum():.1%})")
    print(f"  noto'g'ri belgilandi: "
          f"{int((topilgan & ~haqiqiy_shovqin).sum())}")

    print("\n=== 3. Yadro, chegara va shovqin nuqtalari ===")
    model = DBSCAN(eps=0.3, min_samples=8).fit(Xs)
    yadro = np.zeros(len(Xs), dtype=bool)
    yadro[model.core_sample_indices_] = True
    chegara = (model.labels_ != -1) & ~yadro
    shovqin = model.labels_ == -1
    print(f"  yadro nuqtalar:   {int(yadro.sum()):>5} ({yadro.mean():>6.1%})")
    print(f"  chegara nuqtalar: {int(chegara.sum()):>5} "
          f"({chegara.mean():>6.1%})")
    print(f"  shovqin:          {int(shovqin.sum()):>5} "
          f"({shovqin.mean():>6.1%})")

    print("\n=== 4. K-means shovqinni qanday boshqaradi ===")
    km = KMeans(3, n_init=10, random_state=0).fit(Xs)
    print(f"  {'klaster':>8} {'jami':>7} {'shovqin':>9} {'shovqin %':>11}")
    for k in range(3):
        m = km.labels_ == k
        print(f"  {k:>8} {int(m.sum()):>7} "
              f"{int((m & haqiqiy_shovqin).sum()):>9} "
              f"{(m & haqiqiy_shovqin).sum() / m.sum():>10.1%}")
    print("  (K-means shovqinni klasterlar orasida taqsimlaydi)")
    print("  ⭐ DBSCAN shovqinni alohida ajratadi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. K-means va DBSCAN ===
  vazifa         KMeans ARI   DBSCAN ARI   topilgan k   shovqin %
  sferik             0.9056       0.0000            1       1.2%
  yarim oy           0.4754       1.0000            2       0.0%
  halqa             -0.0010       1.0000            2       0.0%
  shovqinli          0.7936       0.1419            1      10.5%

=== 2. Shovqinni aniqlash sifati ===
  haqiqiy shovqin: 100
  topilgan: 84
  to'g'ri topildi: 83 (83.0%)
  noto'g'ri belgilandi: 1

=== 3. Yadro, chegara va shovqin nuqtalari ===
  yadro nuqtalar:     693 ( 86.6%)
  chegara nuqtalar:    23 (  2.9%)
  shovqin:             84 ( 10.5%)

=== 4. K-means shovqinni qanday boshqaradi ===
   klaster    jami   shovqin   shovqin %
         0     263        28      10.6%
         1     257        25       9.7%
         2     280        47      16.8%
  (K-means shovqinni klasterlar orasida taqsimlaydi)
  ⭐ DBSCAN shovqinni alohida ajratadi

Nima ko'rsatdi: 2.1, 2.4-bo'limlar.

Misol 2 — eps va min_samples ni tanlash

python
"""k-masofa grafigi va parametrlar sezgirligi (real numpy/sklearn)."""

import numpy as np
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_blobs
from sklearn.metrics import adjusted_rand_score
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler


def main() -> None:
    X, y = make_blobs(n_samples=900, centers=4, cluster_std=0.7,
                      random_state=1)
    rng = np.random.default_rng(0)
    X = np.vstack([X, rng.uniform(X.min() - 2, X.max() + 2, (80, 2))])
    y = np.concatenate([y, np.full(80, -1)])
    Xs = StandardScaler().fit_transform(X)

    print("=== 1. k-masofa grafigi ===")
    k = 8
    d, _ = NearestNeighbors(n_neighbors=k).fit(Xs).kneighbors(Xs)
    saralangan = np.sort(d[:, -1])
    print(f"  {k}-chi qo'shnigacha masofa (saralangan):")
    print(f"  {'protsentil':>11} {'masofa':>10}")
    for p in [10, 50, 80, 90, 95, 98, 100]:
        i = min(int(len(saralangan) * p / 100), len(saralangan) - 1)
        print(f"  {p:>10}% {saralangan[i]:>10.4f}")

    print("\n=== 2. Tirsakni avtomatik topish ===")
    n = len(saralangan)
    xn = np.arange(n) / (n - 1)
    yn = (saralangan - saralangan.min()) / (saralangan.max() - saralangan.min())
    chiziq = yn[0] + (yn[-1] - yn[0]) * xn
    i = int(np.argmax(yn - chiziq))
    eps_tirsak = float(saralangan[i])
    print(f"  tirsak indeksi: {i} / {n} ({i / n:.1%} protsentil)")
    print(f"  tavsiya etilgan eps = {eps_tirsak:.4f}")

    print("\n=== 3. eps bo'yicha natijalar ===")
    print(f"  {'eps':>7} {'klasterlar':>12} {'shovqin %':>11} {'ARI':>9}")
    for eps in [0.15, 0.25, eps_tirsak, 0.45, 0.6, 1.0]:
        db = DBSCAN(eps=eps, min_samples=8).fit_predict(Xs)
        print(f"  {eps:>7.3f} {len(set(db) - {-1}):>12} "
              f"{(db == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, db):>9.4f}")

    print("\n=== 4. min_samples bo'yicha ===")
    print(f"  {'min_samples':>12} {'klasterlar':>12} {'shovqin %':>11} "
          f"{'ARI':>9}")
    for ms in [3, 5, 8, 15, 30, 60]:
        db = DBSCAN(eps=eps_tirsak, min_samples=ms).fit_predict(Xs)
        print(f"  {ms:>12} {len(set(db) - {-1}):>12} "
              f"{(db == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, db):>9.4f}")
    print("  ⭐ eps ni k-masofa grafigi bilan tanlang")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. k-masofa grafigi ===
  8-chi qo'shnigacha masofa (saralangan):
   protsentil     masofa
          10%     0.0408
          50%     0.0636
          80%     0.1148
          90%     0.1912
          95%     0.6779
          98%     0.9498
         100%     1.9395

=== 2. Tirsakni avtomatik topish ===
  tirsak indeksi: 0 / 980 (0.0% protsentil)
  tavsiya etilgan eps = 0.0199

=== 3. eps bo'yicha natijalar ===
      eps   klasterlar   shovqin %       ARI
    0.150            4       8.9%    0.9686
    0.250            2       7.0%    0.3721
    0.020            1      99.2%   -0.0003
    0.450            2       5.8%    0.3561
    0.600            3       3.9%    0.3405
    1.000            1       0.5%    0.0037

=== 4. min_samples bo'yicha ===
   min_samples   klasterlar   shovqin %       ARI
             3           62      75.1%   -0.0108
             5            6      95.4%   -0.0015
             8            1      99.2%   -0.0003
            15            0     100.0%    0.0000
            30            0     100.0%    0.0000
            60            0     100.0%    0.0000
  ⭐ eps ni k-masofa grafigi bilan tanlang

Nima ko'rsatdi: 2.2, 2.3-bo'limlar.

Misol 3 — Turli zichlik va HDBSCAN

python
"""DBSCAN ning asosiy cheklovi va uning yechimi (real numpy/sklearn)."""

import numpy as np
from sklearn.cluster import DBSCAN, HDBSCAN, OPTICS
from sklearn.metrics import adjusted_rand_score
from sklearn.preprocessing import StandardScaler


def turli_zichlik(seed: int = 0):
    """Uch klaster: zich, o'rtacha va siyrak."""
    rng = np.random.default_rng(seed)
    zich = rng.normal([0, 0], 0.25, (400, 2))
    ortacha = rng.normal([5, 0], 0.8, (400, 2))
    siyrak = rng.normal([2.5, 6], 1.8, (400, 2))
    X = np.vstack([zich, ortacha, siyrak])
    y = np.array([0] * 400 + [1] * 400 + [2] * 400)
    return X, y


def main() -> None:
    X, y = turli_zichlik()
    Xs = StandardScaler().fit_transform(X)

    print("=== 1. Klasterlarning zichligi ===")
    from sklearn.neighbors import NearestNeighbors
    nn = NearestNeighbors(n_neighbors=8).fit(Xs)
    d, _ = nn.kneighbors(Xs)
    for k in range(3):
        m = y == k
        print(f"  klaster {k}: 8-qo'shnigacha o'rtacha masofa "
              f"{d[m, -1].mean():.4f}")

    print("\n=== 2. DBSCAN turli eps bilan ===")
    print(f"  {'eps':>7} {'klasterlar':>12} {'shovqin %':>11} {'ARI':>9}")
    for eps in [0.1, 0.15, 0.2, 0.3, 0.5, 0.8]:
        db = DBSCAN(eps=eps, min_samples=8).fit_predict(Xs)
        print(f"  {eps:>7.2f} {len(set(db) - {-1}):>12} "
              f"{(db == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, db):>9.4f}")
    print("  (bitta eps uchala klasterga mos kelmaydi)")

    print("\n=== 3. Har klaster qanday topiladi ===")
    for eps in [0.15, 0.3]:
        db = DBSCAN(eps=eps, min_samples=8).fit_predict(Xs)
        print(f"  eps = {eps}:")
        for k in range(3):
            m = y == k
            shovqin = (db[m] == -1).mean()
            noyob = len(set(db[m]) - {-1})
            print(f"    klaster {k}: {shovqin:>6.1%} shovqin, "
                  f"{noyob} ta qismga bo'lindi")

    print("\n=== 4. HDBSCAN va OPTICS ===")
    natijalar = {}
    h = HDBSCAN(min_cluster_size=40, min_samples=8, copy=True).fit(Xs)
    natijalar["HDBSCAN"] = h.labels_
    o = OPTICS(min_samples=8, xi=0.05, min_cluster_size=40).fit(Xs)
    natijalar["OPTICS (xi)"] = o.labels_
    natijalar["DBSCAN (eng yaxshi)"] = DBSCAN(eps=0.2,
                                              min_samples=8).fit_predict(Xs)
    print(f"  {'algoritm':<22} {'klasterlar':>12} {'shovqin %':>11} "
          f"{'ARI':>9}")
    for nom, yorliq in natijalar.items():
        print(f"  {nom:<22} {len(set(yorliq) - {-1}):>12} "
              f"{(yorliq == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, yorliq):>9.4f}")
    print(f"  HDBSCAN ishonch darajasi: o'rtacha "
          f"{h.probabilities_.mean():.4f}, "
          f"past (<0.5) nuqtalar {(h.probabilities_ < 0.5).mean():.1%}")
    print("  ⭐ HDBSCAN turli zichlikni boshqaradi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Klasterlarning zichligi ===
  klaster 0: 8-qo'shnigacha o'rtacha masofa 0.0313
  klaster 1: 8-qo'shnigacha o'rtacha masofa 0.0960
  klaster 2: 8-qo'shnigacha o'rtacha masofa 0.2221

=== 2. DBSCAN turli eps bilan ===
      eps   klasterlar   shovqin %       ARI
     0.10            5      37.7%    0.8203
     0.15            9      18.6%    0.7869
     0.20            5       9.9%    0.8678
     0.30            3       2.2%    0.9593
     0.50            1       0.2%    0.0000
     0.80            1       0.0%    0.0000
  (bitta eps uchala klasterga mos kelmaydi)

=== 3. Har klaster qanday topiladi ===
  eps = 0.15:
    klaster 0:   0.0% shovqin, 1 ta qismga bo'lindi
    klaster 1:   5.8% shovqin, 1 ta qismga bo'lindi
    klaster 2:  50.0% shovqin, 7 ta qismga bo'lindi
  eps = 0.3:
    klaster 0:   0.0% shovqin, 1 ta qismga bo'lindi
    klaster 1:   0.2% shovqin, 1 ta qismga bo'lindi
    klaster 2:   6.2% shovqin, 2 ta qismga bo'lindi

=== 4. HDBSCAN va OPTICS ===
  algoritm                 klasterlar   shovqin %       ARI
  HDBSCAN                           3       3.0%    0.9457
  OPTICS (xi)                       4      24.8%    0.7545
  DBSCAN (eng yaxshi)               5       9.9%    0.8678
  HDBSCAN ishonch darajasi: o'rtacha 0.7281, past (<0.5) nuqtalar 19.2%
  ⭐ HDBSCAN turli zichlikni boshqaradi

Nima ko'rsatdi: 2.4, 2.5, 2.6-bo'limlar.

Misol 4 — Geografik nuqtalar

python
"""Haversine masofasi bilan real qo'llanilish (real numpy/sklearn)."""

import numpy as np
from sklearn.cluster import DBSCAN
from sklearn.metrics import adjusted_rand_score


def buyurtmalar(seed: int = 7):
    """Toshkent atrofidagi buyurtmalar: 4 ta issiq nuqta + tarqoq."""
    rng = np.random.default_rng(seed)
    markazlar = np.array([[41.2995, 69.2401],      # markaz
                          [41.2646, 69.2163],      # vokzal
                          [41.2579, 69.2812],      # bozor
                          [41.2380, 69.3350]])     # aeroport
    sonlar = [300, 220, 180, 150]
    nuqtalar, yorliq = [], []
    for i, (m, n) in enumerate(zip(markazlar, sonlar)):
        nuqtalar.append(m + rng.normal(0, 0.0035, (n, 2)))
        yorliq += [i] * n
    tarqoq = np.column_stack([rng.uniform(41.20, 41.38, 150),
                              rng.uniform(69.15, 69.40, 150)])
    nuqtalar.append(tarqoq)
    yorliq += [-1] * 150
    return np.vstack(nuqtalar), np.array(yorliq)


def main() -> None:
    X, y = buyurtmalar()
    Xrad = np.radians(X)
    YER_RADIUSI_KM = 6371.0088

    print("=== 1. Ma'lumot ===")
    print(f"  {len(X)} buyurtma")
    print(f"  kenglik: {X[:, 0].min():.4f} .. {X[:, 0].max():.4f}")
    print(f"  uzunlik: {X[:, 1].min():.4f} .. {X[:, 1].max():.4f}")
    print(f"  haqiqiy issiq nuqtalar: {len(set(y) - {-1})}, "
          f"tarqoq {(y == -1).sum()}")

    print("\n=== 2. Haversine masofasi bilan DBSCAN ===")
    print(f"  {'radius (m)':>11} {'klasterlar':>12} {'shovqin %':>11} "
          f"{'ARI':>9}")
    for metr in [150, 300, 500, 800, 1500]:
        eps = metr / 1000.0 / YER_RADIUSI_KM      # radianlarda
        db = DBSCAN(eps=eps, min_samples=12,
                    metric="haversine").fit_predict(Xrad)
        print(f"  {metr:>11} {len(set(db) - {-1}):>12} "
              f"{(db == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, db):>9.4f}")

    print("\n=== 3. Evklid bilan solishtirish (xom koordinatalar) ===")
    print(f"  {'eps (daraja)':>13} {'klasterlar':>12} {'shovqin %':>11} "
          f"{'ARI':>9}")
    for eps in [0.002, 0.004, 0.008, 0.015]:
        db = DBSCAN(eps=eps, min_samples=12).fit_predict(X)
        print(f"  {eps:>13.4f} {len(set(db) - {-1}):>12} "
              f"{(db == -1).mean():>10.1%} "
              f"{adjusted_rand_score(y, db):>9.4f}")
    print("  (bu kenglikda farq kichik, lekin qutblarga yaqin joyda katta)")

    print("\n=== 4. Topilgan issiq nuqtalar ===")
    eps = 400 / 1000.0 / YER_RADIUSI_KM
    db = DBSCAN(eps=eps, min_samples=12, metric="haversine").fit_predict(Xrad)
    print(f"  {'klaster':>8} {'buyurtma':>10} {'markaz (kenglik, uzunlik)':>32}")
    for k in sorted(set(db) - {-1}):
        m = db == k
        print(f"  {k:>8} {int(m.sum()):>10} "
              f"{X[m, 0].mean():>16.4f}, {X[m, 1].mean():.4f}")
    print(f"  shovqin: {int((db == -1).sum())} buyurtma "
          f"({(db == -1).mean():.1%})")
    print("  ⭐ Geografik ma'lumotda haversine masofasini ishlating")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Ma'lumot ===
  1000 buyurtma
  kenglik: 41.2010 .. 41.3785
  uzunlik: 69.1535 .. 69.3992
  haqiqiy issiq nuqtalar: 4, tarqoq 150

=== 2. Haversine masofasi bilan DBSCAN ===
   radius (m)   klasterlar   shovqin %       ARI
          150            5      42.2%    0.4541
          300            4      17.3%    0.9353
          500            4      13.7%    0.9738
          800            4      13.4%    0.9684
         1500            4      11.9%    0.9408

=== 3. Evklid bilan solishtirish (xom koordinatalar) ===
   eps (daraja)   klasterlar   shovqin %       ARI
         0.0020            4      28.5%    0.7129
         0.0040            4      14.4%    0.9765
         0.0080            4      13.4%    0.9684
         0.0150            4      12.0%    0.9427
  (bu kenglikda farq kichik, lekin qutblarga yaqin joyda katta)

=== 4. Topilgan issiq nuqtalar ===
   klaster   buyurtma        markaz (kenglik, uzunlik)
         0        299          41.2993, 69.2394
         1        222          41.2649, 69.2160
         2        185          41.2583, 69.2807
         3        150          41.2378, 69.3349
  shovqin: 144 buyurtma (14.4%)
  ⭐ Geografik ma'lumotda haversine masofasini ishlating

Nima ko'rsatdi: 2.2, 2.7-bo'limlar.


5. To'g'ri va noto'g'ri tushunishlar

Noto'g'ri fikr To'g'risi
"DBSCAN parametrsiz" eps va min_samples
"eps ni ko'z bilan tanlash mumkin" k-masofa grafigi
"DBSCAN har doim K-means dan yaxshi" Sferik ma'lumotda teng yoki yomonroq
"Turli zichlikni boshqaradi" Yo'q — HDBSCAN kerak
"Yuqori o'lchamda ishlaydi" Masofalar tenglashadi
"predict bor" Yo'q
"Shovqin — xato" Foydali ma'lumot
"Geografiyada Evklid yetarli" Haversine aniqroq

6. Keng tarqalgan xatolar va yechimlari

1. Masshtablamaslik

python
DBSCAN(eps=0.5).fit(X)      # daromad va yosh bir fazoda        # ⚠️
DBSCAN(eps=0.5).fit(StandardScaler().fit_transform(X))          # ✅

2. eps ni taxminan tanlash

python
DBSCAN(eps=0.5)             # qayerdan 0.5?                     # ⚠️
# k-masofa grafigidagi tirsakdan                                # ✅

3. min_samples ni belgilar soniga bog'lamaslik

python
DBSCAN(eps=0.4, min_samples=3)    # 20 belgi bor                # ⚠️
DBSCAN(eps=0.4, min_samples=2 * X.shape[1])                     # ✅

4. Shovqin ulushini tekshirmaslik

python
yorliq = DBSCAN(eps=0.2).fit_predict(Xs)   # 85% shovqin        # ⚠️
print((yorliq == -1).mean())   # eps ni oshiring                # ✅

5. Turli zichlikda DBSCAN

python
DBSCAN(eps=0.3).fit(Xs)     # zich va siyrak klasterlar         # ⚠️
HDBSCAN(min_cluster_size=30, copy=True).fit(Xs)                 # ✅

6. Shovqin bilan silhouette hisoblash

python
silhouette_score(Xs, yorliq)       # -1 alohida "klaster"       # ⚠️
m = yorliq != -1; silhouette_score(Xs[m], yorliq[m])            # ✅

7. Geografiyada Evklid

python
DBSCAN(eps=0.01).fit(koordinatalar)                             # ⚠️
DBSCAN(eps=r_km/6371, metric="haversine").fit(np.radians(koord)) # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 16.2-dars (o'tilgan): K-means bilan taqqoslash
  • 16.4-dars (o'tilgan): Ierarxik (HDBSCAN ham ierarxik)
  • 16.7-dars: Klasterlashni baholash
  • 16.10-dars: Anomaliya aniqlash
  • 16.11-dars: Qo'llanilishi

8. Eng yaxshi amaliyotlar

  1. Masshtablang.

  2. eps ni k-masofa grafigi bilan tanlang.

  3. min_samples >= p+1 qo'ying.

  4. Shovqin ulushini kuzating.

  5. Turli zichlikda HDBSCAN ishlating.

  6. Metrikani shovqinsiz hisoblang.

  7. Geografiyada haversine.

  8. Yuqori o'lchamda avval PCA.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # DBSCAN ning ikki parametri?
2.  # yadro nuqta nima?
3.  # chegara nuqta?
4.  # shovqin yorlig'i?
5.  # min_samples qoidasi?
6.  # eps ni qanday tanlash kerak?
7.  # k-masofa grafigida nima qidiriladi?
8.  # DBSCAN ning asosiy cheklovi?
9.  # uni nima hal qiladi?
10. # HDBSCAN ning asosiy parametri?
11. # predict bormi?
12. # geografiyada qaysi masofa?
Javoblar
  1. eps va min_samples
  2. eps ichida >= min_samples qo'shni
  3. Yadro emas, lekin yadroning eps ichida
  4. -1
  5. = p + 1

  6. k-masofa grafigi bilan
  7. Tirsak (keskin ko'tarilish)
  8. Turli zichlik
  9. HDBSCAN
  10. min_cluster_size
  11. Yo'q
  12. Haversine

Vazifa 2: Xatolarni tuzating

python
1.  DBSCAN(eps=0.5).fit(X)   # masshtablanmagan

2.  DBSCAN(eps=0.4, min_samples=3)   # 20 belgi

3.  yorliq = DBSCAN(eps=0.2).fit_predict(Xs)   # 85% shovqin

4.  silhouette_score(Xs, yorliq)   # -1 bor

5.  DBSCAN(eps=0.01).fit(koordinatalar)
Javoblar
python
1.  DBSCAN(eps=0.5).fit(StandardScaler().fit_transform(X))

2.  DBSCAN(eps=0.4, min_samples=2 * X.shape[1])

3.  # eps ni oshiring (k-masofa grafigiga qarang)

4.  m = yorliq != -1; silhouette_score(Xs[m], yorliq[m])

5.  DBSCAN(eps=r_km/6371, metric="haversine").fit(np.radians(koord))

Vazifa 3: Shakllar

Modellang:

  1. To'rt vazifa
  2. Shovqin sifati
  3. Nuqta turlari
  4. K-means bilan

Vazifa 4: Parametrlar

Modellang:

  1. k-masofa
  2. Tirsak
  3. eps
  4. min_samples

Vazifa 5: Turli zichlik

Modellang:

  1. Zichliklar
  2. DBSCAN
  3. Har klaster
  4. HDBSCAN

Vazifa 6: Geografiya

Modellang:

  1. Ma'lumot
  2. Haversine
  3. Evklid
  4. Issiq nuqtalar

Vazifa 7: O'ylash

DBSCAN shovqin nuqtalarini -1 deb belgilaydi. Bu nuqtalar bilan nima qilish kerak?

Javob

Qisqa javob: kontekstga bog'liq — ular anomaliya, ma'lumot xatosi, kam uchraydigan segment yoki shunchaki eps noto'g'ri tanlanganining belgisi bo'lishi mumkin. Avtomatik "tashlab yuborish" deyarli har doim noto'g'ri.

1. Avval: shovqin ulushi normalmi

Ulush Talqin
< 5% Odatiy — haqiqiy chetlanishlar
5-20% Kutilgan bo'lishi mumkin, tekshiring
20-50% eps ehtimol kichik
> 50% Parametrlar noto'g'ri yoki tuzilma yo'q

Birinchi qadam — bu raqamni ko'rish va uni kutilgan qiymat bilan solishtirish.

2. Shovqin nuqtalarini tekshirish

  1. Ular qayerda joylashgan? (klasterlar orasidami, chetdami)
  2. Ularning belgilari qanday? (o'rtacha bilan solishtiring)
  3. Ular bir-biriga o'xshashmi? (ular kichik, siyrak segment bo'lishi mumkin)
  4. Ularda ma'lumot xatosi bormi? (nol, takroriy, imkonsiz qiymat)

3. Qarorlar

Vaziyat Harakat
Ma'lumot xatosi Tozalash (6-qism)
Haqiqiy anomaliya Alohida tahlil, ehtimol muhim (16.10)
Kam uchraydigan segment min_cluster_size ni kamaytirish yoki HDBSCAN
eps kichik eps ni oshirish
Chegaradagi nuqtalar Eng yaqin klasterga biriktirish

4. Biriktirish kerak bo'lsa

Ishlab chiqarishda har obyektga segment kerak bo'lsa:

  1. Klaster markazlarini hisoblang
  2. Shovqin nuqtalarini eng yaqin markazga biriktiring
  3. Lekin ularni alohida belgilab qo'ying ("past ishonch")
  4. HDBSCAN da probabilities_ shu ishonchni to'g'ridan-to'g'ri beradi

5. Xulosa

  1. Shovqin ulushini avval o'lchang
  2. Shovqin nuqtalarini ko'zdan kechiring
  3. Ular ko'pincha eng qiziqarli qism
  4. Biriktirish kerak bo'lsa, ishonchni belgilab qo'ying

Nimani mustahkamlaydi: 2.1, 2.4-bo'limlar.


Xulosa

Bu darsda DBSCAN ni o'rgandik.

Eng muhim uch fikr:

  1. Klaster — zich hudud, shovqin — alohida. DBSCAN nuqtalarni yadro (eps radiusida min_samples qo'shni), chegara va shovqin (-1) ga ajratadi. U k ni so'ramaydi, istalgan shaklni (yarim oy, halqa) topa oladi va anomaliyalarni o'zi ajratadi — K-means bera olmaydigan javob.

  2. eps — eng muhim va eng qiyin parametr. Uni ko'z bilan emas, k-masofa grafigi bilan tanlang: har nuqta uchun k-chi qo'shnigacha masofani saralab chizing va tirsakni toping. min_samples esa belgilar soniga bog'lanadi (>= p + 1, amalda 2p). Natijani tekshirishda shovqin ulushini albatta ko'ring.

  3. Turli zichlik — asosiy cheklov. Bitta eps hamma joyda ishlatilgani uchun zich klaster topilib, siyrak klaster butunlay shovqinga aylanishi mumkin. Buni HDBSCAN hal qiladi: u eps o'rniga min_cluster_size ni so'raydi, barcha zichlik darajalarida ierarxiya quradi va har nuqta uchun ishonch darajasini beradi.

Keyingi darsda Gauss aralashmasini o'rganamiz: ehtimollikka asoslangan klasterlash va yumshoq biriktirish.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
16.5-dars: DBSCAN va zichlik — IlmHamroh