11-bo‘lim
K-yaqin qo'shni (KNN)
Eng sodda algoritm - masofaga asoslangan bashorat, k ni tanlash, masofa turlari va tavsiya tizimlari.
Ushbu bo‘lim mundarijasi
KNN - tushunish eng oson bo'lgan algoritm. Uning g'oyasi bir jumlada ifodalanadi: "menga qo'shningni ayt - kimligingni aytaman."
Qanday ishlaydi? #
Algoritm:
- Yangi nuqta bilan barcha o'qitish namunalari orasidagi masofani hisobla
- Eng yaqin k tasini tanla
- Klassifikatsiyada - ular orasida ko'pchilik ovozini ol
- Regressiyada - ularning o'rtachasini hisobla
Amaliyotda #
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}")
Aniqlik: 0.978
KNN masofa bilan ishlaydi. Agar bir belgi 0-1, ikkinchisi 0-100000 oralig'ida bo'lsa, masofa deyarli faqat ikkinchisiga bog'liq bo'ladi.
# 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 #
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))
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
- Toq son tanlang (ikkilik klassifikatsiyada teng ovoz bo'lmasligi uchun)
- Boshlang'ich taxmin:
k = sqrt(n) - Kross-validatsiya bilan aniq qiymatni toping
k=1- deyarli har doim qayta o'qitish
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}")
Eng yaxshi k: {'kneighborsclassifier__n_neighbors': 13}
CV aniqlik: 0.962
Masofa turlari #
KNeighborsClassifier(metric="euclidean") # standart
KNeighborsClassifier(metric="manhattan")
KNeighborsClassifier(metric="minkowski", p=3)
KNeighborsClassifier(metric="cosine")
| Masofa | Formula | Qachon |
|---|---|---|
| Yevklid | sqrt(Σ(a-b)²) | Odatiy, uzluksiz belgilar |
| Manxetten | modullar yig'indisi | Ko'p o'lchamli, chetdagi qiymatlar bor |
| Kosinus | Burchak | Matn, tavsiya tizimlari |
| Hemming | Farq soni | Ikkilik belgilar |
"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 #
# 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 yaxshiroqMantiqiy: 1 metr uzoqdagi qo'shni 10 metrdagidan ishonchliroq ma'lumot beradi.
Bu, ayniqsa, katta k qiymatlarida foydali.
KNN regressiya uchun #
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 #
| Afzalligi | Kamchiligi |
|---|---|
| Juda sodda, tushunarli | Bashorat sekin (har safar hamma masofa hisoblanadi) |
| O'qitish bosqichi yo'q | Butun ma'lumotni xotirada saqlaydi |
| Murakkab chegaralarni topa oladi | Masshtablash majburiy |
| Ko'p sinfli vazifada tabiiy ishlaydi | Ko'p o'lchamda yomonlashadi |
| Yangi ma'lumot qo'shish oson | Keraksiz belgilarga sezgir |
O'lchamlar soni oshgani sari barcha nuqtalar bir-biridan bir xil uzoqlikda bo'lib qoladi:
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}")
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 #
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 #
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}")
Husanboyga o'xshash foydalanuvchilar:
Nodira o'xshashlik: 0.987
Jasur o'xshashlik: 0.949
"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 #
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.
- Iris ma'lumotida KNN modelini o'qiting.
kni 1 dan 30 gacha o'zgartirib, o'qitish va sinov aniqligini chizing.- Eng yaxshi
kniGridSearchCVbilan toping. - Masshtablashsiz va masshtablangan natijalarni solishtiring.
weights="uniform"va"distance"farqini o'lchang.- Yevklid va Manxetten masofalarini solishtiring.
- Ikki belgi bilan qaror chegarasini chizing (
k=1vak=15uchun). KNeighborsRegressorbilan uy narxini bashorat qiling.- Yuqoridagi tavsiya tizimini kengaytiring: 10 foydalanuvchi, 8 film.
- 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, kattak- yetarli o'qimaslik. ktoq son bo'lsin; boshlang'ich taxminsqrt(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.
NearestNeighborstavsiya tizimlari va anomaliya aniqlash uchun.
Keyingi bo'limda qaror daraxtlari va Random Forest ni 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.