9-bo‘lim
Logistik regressiya va klassifikatsiya
Toifani bashorat qilish, sigmoid funksiya, ehtimollik, qaror chegarasi va ko'p sinfli klassifikatsiya.
Ushbu bo‘lim mundarijasi
Endi sonni emas, toifani bashorat qilamiz: spam yoki spam emas, kasal yoki sog'lom, mijoz ketadimi yoki qoladimi.
Nima uchun chiziqli regressiya ishlamaydi? #
import numpy as np
from sklearn.linear_model import LinearRegression
# 0 - imtihondan yiqildi, 1 - o'tdi
soatlar = np.array([1, 2, 3, 4, 5, 6, 7, 8, 20]).reshape(-1, 1)
otdi = np.array([0, 0, 0, 0, 1, 1, 1, 1, 1])
model = LinearRegression().fit(soatlar, otdi)
print(model.predict([[10]]))
print(model.predict([[0]]))
[1.08]
[-0.09]
Chiziqli regressiya 1.08 va -0.09 chiqardi. Lekin ehtimollik
faqat 0 va 1 orasida bo'lishi mumkin.
Bundan tashqari, 20 soat o'qigan bitta talaba butun chiziqni
buzib yubordi.
Sigmoid funksiya #
Yechim - chiziqli natijani [0, 1] oralig'iga siqish.
def sigmoid(z):
return 1 / (1 + np.exp(-z))
for z in [-5, -2, 0, 2, 5]:
print(f"sigmoid({z:3d}) = {sigmoid(z):.4f}")
sigmoid( -5) = 0.0067
sigmoid( -2) = 0.1192
sigmoid( 0) = 0.5000
sigmoid( 2) = 0.8808
sigmoid( 5) = 0.9933
Birinchi klassifikator #
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(soatlar, otdi)
print("Bashorat:", model.predict([[3], [6], [10]]))
print("Ehtimollik:")
print(model.predict_proba([[3], [6], [10]]).round(3))
Bashorat: [0 1 1]
Ehtimollik:
[[0.874 0.126]
[0.192 0.808]
[0.011 0.989]]
predict_proba juda muhimpredict faqat 0 yoki 1 beradi. predict_proba esa ishonch
darajasini ko'rsatadi:
| Soat | O'tmaslik | O'tish |
|---|---|---|
| 3 | 87.4% | 12.6% |
| 6 | 19.2% | 80.8% |
| 10 | 1.1% | 98.9% |
Amaliyotda ehtimollik ko'pincha muhimroq: "bu bemorda kasallik 60% ehtimol bilan bor" degan javob "bor" degandan foydaliroq.
Real ma'lumot bilan #
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.metrics import accuracy_score, classification_report
np.random.seed(42)
n = 500
talabalar = pd.DataFrame({
"oqish_soati": np.random.uniform(0, 20, n),
"davomat": np.random.uniform(40, 100, n),
"oldingi_baho": np.random.uniform(2, 5, n),
"uyqu_soati": np.random.uniform(4, 10, n),
})
# Yashirin qoida
ball = (
talabalar["oqish_soati"] * 0.35
+ talabalar["davomat"] * 0.06
+ talabalar["oldingi_baho"] * 1.2
+ np.random.normal(0, 1.5, n)
)
talabalar["otdi"] = (ball > ball.median()).astype(int)
X = talabalar.drop(columns=["otdi"])
y = talabalar["otdi"]
X_o, X_s, y_o, y_s = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
model = make_pipeline(StandardScaler(), LogisticRegression())
model.fit(X_o, y_o)
bashorat = model.predict(X_s)
print(f"Aniqlik: {accuracy_score(y_s, bashorat):.3f}")
Aniqlik: 0.890
Koeffitsiyentlarni talqin qilish #
vaznlar = model.named_steps["logisticregression"].coef_[0]
for belgi, vazn in sorted(zip(X.columns, vaznlar), key=lambda p: -abs(p[1])):
yonalish = "oshiradi" if vazn > 0 else "kamaytiradi"
print(f"{belgi:15s} {vazn:6.2f} o'tish ehtimolini {yonalish}")
oqish_soati 2.14 o'tish ehtimolini oshiradi
oldingi_baho 0.92 o'tish ehtimolini oshiradi
davomat 0.71 o'tish ehtimolini oshiradi
uyqu_soati -0.04 o'tish ehtimolini kamaytiradi
Logistik regressiyada koeffitsiyent log-odds ga ta'sirni ko'rsatadi.
Amaliy talqin uchun eksponentaga ko'taring:
print(np.exp(2.14)) # 8.5
"O'qish soati bir standart og'ishga oshsa, o'tish shansi 8.5 barobar oshadi."
Qaror chegarasi #
ehtimollik = model.predict_proba(X_s)[:, 1]
# Standart chegara 0.5
bashorat_05 = (ehtimollik >= 0.5).astype(int)
# Qattiqroq chegara
bashorat_07 = (ehtimollik >= 0.7).astype(int)
print(f"0.5 chegara: {bashorat_05.sum()} ta 'o'tdi'")
print(f"0.7 chegara: {bashorat_07.sum()} ta 'o'tdi'")
0.5 chegara: 52 ta 'o'tdi'
0.7 chegara: 38 ta 'o'tdi'
Model chegarani bilmaydi. Uni siz xatoning narxiga qarab tanlaysiz:
"Kasallikni o'tkazib yuborish" 100 barobar qimmatroq bo'lsa - chegarani pasaytiring, ko'proq "shubhali" deb belgilang.
Keyingi bo'limda buni o'lchash usullarini ko'ramiz.
Ko'p sinfli klassifikatsiya #
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
print("Sinflar:", iris.target_names)
Sinflar: ['setosa' 'versicolor' 'virginica']
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(), LogisticRegression(max_iter=1000))
model.fit(X_o, y_o)
print(f"Aniqlik: {model.score(X_s, y_s):.3f}")
print("Ehtimolliklar:")
print(model.predict_proba(X_s[:3]).round(3))
Aniqlik: 0.911
Ehtimolliklar:
[[0. 0.024 0.976]
[0.978 0.022 0. ]
[0. 0.918 0.082]
]
Har bir qatordagi ehtimolliklar yig'indisi 1 ga teng.
| Strategiya | Qanday ishlaydi |
|---|---|
| One-vs-Rest | Har bir sinf uchun alohida ikkilik model |
| Multinomial | Barcha sinflar uchun bitta model (softmax) |
scikit-learn 1.5 dan boshlab multinomial standart bo'lgan - u odatda
aniqroq natija beradi.
Regularizatsiya #
# C - regularizatsiya kuchining TESKARISI
for c in [0.01, 0.1, 1, 100]:
model = make_pipeline(StandardScaler(), LogisticRegression(C=c, max_iter=1000))
model.fit(X_o, y_o)
print(f"C={c:6.2f} o'qitish={model.score(X_o, y_o):.3f} "
f"sinov={model.score(X_s, y_s):.3f}")
C= 0.01 o'qitish=0.867 sinov=0.867
C= 0.10 o'qitish=0.914 sinov=0.911
C= 1.00 o'qitish=0.962 sinov=0.911
C=100.00 o'qitish=0.981 sinov=0.889
C teskari ishlaydiRidge da alpha katta = kuchli regularizatsiya.
LogisticRegression da C kichik = kuchli regularizatsiya.
Bu chalkashlik manbai - eslab qoling: C = 1 / alpha.
Chegaraviy chiziq #
import matplotlib.pyplot as plt
X_ikki = X[:, :2] # faqat ikkita belgi
model = make_pipeline(StandardScaler(), LogisticRegression())
model.fit(X_ikki, y)
x_min, x_max = X_ikki[:, 0].min() - 0.5, X_ikki[:, 0].max() + 0.5
y_min, y_max = X_ikki[:, 1].min() - 0.5, X_ikki[:, 1].max() + 0.5
tor_x, tor_y = np.meshgrid(
np.linspace(x_min, x_max, 300),
np.linspace(y_min, y_max, 300),
)
Z = model.predict(np.c_[tor_x.ravel(), tor_y.ravel()]).reshape(tor_x.shape)
plt.figure(figsize=(8, 6))
plt.contourf(tor_x, tor_y, Z, alpha=0.25, cmap="viridis")
plt.scatter(X_ikki[:, 0], X_ikki[:, 1], c=y, cmap="viridis", edgecolors="k")
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])
plt.title("Logistik regressiya qaror chegaralari")
plt.show()
Logistik regressiya chiziqli chegara chizadi. Sinflar egri chiziq bilan ajralsa - u yaxshi ishlamaydi.
Bunday holatda:
PolynomialFeaturesqo'shing- Yoki daraxt, SVM (RBF yadro) kabi modellarni ishlating
Nomutanosib sinflar #
from collections import Counter
# 95% sog'lom, 5% kasal
y_nomutanosib = np.array([0] * 950 + [1] * 50)
print(Counter(y_nomutanosib))
Counter({0: 950, 1: 50})
Har doim "sog'lom" deb javob beradigan model 95% aniqlik ko'rsatadi - lekin u bironta ham kasalni topa olmaydi.
Yechimlar:
# 1. Sinf vaznlarini muvozanatlash
model = LogisticRegression(class_weight="balanced")
# 2. Aniqlik emas, boshqa metrikalar ishlatish
from sklearn.metrics import f1_score, recall_score
# 3. Kam sinfni ko'paytirish yoki ko'p sinfni kamaytirish (SMOTE)
Keyingi bo'lim to'liq shu mavzuga bag'ishlangan.
model_oddiy = LogisticRegression()
model_muvozanat = LogisticRegression(class_weight="balanced")
Qachon ishlatish kerak? #
| Afzalligi | Kamchiligi |
|---|---|
| Tez o'qiydi va tez ishlaydi | Faqat chiziqli chegara |
| Natija tushuntiriladi | Murakkab naqshni topa olmaydi |
| Ehtimollik beradi | Belgilar masshtablanishi kerak |
| Kam ma'lumotda ham ishlaydi | Chetdagi qiymatlarga sezgir |
| Regularizatsiya qo'llab-quvvatlanadi |
Logistik regressiya - klassifikatsiya uchun asos model (baseline).
Uni birinchi bo'lib sinang. Agar u 88% bersa va murakkab neyron tarmoq 89% bersa - oddiy modelni tanlang: u tezroq, tushunarliroq va qo'llab-quvvatlash osonroq.
sigmoidfunksiyasini yozing va-10dan10gacha chizing.- Talabalar ma'lumotini yarating va logistik regressiya bilan o'qiting.
predictvapredict_probanatijalarini solishtiring.- Koeffitsiyentlarni chiqaring va eng muhim belgini toping.
- Chegarani
0.3,0.5,0.7qilib, "ha" javoblari sonini sanang. - Iris ma'lumotida uch sinfli model quring.
Cni0.001dan1000gacha o'zgartirib, natijani jadvalga chiqaring.- Ikki belgi bilan qaror chegarasini chizing.
PolynomialFeatures(2)qo'shing - chegara egri bo'ldimi?- Nomutanosib ma'lumot yarating va
class_weight="balanced"ta'sirini o'lchang.
Xulosa #
- Logistik regressiya toifani bashorat qiladi, nomiga qaramay.
- Sigmoid funksiya istalgan sonni
[0, 1]oralig'iga siqadi. predict_probaehtimollik beradi - ko'pinchapredictdan foydaliroq.- Qaror chegarasi standart holatda
0.5, lekin uni o'zgartirish mumkin. - Chegara biznes qarori: xatoning narxiga qarab tanlanadi.
- Koeffitsiyentlar log-odds ga ta'sirni ko'rsatadi;
exp()bilan talqin qilinadi. Cregularizatsiya kuchining teskarisi: kichikC= kuchli cheklov.- Chegara har doim chiziqli - egri chegara uchun boshqa model kerak.
- Nomutanosib sinflarda aniqlik aldaydi -
class_weight="balanced"ishlating. - Bu model klassifikatsiya uchun eng yaxshi asos model.
Keyingi bo'limda modellarni to'g'ri baholashni 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.