11-bo‘lim

K-yaqin qo'shni (KNN)

Eng sodda algoritm - masofaga asoslangan bashorat, k ni tanlash, masofa turlari va tavsiya tizimlari.

🕑 11 daqiqa o‘qish 📄 693 so‘z 👁 6 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Qanday ishlaydi?
  2. Amaliyotda
  3. k ni tanlash
  4. Masofa turlari
  5. Vazn berish
  6. KNN regressiya uchun
  7. Afzallik va kamchiliklar
  8. Tezlikni oshirish
  9. Amaliy qo'llanish - tavsiya tizimi
  10. Anomaliyani aniqlash
  11. Xulosa

KNN - tushunish eng oson bo'lgan algoritm. Uning g'oyasi bir jumlada ifodalanadi: "menga qo'shningni ayt - kimligingni aytaman."

Qanday ishlaydi? #

Yangi nuqtaning k ta eng yaqin qo'shnisi ovoz beradi yangi nuqta k = 5 Ovoz berish Ko'k: 2 ta ovoz Qizil: 3 ta ovoz Natija: qizil Regressiyada esa o'rtacha qiymat olinadi
Model hech nima "o'rganmaydi" - u faqat ma'lumotni eslab qoladi

Algoritm:

  1. Yangi nuqta bilan barcha o'qitish namunalari orasidagi masofani hisobla
  2. Eng yaqin k tasini tanla
  3. Klassifikatsiyada - ular orasida ko'pchilik ovozini ol
  4. Regressiyada - ularning o'rtachasini hisobla

Amaliyotda #

Python
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline

iris = load_iris()
X, y = iris.data, iris.target

X_o, X_s, y_o, y_s = train_test_split(
    X, y, test_size=0.3, random_state=42, stratify=y
)

model = make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=5))
model.fit(X_o, y_o)

print(f"Aniqlik: {model.score(X_s, y_s):.3f}")
Natija
Aniqlik: 0.978
Masshtablash MAJBURIY

KNN masofa bilan ishlaydi. Agar bir belgi 0-1, ikkinchisi 0-100000 oralig'ida bo'lsa, masofa deyarli faqat ikkinchisiga bog'liq bo'ladi.

Python
# Masshtablashsiz
knn_xom = KNeighborsClassifier(5).fit(X_o, y_o)
print(f"Masshtablashsiz: {knn_xom.score(X_s, y_s):.3f}")

Iris da farq kam, lekin turli birlikdagi belgilar bo'lsa - farq katta.

k ni tanlash #

Python
natijalar = []

for k in range(1, 31):
    model = make_pipeline(StandardScaler(), KNeighborsClassifier(n_neighbors=k))
    model.fit(X_o, y_o)

    natijalar.append({
        "k": k,
        "oqitish": model.score(X_o, y_o),
        "sinov": model.score(X_s, y_s),
    })

import pandas as pd
jadval = pd.DataFrame(natijalar)
print(jadval.iloc[[0, 2, 4, 9, 19, 29]].round(3))
Natija
     k  oqitish  sinov
0    1    1.000  0.956
2    3    0.971  0.978
4    5    0.962  0.978
9   10    0.962  0.956
19  20    0.943  0.933
29  30    0.933  0.911
k qanday tanlanadi? k = 1 Chegara juda tarmoqlangan Shovqinni ham o'rganib oladi Qayta o'qitish k = 5 Silliq chegara Shovqinga chidamli Yaxshi muvozanat k = 50 Chegara juda sodda Mahalliy tuzilma yo'qoladi Yetarli o'qimaydi Boshlash uchun k = namunalar sonining kvadrat ildizi
k oshgani sari chegara silliqlashadi
k ni tanlash qoidalari
  1. Toq son tanlang (ikkilik klassifikatsiyada teng ovoz bo'lmasligi uchun)
  2. Boshlang'ich taxmin: k = sqrt(n)
  3. Kross-validatsiya bilan aniq qiymatni toping
  4. k=1 - deyarli har doim qayta o'qitish
Python
from sklearn.model_selection import GridSearchCV

qidiruv = GridSearchCV(
    make_pipeline(StandardScaler(), KNeighborsClassifier()),
    {"kneighborsclassifier__n_neighbors": range(1, 31)},
    cv=5,
    scoring="accuracy",
)
qidiruv.fit(X_o, y_o)

print(f"Eng yaxshi k: {qidiruv.best_params_}")
print(f"CV aniqlik:   {qidiruv.best_score_:.3f}")
Natija
Eng yaxshi k: {'kneighborsclassifier__n_neighbors': 13}
CV aniqlik:   0.962

Masofa turlari #

Python
KNeighborsClassifier(metric="euclidean")    # standart
KNeighborsClassifier(metric="manhattan")
KNeighborsClassifier(metric="minkowski", p=3)
KNeighborsClassifier(metric="cosine")
MasofaFormulaQachon
Yevklidsqrt(Σ(a-b)²)Odatiy, uzluksiz belgilar
Manxettenmodullar yig'indisiKo'p o'lchamli, chetdagi qiymatlar bor
KosinusBurchakMatn, tavsiya tizimlari
HemmingFarq soniIkkilik belgilar
Ikki nuqta orasidagi masofani o'lchashning turli usullari Yevklid To'g'ri chiziq - "qush uchishi" Manxetten Faqat o'qlar bo'ylab - "shahar ko'chalari" Kosinus burchak Yo'nalish muhim, uzunlik emas
Masofa tanlovi vazifaga bog'liq
Kosinus masofasi - matn uchun

"Salom dunyo" va "Salom salom dunyo dunyo dunyo" matnlari bir xil mavzuda, lekin so'z sonlari boshqa.

Yevklid masofasi ularni uzoq deb hisoblaydi. Kosinus esa faqat yo'nalishga qaraydi va ularni yaqin deb topadi.

Vazn berish #

Python
# Barcha qo'shnilar teng ovozga ega
KNeighborsClassifier(n_neighbors=5, weights="uniform")

# Yaqinroq qo'shni kuchliroq ovoz beradi
KNeighborsClassifier(n_neighbors=5, weights="distance")
weights="distance" ko'pincha yaxshiroq

Mantiqiy: 1 metr uzoqdagi qo'shni 10 metrdagidan ishonchliroq ma'lumot beradi.

Bu, ayniqsa, katta k qiymatlarida foydali.

KNN regressiya uchun #

Python
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_absolute_error

model = make_pipeline(
    StandardScaler(),
    KNeighborsRegressor(n_neighbors=5, weights="distance"),
)
model.fit(X_o, y_o)

bashorat = model.predict(X_s)
print(f"MAE: {mean_absolute_error(y_s, bashorat):.2f}")

Regressiyada k ta qo'shnining o'rtachasi olinadi.

Afzallik va kamchiliklar #

AfzalligiKamchiligi
Juda sodda, tushunarliBashorat sekin (har safar hamma masofa hisoblanadi)
O'qitish bosqichi yo'qButun ma'lumotni xotirada saqlaydi
Murakkab chegaralarni topa oladiMasshtablash majburiy
Ko'p sinfli vazifada tabiiy ishlaydiKo'p o'lchamda yomonlashadi
Yangi ma'lumot qo'shish osonKeraksiz belgilarga sezgir
O'lchamlilik la'nati

O'lchamlar soni oshgani sari barcha nuqtalar bir-biridan bir xil uzoqlikda bo'lib qoladi:

Python
for olcham in [2, 10, 100, 1000]:
    nuqtalar = np.random.rand(1000, olcham)
    masofalar = np.linalg.norm(nuqtalar[0] - nuqtalar[1:], axis=1)
    nisbat = masofalar.max() / masofalar.min()
    print(f"{olcham:5d} o'lcham: eng uzoq/eng yaqin = {nisbat:.2f}")
Natija
    2 o'lcham: eng uzoq/eng yaqin = 42.18
   10 o'lcham: eng uzoq/eng yaqin = 4.05
  100 o'lcham: eng uzoq/eng yaqin = 1.61
 1000 o'lcham: eng uzoq/eng yaqin = 1.18

1000 o'lchamda "eng yaqin qo'shni" tushunchasi ma'nosini yo'qotadi.

Yechim: avval PCA bilan o'lchamni kamaytiring (15-bo'lim) yoki keraksiz belgilarni olib tashlang.

Tezlikni oshirish #

Python
KNeighborsClassifier(algorithm="ball_tree")   # ko'p o'lchamda yaxshi
KNeighborsClassifier(algorithm="kd_tree")     # kam o'lchamda tez
KNeighborsClassifier(algorithm="brute")       # to'g'ridan-to'g'ri
KNeighborsClassifier(algorithm="auto")        # o'zi tanlaydi
KNeighborsClassifier(n_jobs=-1)               # barcha yadrolar

Amaliy qo'llanish - tavsiya tizimi #

Python
from sklearn.neighbors import NearestNeighbors

# Har bir foydalanuvchining film baholari
baholar = np.array([
    [5, 4, 0, 0, 3],     # Husanboy
    [4, 5, 0, 1, 2],     # Jasur
    [0, 0, 5, 4, 0],     # Malika
    [1, 0, 4, 5, 1],     # Aziz
    [5, 5, 1, 0, 4],     # Nodira
])

izlovchi = NearestNeighbors(n_neighbors=3, metric="cosine")
izlovchi.fit(baholar)

masofalar, indekslar = izlovchi.kneighbors([baholar[0]])

ismlar = ["Husanboy", "Jasur", "Malika", "Aziz", "Nodira"]
print("Husanboyga o'xshash foydalanuvchilar:")
for masofa, idx in zip(masofalar[0][1:], indekslar[0][1:]):
    print(f"  {ismlar[idx]:10s} o'xshashlik: {1 - masofa:.3f}")
Natija
Husanboyga o'xshash foydalanuvchilar:
  Nodira     o'xshashlik: 0.987
  Jasur      o'xshashlik: 0.949
Bu haqiqiy tavsiya tizimining asosi

"Sizga o'xshash foydalanuvchilar buni ham ko'rgan" - aynan shu usul.

Netflix, YouTube va onlayn do'konlar bu g'oyaning ancha murakkab versiyalarini ishlatadi.

Anomaliyani aniqlash #

Python
izlovchi = NearestNeighbors(n_neighbors=5).fit(X_oqitish)
masofalar, _ = izlovchi.kneighbors(X_sinov)

ortacha_masofa = masofalar.mean(axis=1)
chegara = np.percentile(ortacha_masofa, 95)

anomaliyalar = X_sinov[ortacha_masofa > chegara]
print(f"Topilgan anomaliyalar: {len(anomaliyalar)}")

Qo'shnilaridan juda uzoqdagi nuqtalar - shubhali.

Amaliy topshiriq
  1. Iris ma'lumotida KNN modelini o'qiting.
  2. k ni 1 dan 30 gacha o'zgartirib, o'qitish va sinov aniqligini chizing.
  3. Eng yaxshi k ni GridSearchCV bilan toping.
  4. Masshtablashsiz va masshtablangan natijalarni solishtiring.
  5. weights="uniform" va "distance" farqini o'lchang.
  6. Yevklid va Manxetten masofalarini solishtiring.
  7. Ikki belgi bilan qaror chegarasini chizing (k=1 va k=15 uchun).
  8. KNeighborsRegressor bilan uy narxini bashorat qiling.
  9. Yuqoridagi tavsiya tizimini kengaytiring: 10 foydalanuvchi, 8 film.
  10. O'lchamlilik la'nati kodini ishga tushiring va natijani tushuntiring.

Xulosa #

  • KNN eng yaqin k ta qo'shni asosida bashorat qiladi.
  • Klassifikatsiyada ovoz berish, regressiyada o'rtacha.
  • Model hech nima o'rganmaydi - u faqat ma'lumotni saqlaydi.
  • Masshtablash majburiy - algoritm masofa bilan ishlaydi.
  • Kichik k - qayta o'qitish, katta k - yetarli o'qimaslik.
  • k toq son bo'lsin; boshlang'ich taxmin sqrt(n).
  • weights="distance" ko'pincha yaxshiroq natija beradi.
  • Kosinus masofasi matn va tavsiya tizimlari uchun.
  • O'lchamlilik la'nati: ko'p o'lchamda KNN yomonlashadi.
  • NearestNeighbors tavsiya tizimlari va anomaliya aniqlash uchun.

Keyingi bo'limda qaror daraxtlari va Random Forest ni o'rganamiz.

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.