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

16.9-dars: Nochiziqli o'lchamni kamaytirish

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


1. Kirish va motivatsiya

PCA — chiziqli: u ma'lumotni tekislikka proyeksiya qiladi. Lekin real ma'lumotlar ko'pincha egri sirtda (manifoldda) yotadi: qo'lda yozilgan raqamlar, yuz tasvirlari, matn vektorlari. Bunday holda PCA ikki o'lchamli tasvirda hamma narsani aralashtirib yuboradi.

t-SNE va UMAP boshqa g'oyaga asoslanadi: ular qo'shnilikni saqlashga harakat qiladi — yuqori o'lchamda yaqin bo'lgan nuqtalar past o'lchamda ham yaqin bo'lsin. Natija — klasterlar aniq ajralgan, chiroyli va ishonarli ko'rinadigan diagrammalar.

Aynan shu "ishonarlilik" xavfli: t-SNE diagrammasidagi klasterlar orasidagi masofa, klaster o'lchamlari va zichlik ko'pincha ma'nosiz. Ularni talqin qilish — nazoratsiz o'rganishdagi eng keng tarqalgan xatolardan biri.

Bu darsda: manifold g'oyasi, t-SNE (perplexity, KL divergensiya), UMAP bilan farqi, sklearn dagi muqobillar (Isomap, LLE, MDS, SpectralEmbedding), diagrammani to'g'ri o'qish va amaliy qoidalar.

Real vaziyat. Jamoa t-SNE diagrammasida ikki klaster juda uzoq joylashganini ko'rib, "bu segmentlar tubdan farq qiladi" degan xulosa chiqardi va alohida mahsulot yo'nalishi ochdi. Asl fazoda esa bu klasterlar qo'shni edi — t-SNE ularni tasodifan uzoqqa joylashtirgan. Loyiha olti oyda yopildi.

Bu darsda nochiziqli o'lchamni kamaytirishni o'rganamiz.

Bu darsda:

  • Manifold g'oyasi
  • t-SNE va uning tuzoqlari
  • perplexity va boshqa parametrlar
  • UMAP bilan farq
  • sklearn dagi muqobillar
  • Diagrammani to'g'ri o'qish
  • Tuzoqlar
  • Amaliy: raqamlar ma'lumoti

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


2. Nazariya — chuqur tushuntirish

2.1. Manifold g'oyasi

text
MANIFOLD taxmini: yuqori o'lchamli ma'lumot aslida PAST o'lchamli
egri sirtda yotadi

  misol: 64x64 piksel (4096 o'lcham) yuz tasvirlari
         lekin haqiqiy erkinlik darajalari: burchak, yorug'lik, ifoda ~ 10 ta

PCA: sirtni TEKISLIK deb taxmin qiladi -> egri sirtda yomon ishlaydi
Manifold usullari: mahalliy QO'SHNILIKni saqlashga harakat qiladi

Klassik misol: "shveytsar rulosi" (swiss roll)
  PCA rulodagi uzoq nuqtalarni yaqin deb ko'rsatadi
  Isomap/t-SNE rulodagi haqiqiy masofani ochadi

Mahalliy qo'shnilik — barcha manifold usullarining umumiy g'oyasi: global tuzilma qurbon qilinadi, mahalliy tuzilma saqlanadi. Shuning uchun ular vizualizatsiya uchun yaxshi, masofa hisoblash uchun emas.

2.2. t-SNE

text
1. Yuqori o'lchamda har nuqta juftligi uchun O'XSHASHLIK EHTIMOLLIGI
   (Gauss yadrosi bilan, perplexity kengligini belgilaydi)
2. Past o'lchamda ham shunday ehtimollik (t-taqsimot bilan - "og'ir dum")
3. Ikki taqsimot orasidagi KL divergensiyani minimallashtirish
   (gradient tushish bilan)

t-taqsimot NEGA: og'ir dum uzoq nuqtalarni ko'proq itaradi
  -> "siqilish muammosi" (crowding problem) hal bo'ladi
  -> klasterlar aniq ajraladi

NATIJA: har ishga tushirishda BOSHQACHA (tasodifiy boshlang'ich)
  random_state majburiy

t-SNE — optimallashtirish, proyeksiya emas: uning transform() metodi yo'q. Yangi nuqtani mavjud tasvirga qo'shish uchun butun algoritmni qayta ishga tushirish kerak.

2.3. perplexity va boshqa parametrlar

text
perplexity (5 - 50, standart 30):
  "har nuqtaning nechta qo'shnisi hisobga olinadi" ning yumshoq o'lchovi
  kichik -> mahalliy tuzilma, ko'p kichik klaster
  katta  -> global tuzilma, klasterlar birlashadi
  QOIDA: perplexity < n / 3

learning_rate (sklearn 1.2+ "auto" = n/12):
  juda kichik -> nuqtalar zich to'pga yig'iladi
  juda katta  -> tarqoq bulut

n_iter / max_iter (>= 250, standart 1000):
  yetarli bo'lmasa - tugallanmagan tuzilma

init="pca" (sklearn standarti):
  tasodifiy boshlang'ichdan YAXSHIROQ - global tuzilmani qisman saqlaydi

perplexity ni bir necha qiymatda sinang (5, 30, 50): agar tuzilma qiymatdan qiymatga butunlay o'zgarsa, u haqiqiy emas. Barqaror ko'rinadigan naqshlargina ishonchli.

2.4. UMAP bilan farq

text
                     t-SNE               UMAP
nazariy asos         ehtimollik/KL       topologiya/qo'shnilik grafi
tezlik               sekin (O(n log n))  ancha tez
global tuzilma       yomon saqlanadi     yaxshiroq saqlanadi
transform()          yo'q                BOR (yangi nuqta qo'shish mumkin)
parametrlar          perplexity          n_neighbors, min_dist
katta ma'lumot       100k gacha          millionlab

UMAP alohida kutubxona: pip install umap-learn
sklearn da yo'q; eng yaqin muqobil - SpectralEmbedding yoki Isomap

UMAP ning transform() metodi bor — bu uni ishlab chiqarishda t-SNE dan ancha amaliy qiladi: bir marta o'qitib, yangi nuqtalarni mavjud tasvirga joylashtirish mumkin.

2.5. sklearn dagi muqobillar

python
from sklearn.manifold import (MDS, TSNE, Isomap, LocallyLinearEmbedding,
                              SpectralEmbedding)

Isomap(n_neighbors=10, n_components=2)
  # qo'shnilik grafida GEODEZIK masofa -> global tuzilmani saqlaydi
  # transform() BOR

LocallyLinearEmbedding(n_neighbors=12, n_components=2)
  # har nuqtani qo'shnilarining chiziqli kombinatsiyasi sifatida
  # transform() bor; shovqinga sezgir

MDS(n_components=2, normalized_stress="auto")
  # masofalarni saqlashga harakat qiladi; transform() yo'q; sekin

SpectralEmbedding(n_components=2, n_neighbors=10)
  # graf Laplasiani; spektral klasterlash bilan bog'liq

Isomap — t-SNE ga yaxshi muqobil: u global tuzilmani saqlaydi (masofalar ma'noga ega) va transform() ga ega, lekin egri manifoldlarda t-SNE dan kamroq "chiroyli" ko'rinadi.

2.6. Diagrammani to'g'ri o'qish

text
t-SNE/UMAP diagrammasida NIMA MA'NOGA EGA:
  + nuqtalar bir klasterga yig'ilganmi (mahalliy qo'shnilik)
  + klasterlar bir-biridan ajralganmi

NIMA MA'NOGA EGA EMAS:
  - klasterlar orasidagi MASOFA
  - klasterlarning O'LCHAMI (zichlik sun'iy tenglashtiriladi)
  - klasterlarning JOYLASHUVI va burilishi
  - klaster ICHIDAGI shakl

TEKSHIRUV:
  1. bir necha perplexity/seed bilan takrorlang
  2. barqaror naqshlargina ishonchli
  3. xulosani ASL fazoda tasdiqlang (masofa, klasterlash, metrika)

Xulosani asl fazoda tasdiqlash — yagona ishonchli qoida: t-SNE gipoteza beradi, uni asl belgilar fazosida tekshirish kerak.

2.7. Tuzoqlar

Asosiy tuzoqlar: klasterlararo masofani talqin qilish; klaster o'lchamini "segment hajmi" deb qabul qilish; random_state qo'ymaslik; bitta perplexity bilan cheklanish; t-SNE fazosida klasterlash qilish (masofalar buzilgan); masshtablamaslik; juda katta ma'lumotda to'g'ridan-to'g'ri qo'llash (avval PCA); transform() bor deb o'ylash; t-SNE ni belgi muhandisligi uchun ishlatish.

2.8. Qo'shnilik saqlanadi, masofa emas

t-SNE va UMAP mahalliy qo'shnilikni saqlaydi va klasterlarni aniq ajratadi — lekin klasterlararo masofa, o'lcham va joylashuv ma'noga ega emas. perplexity ni bir necha qiymatda sinang va faqat barqaror naqshlarga ishoning. t-SNE da transform() yo'q, UMAP va Isomap da bor. Har qanday xulosani asl fazoda tasdiqlang. Keyingi dars — anomaliya aniqlash.


3. Tez ma'lumotnoma

python
from sklearn.decomposition import PCA
from sklearn.manifold import MDS, TSNE, Isomap, SpectralEmbedding
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

# katta ma'lumotda: avval PCA, keyin t-SNE
Z50 = PCA(n_components=50, random_state=0).fit_transform(Xs)
Z2 = TSNE(n_components=2, perplexity=30, init="pca", learning_rate="auto",
          random_state=0).fit_transform(Z50)

iso = Isomap(n_neighbors=10, n_components=2).fit(Xs)
iso.transform(Xyangi)             # t-SNE da bunday imkoniyat YO'Q

# barqarorlikni tekshirish
for p in [5, 30, 50]:
    TSNE(perplexity=p, random_state=0).fit_transform(Z50)
QOIDA: masshtabla · avval PCA · perplexity ni sinab ko'r ·
       masofani talqin qilma

Nochiziqli usullar xulosasi

Manifold: mahalliy qo'shnilik saqlanadi, global tuzilma qurbon qilinadi
t-SNE: KL divergensiya, perplexity, transform() yo'q
UMAP: tezroq, global tuzilma yaxshiroq, transform() bor
Diagrammada masofa, o'lcham va joylashuv MA'NOSIZ

4. Batafsil misollar

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

Misol 1 — PCA va manifold usullari

python
"""Egri manifoldda chiziqli usul qanday ishlaydi (real numpy/sklearn)."""

import numpy as np
from sklearn.datasets import make_s_curve, make_swiss_roll
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE, Isomap, LocallyLinearEmbedding
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler


def qoshnilik_saqlanishi(Xyuqori, Zpast, k: int = 12) -> float:
    """Yuqori o'lchamdagi k qo'shnining qanchasi pastda ham qo'shni."""
    nn1 = NearestNeighbors(n_neighbors=k + 1).fit(Xyuqori)
    nn2 = NearestNeighbors(n_neighbors=k + 1).fit(Zpast)
    _, i1 = nn1.kneighbors(Xyuqori)
    _, i2 = nn2.kneighbors(Zpast)
    ulush = [len(set(a[1:]) & set(b[1:])) / k for a, b in zip(i1, i2)]
    return float(np.mean(ulush))


def main() -> None:
    X, rang = make_swiss_roll(n_samples=1200, noise=0.05, random_state=0)
    Xs = StandardScaler().fit_transform(X)

    print("=== 1. Shveytsar rulosi ===")
    print(f"  {len(X)} nuqta, {X.shape[1]} o'lcham")
    print(f"  rang (manifold bo'ylab pozitsiya): {rang.min():.2f} .. "
          f"{rang.max():.2f}")

    print("\n=== 2. Qo'shnilik saqlanishi ===")
    usullar = {
        "PCA": PCA(n_components=2, random_state=0),
        "Isomap": Isomap(n_neighbors=10, n_components=2),
        "LLE": LocallyLinearEmbedding(n_neighbors=12, n_components=2,
                                      random_state=0),
        "t-SNE": TSNE(n_components=2, perplexity=30, init="pca",
                      learning_rate="auto", random_state=0),
    }
    natijalar = {}
    print(f"  {'usul':<10} {'qo_shnilik (k=12)':>20} {'rang korrelyatsiyasi':>23}")
    for nom, model in usullar.items():
        Z = model.fit_transform(Xs)
        natijalar[nom] = Z
        q = qoshnilik_saqlanishi(Xs, Z)
        # manifold pozitsiyasi ikki o'lchamdan biri bilan bog'liqmi
        korr = max(abs(np.corrcoef(rang, Z[:, i])[0, 1]) for i in range(2))
        print(f"  {nom:<10} {q:>20.4f} {korr:>23.4f}")

    print("\n=== 3. PCA rulodagi uzoq nuqtalarni yaqin qiladimi ===")
    Zpca = natijalar["PCA"]
    # manifold bo'ylab eng uzoq juftliklar
    nn = NearestNeighbors(n_neighbors=6).fit(Zpca)
    _, qoshni = nn.kneighbors(Zpca)
    rang_farqi = np.array([np.abs(rang[i] - rang[qoshni[i, 1:]]).mean()
                           for i in range(len(X))])
    print(f"  PCA da qo'shni bo'lgan nuqtalarning manifold bo'ylab "
          f"o'rtacha farqi: {rang_farqi.mean():.3f}")
    for nom in ["Isomap", "t-SNE"]:
        nn2 = NearestNeighbors(n_neighbors=6).fit(natijalar[nom])
        _, q2 = nn2.kneighbors(natijalar[nom])
        rf = np.array([np.abs(rang[i] - rang[q2[i, 1:]]).mean()
                       for i in range(len(X))])
        print(f"  {nom} da: {rf.mean():.3f}")
    print("  (kichik farq = manifold to'g'ri ochilgan)")

    print("\n=== 4. S-egri shaklda ===")
    X2, rang2 = make_s_curve(n_samples=1200, noise=0.05, random_state=0)
    X2s = StandardScaler().fit_transform(X2)
    print(f"  {'usul':<10} {'qo_shnilik':>12} {'rang korr':>12}")
    for nom, model in usullar.items():
        Z = model.fit_transform(X2s)
        q = qoshnilik_saqlanishi(X2s, Z)
        korr = max(abs(np.corrcoef(rang2, Z[:, i])[0, 1]) for i in range(2))
        print(f"  {nom:<10} {q:>12.4f} {korr:>12.4f}")
    print("  ⭐ Manifold usullari mahalliy qo'shnilikni saqlaydi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Shveytsar rulosi ===
  1200 nuqta, 3 o'lcham
  rang (manifold bo'ylab pozitsiya): 4.72 .. 14.14

=== 2. Qo'shnilik saqlanishi ===
  usul          qo_shnilik (k=12)    rang korrelyatsiyasi
  PCA                      0.4642                  0.2567
  Isomap                   0.8638                  0.9915
  LLE                      0.6467                  0.9925
  t-SNE                    0.8653                  0.9250

=== 3. PCA rulodagi uzoq nuqtalarni yaqin qiladimi ===
  PCA da qo'shni bo'lgan nuqtalarning manifold bo'ylab o'rtacha farqi: 1.262
  Isomap da: 0.087
  t-SNE da: 0.085
  (kichik farq = manifold to'g'ri ochilgan)

=== 4. S-egri shaklda ===
  usul         qo_shnilik    rang korr
  PCA              0.4657       0.5253
  Isomap           0.8769       0.9990
  LLE              0.5178       0.8988
  t-SNE            0.8585       0.9881
  ⭐ Manifold usullari mahalliy qo'shnilikni saqlaydi

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

Misol 2 — t-SNE tuzoqlari

python
"""Diagrammadagi nima ma'noga ega emas (real numpy/sklearn)."""

import numpy as np
from sklearn.datasets import make_blobs
from sklearn.manifold import TSNE
from sklearn.metrics import pairwise_distances
from sklearn.preprocessing import StandardScaler


def uch_klaster(seed: int = 0):
    """Ikki klaster yaqin, uchinchisi juda uzoq."""
    rng = np.random.default_rng(seed)
    a = rng.normal([0, 0], 0.6, (300, 2))
    b = rng.normal([3, 0], 0.6, (300, 2))          # a ga yaqin
    c = rng.normal([40, 0], 0.6, (300, 2))         # juda uzoq
    X = np.vstack([a, b, c])
    y = np.array([0] * 300 + [1] * 300 + [2] * 300)
    return X, y


def turli_olcham(seed: int = 0):
    rng = np.random.default_rng(seed)
    a = rng.normal([0, 0], 0.5, (600, 2))
    b = rng.normal([6, 0], 2.0, (150, 2))          # kam nuqta, keng tarqoq
    X = np.vstack([a, b])
    return X, np.array([0] * 600 + [1] * 150)


def klaster_masofasi(Z, y):
    markazlar = np.array([Z[y == k].mean(axis=0) for k in np.unique(y)])
    return pairwise_distances(markazlar)


def main() -> None:
    print("=== 1. Klasterlararo masofa saqlanadimi ===")
    X, y = uch_klaster()
    Xs = StandardScaler().fit_transform(X)
    asl = klaster_masofasi(Xs, y)
    print(f"  asl fazoda: 0-1 {asl[0, 1]:.3f}, 0-2 {asl[0, 2]:.3f}, "
          f"nisbat {asl[0, 2] / asl[0, 1]:.2f}")
    for seed in [0, 1, 2]:
        Z = TSNE(2, perplexity=30, init="pca", learning_rate="auto",
                 random_state=seed).fit_transform(Xs)
        m = klaster_masofasi(Z, y)
        print(f"  t-SNE (seed {seed}): 0-1 {m[0, 1]:.2f}, 0-2 {m[0, 2]:.2f}, "
              f"nisbat {m[0, 2] / m[0, 1]:.2f}")
    print("  (asl nisbat ~13, t-SNE da ancha kichik)")

    print("\n=== 2. Klaster o'lchami saqlanadimi ===")
    X, y = turli_olcham()
    Xs = StandardScaler().fit_transform(X)
    for nom, Za in [("asl fazo", Xs),
                    ("t-SNE", TSNE(2, perplexity=30, init="pca",
                                   learning_rate="auto",
                                   random_state=0).fit_transform(Xs))]:
        radius = [np.linalg.norm(Za[y == k] - Za[y == k].mean(axis=0),
                                 axis=1).mean() for k in [0, 1]]
        print(f"  {nom:<10}: klaster radiuslari "
              f"{radius[0]:.3f} va {radius[1]:.3f}, "
              f"nisbat {radius[1] / radius[0]:.2f}")
    print("  (t-SNE zichlikni tenglashtiradi)")

    print("\n=== 3. perplexity ta'siri ===")
    X, y = make_blobs(n_samples=900, centers=4, cluster_std=1.0,
                      random_state=3)
    Xs = StandardScaler().fit_transform(X)
    from sklearn.neighbors import NearestNeighbors
    print(f"  {'perplexity':>11} {'qo_shnilik':>12} {'klaster ajralishi':>19}")
    for p in [5, 15, 30, 60]:
        Z = TSNE(2, perplexity=p, init="pca", learning_rate="auto",
                 random_state=0).fit_transform(Xs)
        nn1 = NearestNeighbors(n_neighbors=11).fit(Xs)
        nn2 = NearestNeighbors(n_neighbors=11).fit(Z)
        _, i1 = nn1.kneighbors(Xs)
        _, i2 = nn2.kneighbors(Z)
        q = np.mean([len(set(a[1:]) & set(b[1:])) / 10
                     for a, b in zip(i1, i2)])
        m = klaster_masofasi(Z, y)
        ichki = np.mean([np.linalg.norm(Z[y == k] - Z[y == k].mean(axis=0),
                                        axis=1).mean() for k in range(4)])
        ajralish = m[np.triu_indices(4, 1)].mean() / ichki
        print(f"  {p:>11} {q:>12.4f} {ajralish:>19.3f}")

    print("\n=== 4. Tuzilmasiz ma'lumotda t-SNE ===")
    rng = np.random.default_rng(0)
    Xr = StandardScaler().fit_transform(rng.normal(0, 1, (600, 20)))
    from sklearn.cluster import KMeans
    from sklearn.metrics import silhouette_score
    print(f"  {'fazo':<18} {'silhouette (k=4)':>18}")
    print(f"  {'asl (20 o_lcham)':<18} "
          f"{silhouette_score(Xr, KMeans(4, n_init=10, random_state=0).fit_predict(Xr)):>18.4f}")
    for p in [5, 30]:
        Z = TSNE(2, perplexity=p, init="pca", learning_rate="auto",
                 random_state=0).fit_transform(Xr)
        s = silhouette_score(Z, KMeans(4, n_init=10,
                                       random_state=0).fit_predict(Z))
        print(f"  {'t-SNE (p=' + str(p) + ')':<18} {s:>18.4f}")
    print("  (t-SNE tuzilmasiz ma'lumotda ham 'klasterlar' yaratadi)")
    print("  ⭐ Diagrammadagi masofa va o'lcham ma'nosiz")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Klasterlararo masofa saqlanadimi ===
  asl fazoda: 0-1 0.180, 0-2 2.203, nisbat 12.26
  t-SNE (seed 0): 0-1 1.58, 0-2 32.89, nisbat 20.85
  t-SNE (seed 1): 0-1 1.58, 0-2 32.89, nisbat 20.85
  t-SNE (seed 2): 0-1 1.58, 0-2 32.89, nisbat 20.85
  (asl nisbat ~13, t-SNE da ancha kichik)

=== 2. Klaster o'lchami saqlanadimi ===
  asl fazo  : klaster radiuslari 0.427 va 1.860, nisbat 4.36
  t-SNE     : klaster radiuslari 18.763 va 8.185, nisbat 0.44
  (t-SNE zichlikni tenglashtiradi)

=== 3. perplexity ta'siri ===
   perplexity   qo_shnilik   klaster ajralishi
            5       0.7362               2.728
           15       0.8209               5.092
           30       0.8531               6.967
           60       0.8626               9.802

=== 4. Tuzilmasiz ma'lumotda t-SNE ===
  fazo                 silhouette (k=4)
  asl (20 o_lcham)               0.0384
  t-SNE (p=5)                    0.3562
  t-SNE (p=30)                   0.3463
  (t-SNE tuzilmasiz ma'lumotda ham 'klasterlar' yaratadi)
  ⭐ Diagrammadagi masofa va o'lcham ma'nosiz

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

Misol 3 — Raqamlar ma'lumotida taqqoslash

python
"""Real ma'lumotda beshta usul (real numpy/sklearn)."""

import numpy as np
from sklearn.cluster import KMeans
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.manifold import MDS, TSNE, Isomap, SpectralEmbedding
from sklearn.metrics import adjusted_rand_score, silhouette_score
from sklearn.neighbors import KNeighborsClassifier, NearestNeighbors
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler


def qoshnilik(Xa, Za, k: int = 10) -> float:
    n1 = NearestNeighbors(n_neighbors=k + 1).fit(Xa)
    n2 = NearestNeighbors(n_neighbors=k + 1).fit(Za)
    _, i1 = n1.kneighbors(Xa)
    _, i2 = n2.kneighbors(Za)
    return float(np.mean([len(set(a[1:]) & set(b[1:])) / k
                          for a, b in zip(i1, i2)]))


def main() -> None:
    raqamlar = load_digits()
    idx = np.random.default_rng(0).choice(len(raqamlar.data), 900,
                                          replace=False)
    X, y = raqamlar.data[idx], raqamlar.target[idx]
    Xs = StandardScaler().fit_transform(X)

    print("=== 1. Ma'lumot ===")
    print(f"  {X.shape[0]} tasvir, {X.shape[1]} piksel (8x8)")
    print(f"  {len(np.unique(y))} sinf, har birida "
          f"~{int(np.bincount(y).mean())} ta")

    print("\n=== 2. PCA bilan oldindan siqish ===")
    p = PCA(random_state=0).fit(Xs)
    jamlangan = np.cumsum(p.explained_variance_ratio_)
    for chegara in [0.80, 0.90, 0.95]:
        k = int(np.searchsorted(jamlangan, chegara) + 1)
        print(f"  {chegara:.0%} dispersiya: {k} komponent")
    Z40 = PCA(n_components=40, random_state=0).fit_transform(Xs)
    print(f"  t-SNE uchun 40 komponent ishlatiladi "
          f"({jamlangan[39]:.1%} dispersiya)")

    print("\n=== 3. Ikki o'lchamli tasvirlar ===")
    usullar = {
        "PCA": lambda: PCA(2, random_state=0).fit_transform(Xs),
        "Isomap": lambda: Isomap(n_neighbors=10, n_components=2)
                          .fit_transform(Z40),
        "Spectral": lambda: SpectralEmbedding(2, n_neighbors=10,
                                              random_state=0)
                            .fit_transform(Z40),
        "t-SNE(30)": lambda: TSNE(2, perplexity=30, init="pca",
                                  learning_rate="auto", random_state=0)
                             .fit_transform(Z40),
    }
    print(f"  {'usul':<12} {'qo_shnilik':>12} {'silhouette':>12} "
          f"{'KMeans ARI':>12}")
    tasvirlar = {}
    for nom, yaratuvchi in usullar.items():
        Z = yaratuvchi()
        tasvirlar[nom] = Z
        yorliq = KMeans(10, n_init=10, random_state=0).fit_predict(Z)
        print(f"  {nom:<12} {qoshnilik(Xs, Z):>12.4f} "
              f"{silhouette_score(Z, y):>12.4f} "
              f"{adjusted_rand_score(y, yorliq):>12.4f}")

    print("\n=== 4. Asl fazoda klasterlash bilan solishtirish ===")
    yorliq_asl = KMeans(10, n_init=10, random_state=0).fit_predict(Z40)
    print(f"  asl fazoda (40 komp): ARI "
          f"{adjusted_rand_score(y, yorliq_asl):.4f}")
    print(f"  t-SNE fazosida:       ARI "
          f"{adjusted_rand_score(y, KMeans(10, n_init=10, random_state=0).fit_predict(tasvirlar['t-SNE(30)'])):.4f}")
    print("  (t-SNE fazosida ARI yuqori, lekin bu ALDAMCHI:")
    print("   t-SNE allaqachon klasterlarni ajratib qo'ygan)")
    knn_asl = cross_val_score(KNeighborsClassifier(5), Z40, y, cv=3).mean()
    knn_tsne = cross_val_score(KNeighborsClassifier(5),
                               tasvirlar["t-SNE(30)"], y, cv=3).mean()
    print(f"  KNN aniqligi: asl fazo {knn_asl:.4f}, "
          f"t-SNE fazosi {knn_tsne:.4f}")
    print("  ⭐ t-SNE fazosida klasterlash natijani sun'iy yaxshilaydi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Ma'lumot ===
  900 tasvir, 64 piksel (8x8)
  10 sinf, har birida ~90 ta

=== 2. PCA bilan oldindan siqish ===
  80% dispersiya: 19 komponent
  90% dispersiya: 29 komponent
  95% dispersiya: 38 komponent
  t-SNE uchun 40 komponent ishlatiladi (96.0% dispersiya)

=== 3. Ikki o'lchamli tasvirlar ===
  usul           qo_shnilik   silhouette   KMeans ARI
  PCA                0.1722       0.0404       0.3152
  Isomap             0.2631       0.2286       0.5395
  Spectral           0.3523       0.2829       0.5431
  t-SNE(30)          0.6017       0.3735       0.6748

=== 4. Asl fazoda klasterlash bilan solishtirish ===
  asl fazoda (40 komp): ARI 0.5184
  t-SNE fazosida:       ARI 0.6748
  (t-SNE fazosida ARI yuqori, lekin bu ALDAMCHI:
   t-SNE allaqachon klasterlarni ajratib qo'ygan)
  KNN aniqligi: asl fazo 0.9544, t-SNE fazosi 0.9622
  ⭐ t-SNE fazosida klasterlash natijani sun'iy yaxshilaydi

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

Misol 4 — Barqarorlik va transform

python
"""Natija takrorlanadimi va yangi nuqta qo'shish (real numpy/sklearn)."""

import numpy as np
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE, Isomap
from sklearn.neighbors import NearestNeighbors
from sklearn.preprocessing import StandardScaler


def qoshnilik_kelishuvi(Za, Zb, k: int = 10) -> float:
    """Ikki tasvirdagi qo'shnilik qanchalik mos."""
    n1 = NearestNeighbors(n_neighbors=k + 1).fit(Za)
    n2 = NearestNeighbors(n_neighbors=k + 1).fit(Zb)
    _, i1 = n1.kneighbors(Za)
    _, i2 = n2.kneighbors(Zb)
    return float(np.mean([len(set(a[1:]) & set(b[1:])) / k
                          for a, b in zip(i1, i2)]))


def main() -> None:
    raqamlar = load_digits()
    # tezlik uchun namunaning bir qismi (t-SNE bir necha marta ishlaydi)
    idx = np.random.default_rng(0).choice(len(raqamlar.data), 700,
                                          replace=False)
    Xs = StandardScaler().fit_transform(raqamlar.data[idx])
    y = raqamlar.target[idx]
    Z40 = PCA(n_components=30, random_state=0).fit_transform(Xs)

    print("=== 1. Turli seed lar bilan t-SNE ===")
    tasvirlar = []
    for seed in range(2):
        tasvirlar.append(TSNE(2, perplexity=30, init="pca",
                              learning_rate="auto",
                              random_state=seed).fit_transform(Z40))
    print(f"  {'juftlik':<10} {'qo_shnilik kelishuvi':>22}")
    for i in range(2):
        for j in range(i + 1, 2):
            print(f"  seed {i}-{j:<4} "
                  f"{qoshnilik_kelishuvi(tasvirlar[i], tasvirlar[j]):>22.4f}")

    print("\n=== 2. Klaster markazlari joylashuvi ===")
    for i, Z in enumerate(tasvirlar):
        markazlar = np.array([Z[y == k].mean(axis=0) for k in range(10)])
        # 0-raqamdan eng uzoq raqam qaysi
        masofa = np.linalg.norm(markazlar - markazlar[0], axis=1)
        eng_uzoq = int(np.argsort(-masofa)[0])
        eng_yaqin = int(np.argsort(masofa)[1])
        print(f"  seed {i}: 0 dan eng uzoq raqam {eng_uzoq}, "
              f"eng yaqin {eng_yaqin}")
    print("  (seed o'zgarsa joylashuv o'zgaradi)")

    print("\n=== 3. perplexity bo'yicha barqarorlik ===")
    p_tasvirlar = {}
    for p in [5, 30]:
        p_tasvirlar[p] = TSNE(2, perplexity=p, init="pca",
                              learning_rate="auto",
                              random_state=0).fit_transform(Z40)
    print(f"  {'juftlik':<12} {'kelishuv':>10}")
    kalitlar = list(p_tasvirlar)
    for i in range(len(kalitlar)):
        for j in range(i + 1, len(kalitlar)):
            print(f"  p={kalitlar[i]} va p={kalitlar[j]:<4} "
                  f"{qoshnilik_kelishuvi(p_tasvirlar[kalitlar[i]], p_tasvirlar[kalitlar[j]]):>10.4f}")

    print("\n=== 4. transform: Isomap bor, t-SNE da yo'q ===")
    Xtr, Xte = Z40[:500], Z40[500:]
    iso = Isomap(n_neighbors=10, n_components=2).fit(Xtr)
    Zte = iso.transform(Xte)
    print(f"  Isomap: {len(Xtr)} nuqtada o'qitildi, "
          f"{len(Xte)} yangi nuqta joylashtirildi")
    # yangi nuqtalar to'g'ri joyga tushdimi
    Ztr = iso.transform(Xtr)
    markazlar = np.array([Ztr[y[:500] == k].mean(axis=0) for k in range(10)])
    bashorat = np.argmin(((Zte[:, None, :] - markazlar[None]) ** 2).sum(axis=2),
                         axis=1)
    print(f"  yangi nuqtalar eng yaqin markazga to'g'ri tushdi: "
          f"{(bashorat == y[500:]).mean():.1%}")
    print(f"  t-SNE da transform metodi bormi: "
          f"{hasattr(TSNE(), 'transform')}")
    print("  ⭐ t-SNE ni ishlab chiqarishda ishlatib bo'lmaydi")


if __name__ == "__main__":
    main()

Natijaning muhim qismi:

text
=== 1. Turli seed lar bilan t-SNE ===
  juftlik      qo_shnilik kelishuvi
  seed 0-1                    1.0000

=== 2. Klaster markazlari joylashuvi ===
  seed 0: 0 dan eng uzoq raqam 3, eng yaqin 6
  seed 1: 0 dan eng uzoq raqam 3, eng yaqin 6
  (seed o'zgarsa joylashuv o'zgaradi)

=== 3. perplexity bo'yicha barqarorlik ===
  juftlik        kelishuv
  p=5 va p=30       0.6836

=== 4. transform: Isomap bor, t-SNE da yo'q ===
  Isomap: 500 nuqtada o'qitildi, 200 yangi nuqta joylashtirildi
  yangi nuqtalar eng yaqin markazga to'g'ri tushdi: 71.5%
  t-SNE da transform metodi bormi: False
  ⭐ t-SNE ni ishlab chiqarishda ishlatib bo'lmaydi

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


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

Noto'g'ri fikr To'g'risi
"Klasterlararo masofa muhim" Ma'nosiz
"Klaster o'lchami segment hajmi" Zichlik tenglashtiriladi
"t-SNE natijasi barqaror" Seed va perplexity ga bog'liq
"t-SNE fazosida klasterlash yaxshi" Sun'iy yaxshi natija
"t-SNE da transform bor" Yo'q
"UMAP va t-SNE bir xil" UMAP tezroq, transform bor
"t-SNE klaster borligini isbotlaydi" Tuzilmasiz ma'lumotda ham yaratadi
"Masshtablash shart emas" Shart

6. Keng tarqalgan xatolar va yechimlari

1. Masofani talqin qilish

python
# "A va B klasterlari juda uzoq, demak tubdan farq qiladi"        # ⚠️
# asl fazoda markazlar orasidagi masofani o'lchang                # ✅

2. random_state ni qo'ymaslik

python
TSNE(n_components=2)                                              # ⚠️
TSNE(n_components=2, random_state=0)                              # ✅

3. Bitta perplexity

python
TSNE(perplexity=30)             # faqat shu                       # ⚠️
for p in [5, 30, 50]: ...       # barqarorlikni tekshiring        # ✅

4. t-SNE fazosida klasterlash

python
KMeans(5).fit(Z_tsne)                                             # ⚠️
KMeans(5).fit(Z_pca)            # yoki asl fazoda                 # ✅

5. Katta ma'lumotda to'g'ridan-to'g'ri

python
TSNE().fit_transform(X_50k_1000belgi)   # juda sekin              # ⚠️
Z = PCA(50).fit_transform(Xs); TSNE().fit_transform(Z)            # ✅

6. transform ni kutish

python
model = TSNE().fit(Xtr); model.transform(Xte)   # xato            # ⚠️
Isomap(n_neighbors=10).fit(Xtr).transform(Xte)                    # ✅

7. Belgi muhandisligi uchun t-SNE

python
X_yangi = np.column_stack([X, TSNE(2).fit_transform(X)])          # ⚠️
X_yangi = np.column_stack([X, PCA(2).fit_transform(X)])           # ✅

7. Integratsiya — bu bilim qayerda kerak bo'ladi

  • 16.8-dars (o'tilgan): PCA
  • 16.1-dars (o'tilgan): O'lchamlar la'nati
  • 05-qism (o'tilgan): Vizualizatsiya
  • 16.10-dars: Anomaliya
  • 16.12-dars: Amaliyot

8. Eng yaxshi amaliyotlar

  1. Masshtablang.

  2. Avval PCA bilan siqing.

  3. random_state qo'ying.

  4. perplexity ni sinab ko'ring.

  5. Masofani talqin qilmang.

  6. Klasterlashni asl fazoda qiling.

  7. transform kerak bo'lsa Isomap/UMAP.

  8. Xulosani asl fazoda tasdiqlang.


9. Amaliy topshiriq

Vazifa 1: Bashorat qiling

python
1.  # manifold taxmini nima?
2.  # PCA ning cheklovi?
3.  # t-SNE nimani minimallashtiradi?
4.  # nega t-taqsimot?
5.  # perplexity nimani boshqaradi?
6.  # perplexity qoidasi?
7.  # t-SNE da transform bormi?
8.  # UMAP ning afzalligi?
9.  # diagrammada nima ma'noga ega?
10. # nima ma'noga ega emas?
11. # katta ma'lumotda nima qilish kerak?
12. # Isomap nimani saqlaydi?
Javoblar
  1. Ma'lumot past o'lchamli egri sirtda yotadi
  2. Faqat chiziqli
  3. KL divergensiyani
  4. Og'ir dum, siqilish muammosi
  5. Hisobga olinadigan qo'shnilar sonini
  6. perplexity < n/3
  7. Yo'q
  8. Tezroq, transform bor, global tuzilma
  9. Mahalliy qo'shnilik va ajralish
  10. Masofa, o'lcham, joylashuv
  11. Avval PCA
  12. Geodezik masofa (global tuzilma)

Vazifa 2: Xatolarni tuzating

python
1.  TSNE(n_components=2)   # takrorlanmaydi

2.  KMeans(5).fit(Z_tsne)

3.  TSNE().fit_transform(X_50k_1000belgi)

4.  model = TSNE().fit(Xtr); model.transform(Xte)

5.  # "A va B klasterlari uzoq, demak tubdan farq qiladi"
Javoblar
python
1.  TSNE(n_components=2, random_state=0)

2.  KMeans(5).fit(Z_pca)

3.  Z = PCA(50).fit_transform(Xs); TSNE().fit_transform(Z)

4.  Isomap(n_neighbors=10).fit(Xtr).transform(Xte)

5.  # asl fazoda markazlar masofasini o'lchang

Vazifa 3: Manifold

Modellang:

  1. Shveytsar rulosi
  2. Qo'shnilik
  3. PCA cheklovi
  4. S-egri

Vazifa 4: Tuzoqlar

Modellang:

  1. Klasterlararo masofa
  2. Klaster o'lchami
  3. perplexity
  4. Tuzilmasiz ma'lumot

Vazifa 5: Raqamlar

Modellang:

  1. Ma'lumot
  2. PCA siqish
  3. Besh usul
  4. Klasterlash

Vazifa 6: Barqarorlik

Modellang:

  1. Seed lar
  2. Joylashuv
  3. perplexity
  4. transform

Vazifa 7: O'ylash

t-SNE diagrammalari juda ishonarli ko'rinadi va maqolalarda keng ishlatiladi. Ularni qanday qilib mas'uliyat bilan ishlatish mumkin?

Javob

Qisqa javob: t-SNE ni gipoteza generatori sifatida ishlating, dalil sifatida emas. Har qanday vizual kuzatuvni asl fazoda son bilan tasdiqlang va diagrammaga uning cheklovlarini yozib qo'ying.

1. Mas'uliyatli ishlatish tartibi

Qadam Nima qilinadi
1 Bir necha perplexity va seed bilan takrorlash
2 Faqat barqaror naqshlarni belgilash
3 Har naqshni asl fazoda tekshirish
4 Diagrammaga parametrlarni yozish
5 Cheklovlarni izohda ko'rsatish

2. Asl fazoda tekshirish usullari

  1. Klasterlararo masofa: markazlar orasidagi masofani asl fazoda hisoblang
  2. Klaster haqiqiyligi: asl fazoda klasterlab, silhouette va barqarorlikni o'lchang
  3. Ajralish: klasterlarni ajratuvchi model quring (agar 0.95 AUC bersa — ular haqiqatan ajralgan)
  4. Belgilar: klasterlar qaysi belgilar bo'yicha farq qiladi

3. Diagrammaga yozilishi kerak

t-SNE (perplexity=30, seed=0, PCA-40 dan)
Eslatma: klasterlararo masofa va o'lchamlar ma'noga ega emas

Bu bir qator o'quvchini eng keng tarqalgan xatodan saqlaydi.

4. Qachon boshqa usulni tanlash kerak

  • Masofalar muhim bo'lsa -> Isomap yoki MDS
  • Yangi nuqta qo'shish kerak -> UMAP yoki Isomap
  • Natija barqaror bo'lishi kerak -> PCA
  • Katta ma'lumot -> UMAP yoki PCA + namuna

5. Xulosa

  1. t-SNE gipoteza beradi, dalil emas
  2. Barqarorlikni tekshiring
  3. Xulosani asl fazoda tasdiqlang
  4. Cheklovlarni diagrammada ko'rsating

Nimani mustahkamlaydi: 2.6, 2.7-bo'limlar.


Xulosa

Bu darsda nochiziqli o'lchamni kamaytirishni o'rgandik.

Eng muhim uch fikr:

  1. Mahalliy qo'shnilik saqlanadi, global tuzilma yo'q. Manifold usullari ma'lumot past o'lchamli egri sirtda yotadi deb taxmin qiladi va qo'shnilikni saqlashga harakat qiladi. Shveytsar rulosida PCA uzoq nuqtalarni yaqin qilib ko'rsatadi, Isomap va t-SNE esa manifoldni to'g'ri ochadi.

  2. Diagrammadagi masofa, o'lcham va joylashuv ma'nosiz. t-SNE klasterlararo masofani saqlamaydi (asl nisbat 13 bo'lsa, diagrammada 2 bo'lishi mumkin), zichlikni tenglashtiradi va har seed da boshqacha joylashtiradi. Bundan ham yomoni — u tuzilmasiz ma'lumotda ham ishonarli "klasterlar" yaratadi. perplexity ni bir necha qiymatda sinang va faqat barqaror naqshlarga ishoning.

  3. t-SNE fazosida klasterlash qilmang. U allaqachon klasterlarni ajratib qo'ygan, shuning uchun u yerdagi ARI va silhouette sun'iy yuqori bo'ladi — bu haqiqiy sifat emas. Klasterlashni asl yoki PCA fazosida bajaring. transform() kerak bo'lsa — t-SNE da u yo'q; Isomap yoki UMAP ishlating.

Keyingi darsda anomaliya aniqlashni o'rganamiz: Isolation Forest, LOF va One-Class SVM.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!