Mundarija (22)
- 1. Kirish va motivatsiya
- 2. Nazariya — chuqur tushuntirish
- 2.1. Uch strategiya
- 2.2. Ehtimollar izchilligi
- 2.3. Chalkashlik matritsasi tahlili
- 2.4. macro, micro, weighted
- 2.5. Ko'p sinfda nomutanosiblik
- 2.6. Ierarxik yondashuv
- 2.7. Tuzoqlar
- 2.8. Strategiya — narx va izchillik
- 3. Tez ma'lumotnoma
- 4. Batafsil misollar
- Misol 1 — OvR, OvO va softmax
- Misol 2 — Chalkashlik matritsasi tahlili
- Misol 3 — Nomutanosib ko'p sinf
- Misol 4 — Ierarxik yondashuv
- 5. To'g'ri va noto'g'ri tushunishlar
- 6. Keng tarqalgan xatolar va yechimlari
- 7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 8. Eng yaxshi amaliyotlar
- 9. Amaliy topshiriq
- Xulosa
14.8-dars: Ko'p sinfli strategiyalar
14-QISM — KLASSIFIKATSIYA · 8-dars
1. Kirish va motivatsiya
Ko'pchilik algoritmlar tabiatan binar: SVM ikki sinfni ajratadi, logistik regressiya bitta sigmoid beradi. Lekin real vazifalarda sinflar ko'p: 10 ta raqam, 18 ta rubrika, 200 ta mahsulot kategoriyasi. Ularni qanday hal qilamiz?
Uch yo'l bor: OvR (har sinf qolganlarga qarshi), OvO (har juftlik), va tabiiy ko'p sinfli modellar (softmax, daraxtlar, KNN, NB). Tanlov aniqlikka, tezlikka va ehtimollar izchilligiga ta'sir qiladi.
Bu darsda: uch strategiya va ularning narxi, ehtimollar izchilligi, chalkashlik matritsasi tahlili 12.7-bob, macro/micro/weighted metrikalari, ko'p sinfda nomutanosiblik va ierarxik yondashuv.
Real vaziyat. Marketpleys mahsulotlarni 320 ta kategoriyaga ajratadi. OvR bilan 320 ta model o'qitildi — 45 daqiqa, F1 macro 0.71. Chalkashlik matritsasi ko'rsatdiki, xatolarning 62% i bitta darax shoxida ("elektronika" ichida). Ierarxik yondashuv (avval 12 ta yirik guruh, keyin guruh ichida) F1 ni 0.78 ga ko'tardi va o'qitishni 12 daqiqaga tushirdi.
Bu darsda ko'p sinfli strategiyalarni o'rganamiz.
Bu darsda:
- OvR, OvO va softmax
- Ehtimollar izchilligi
- Chalkashlik matritsasi tahlili
- macro, micro, weighted
- Ko'p sinfda nomutanosiblik
- Ierarxik yondashuv
- Tuzoqlar
- Amaliy: 10 sinfli vazifa
ℹ Misollar real numpy/sklearn bilan (Python 3.14).
2. Nazariya — chuqur tushuntirish
2.1. Uch strategiya
OvR (One-vs-Rest): K ta binar model — "sinf k" va "qolganlari"
bashorat: eng yuqori ball bergan model
+ K ta model (tez), har model butun ma'lumotda
- sinflar nomutanosib bo'lib qoladi, ballar solishtirilmaydigan
OvO (One-vs-One): K(K-1)/2 ta model — har juftlik uchun
bashorat: ovoz berish
+ har model faqat 2 sinf ma'lumotida (kichik, tez)
- model soni kvadratik (K=50 → 1225 model)
SOFTMAX (multinomial): bitta model, K ta chiqish
p_k = exp(z_k) / sum(exp(z_j))
+ izchil ehtimollar, bitta optimallashtirish
- faqat ba'zi algoritmlarda mavjud (LogReg, tarmoqlar)
Tabiatan ko'p sinfli: daraxtlar, KNN, NB, LDA/QDA sklearn da ko'pchilik algoritmlar avtomatik ko'p sinfni qo'llab-quvvatlaydi: LogisticRegression — softmax, SVC — OvO, LinearSVC — OvR. Buni bilmaslik natijani noto'g'ri talqin qilishga olib keladi: masalan, SVC da decision_function shakli (n, K(K-1)/2) bo'lishi mumkin.
2.2. Ehtimollar izchilligi
SOFTMAX: ehtimollar yig'indisi 1 — izchil, kalibrlanishi mumkin 13.10-bob
OvR: har model o'z ehtimolini beradi → yig'indi 1 GA TENG EMAS
sklearn ularni normallashtiradi (bo'ladi), lekin bu kalibrlashni buzadi
OvO: ovozlardan ehtimol tiklash (Wu-Lin-Weng) — taxminiy
Natija: ehtimol muhim bo'lsa → softmax yoki keyin kalibrlash 14.10-bob
faqat yorliq kerak bo'lsa → farq kichik Izchillik — OvR ning asosiy kamchiligi: K ta mustaqil model bir-biridan bexabar, ularning ballari bir shkalada emas. Amalda bu aniqlikka kam ta'sir qiladi, lekin ehtimollar ishlatilganda (narx formulalari, chegaralar — 12.7) muammo bo'ladi.
2.3. Chalkashlik matritsasi tahlili
from sklearn.metrics import ConfusionMatrixDisplay, confusion_matrix
cm = confusion_matrix(y_te, pred)
cm_norm = confusion_matrix(y_te, pred, normalize="true") # qatorlar bo'yicha
# eng ko'p chalkashadigan juftliklar
np.fill_diagonal(cm, 0)
eng = np.dstack(np.unravel_index(np.argsort(cm, axis=None)[::-1], cm.shape))[0][:5]Ko'p sinfda chalkashlik matritsasi — eng ma'lumotli diagnostika 12.7-bob: u qaysi sinflar bir-biriga o'xshashligini ko'rsatadi. Tipik topilmalar: ikki sinf doim chalkashadi (ularni birlashtirish yoki maxsus belgi kerak), bitta sinf hech qachon bashorat qilinmaydi (juda kam namuna), xatolar ierarxiya ichida to'plangan.
2.4. macro, micro, weighted
macro — har sinf uchun metrikani hisoblab, oddiy o'rtacha
→ kam namunali sinflar KATTA vazn oladi
micro — barcha TP/FP/FN ni yig'ib hisoblash
→ ko'p namunali sinflar hukmron; ko'p sinfda micro-F1 = accuracy
weighted — sinf hajmiga qarab vaznlangan o'rtacha
Tanlov:
barcha sinflar teng muhim → macro
umumiy ishlash muhim → weighted yoki accuracy
kam uchraydigan sinf muhim → macro yoki shu sinf uchun alohida metrika macro va weighted farqi nomutanosib ko'p sinfli vazifalarda juda katta bo'lishi mumkin: 20 ta sinfning 15 tasi kichik bo'lsa, weighted 0.92 va macro 0.54 bo'lishi normal. Hisobotda ikkalasini ham bering va qaysi biri muhimligini oldindan kelishing 12.7-bob.
2.5. Ko'p sinfda nomutanosiblik
Muammo: sinflar hajmi 10 000 dan 50 gacha farq qiladi
Yechimlar:
· class_weight="balanced" — har sinf teskari chastota bilan vaznlanadi
· kam sinflarni BIRLASHTIRISH ("boshqa" kategoriyasi)
· ierarxik yondashuv
· har sinf uchun alohida chegara 12.7-bob
· macro metrikalar bilan baholash
Diqqat: stratifikatsiya majburiy 12.3-bob — aks holda kichik sinf foldda yo'q bo'lishi mumkin Ko'p sinfli nomutanosiblik binar holatdan qiyinroq: kichik sinflar hech qachon bashorat qilinmasligi mumkin. class_weight="balanced" birinchi qadam, lekin ko'pincha yetarli emas — sinflarni birlashtirish yoki ierarxiya amaliy yechim bo'ladi.
2.6. Ierarxik yondashuv
Sinflar tabiiy ierarxiyaga ega bo'lsa (kategoriya → kichik kategoriya):
1-bosqich: yirik guruhni bashorat qilish (12 sinf)
2-bosqich: guruh ichida aniq sinfni (har guruh uchun alohida model)
+ har model oddiyroq vazifani yechadi, tezroq o'qitiladi
+ xatolar "yaqin" sinflar orasida qoladi (narxi kamroq)
- xato birinchi bosqichda tarqaladi (kaskad xatosi)
- ko'proq model va murakkabroq infratuzilmaIerarxiya — ko'p sinfli katta vazifalarning amaliy yechimi (marketpleys kategoriyalari, tibbiy kodlar, tillar). Uning asosiy xavfi — kaskad xatosi: birinchi bosqichda yanglishsangiz, ikkinchisi tuzata olmaydi. Shuning uchun birinchi bosqich aniqroq bo'lishi kerak.
2.7. Tuzoqlar
Asosiy tuzoqlar: average ni ko'rsatmaslik 12.7-bob; macro va weighted ni chalkashtirish; stratifikatsiyasiz CV (kichik sinf yo'qoladi); OvR ehtimollarini kalibrlangan deb hisoblash; SVC da decision_function shaklini noto'g'ri talqin qilish; katta K da OvO ishlatish (kvadratik); chalkashlik matritsasini ko'rmaslik; ierarxiyada kaskad xatosini hisobga olmaslik.
2.8. Strategiya — narx va izchillik
Ko'p sinfli vazifa uch yo'l bilan hal qilinadi: OvR (K model, tez, lekin ballar solishtirilmaydigan), OvO (K(K-1)/2 model, kichik vazifalar, katta K da qimmat) va softmax (bitta model, izchil ehtimollar). sklearn da bu avtomatik tanlanadi — qaysi biri ishlatilayotganini bilish kerak. Baholashda macro va weighted ni birga bering, chalkashlik matritsasini albatta ko'ring. Katta va ierarxik sinf to'plamlarida ierarxik yondashuv tezlik va sifat beradi. Keyingi dars — nomutanosib sinflar.
3. Tez ma'lumotnoma
import numpy as np
from sklearn.metrics import classification_report, confusion_matrix, f1_score
from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier
OneVsRestClassifier(LinearSVC()) # K model
OneVsOneClassifier(SVC()) # K(K-1)/2 model
LogisticRegression() # softmax (tabiiy)
f1_score(y, pred, average="macro") # sinflar teng
f1_score(y, pred, average="weighted") # hajmga qarab
print(classification_report(y, pred, digits=3))
cm = confusion_matrix(y, pred, normalize="true")
np.fill_diagonal(cm, 0)
eng_chalkash = np.unravel_index(np.argsort(cm, axis=None)[::-1][:5], cm.shape)
QOIDA: strategiyani bil · macro+weighted ber · CM ni ko'r · stratifikatsiya qilKo'p sinf xulosasi
OvR: K model, tez, ballar izchil emas · OvO: K(K-1)/2, kichik vazifalar
Softmax: bitta model, izchil ehtimollar · Daraxt/KNN/NB: tabiatan ko'p sinfli
macro (sinflar teng) / weighted (hajmga qarab) / micro (= accuracy)
Ierarxiya: tez va aniqroq, lekin kaskad xatosi4. Batafsil misollar
Misollar real numpy/sklearn bilan (Python 3.14).
Misol 1 — OvR, OvO va softmax
"""Uch strategiya: aniqlik va ichki modellar soni (real numpy/sklearn)."""
import numpy as np
from sklearn.datasets import load_digits
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, f1_score
from sklearn.model_selection import train_test_split
from sklearn.multiclass import OneVsOneClassifier, OneVsRestClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
def main() -> None:
X, y = load_digits(return_X_y=True)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
K = len(np.unique(y))
print("=== 1. Vazifa ===")
print(f" {len(X)} namuna, {X.shape[1]} belgi, {K} sinf")
print(f" OvR: {K} model, OvO: {K * (K - 1) // 2} model, softmax: 1 model")
print("\n=== 2. Logistik regressiya: softmax va OvR ===")
asos = lambda: LogisticRegression(max_iter=5000, C=0.1)
modellar = {
"softmax": Pipeline([("sc", StandardScaler()), ("m", asos())]),
"OvR": Pipeline([("sc", StandardScaler()),
("m", OneVsRestClassifier(asos()))]),
"OvO": Pipeline([("sc", StandardScaler()),
("m", OneVsOneClassifier(asos()))]),
}
for nom, m in modellar.items():
m.fit(Xtr, ytr)
pred = m.predict(Xte)
ichki = getattr(m.named_steps["m"], "estimators_", None)
soni = 1 if ichki is None else len(ichki)
print(f" {nom:<8}: aniqlik {accuracy_score(yte, pred):.4f}, "
f"F1 macro {f1_score(yte, pred, average='macro'):.4f}, "
f"ichki modellar {soni:>2}")
print("\n=== 3. SVC ichki strategiyasi ===")
svc = Pipeline([("sc", StandardScaler()), ("m", SVC(C=10.0))]).fit(Xtr, ytr)
df = svc.decision_function(Xte)
print(f" SVC decision_function shakli: {df.shape}")
print(f" (sklearn SVC ichida OvO, lekin natijani OvR shakliga keltiradi)")
svc_ovo = OneVsOneClassifier(SVC(C=10.0))
Xtr_s = StandardScaler().fit(Xtr).transform(Xtr)
Xte_s = StandardScaler().fit(Xtr).transform(Xte)
svc_ovo.fit(Xtr_s, ytr)
print(f" aniq OvO: {len(svc_ovo.estimators_)} ta ichki model, "
f"aniqlik {(svc_ovo.predict(Xte_s) == yte).mean():.4f}")
print("\n=== 4. Ehtimollar izchilligi ===")
soft = modellar["softmax"]
ovr = modellar["OvR"]
ps = soft.predict_proba(Xte[:5])
po = ovr.predict_proba(Xte[:5])
print(f" softmax yig'indilari: {ps.sum(axis=1).round(6)}")
print(f" OvR yig'indilari (normallashtirilgandan keyin): "
f"{po.sum(axis=1).round(6)}")
# normallashtirishdan oldingi xom ballar
xom = np.column_stack([e.predict_proba(
StandardScaler().fit(Xtr).transform(Xte[:5]))[:, 1]
for e in ovr.named_steps["m"].estimators_])
print(f" OvR XOM ehtimollar yig'indisi: {xom.sum(axis=1).round(4)}")
print(" ⭐ OvR da yig'indi 1 emas — normallashtirish kalibrlashni buzadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Vazifa ===
1797 namuna, 64 belgi, 10 sinf
OvR: 10 model, OvO: 45 model, softmax: 1 model
=== 2. Logistik regressiya: softmax va OvR ===
softmax : aniqlik 0.9722, F1 macro 0.9725, ichki modellar 1
OvR : aniqlik 0.9648, F1 macro 0.9652, ichki modellar 10
OvO : aniqlik 0.9778, F1 macro 0.9779, ichki modellar 45
=== 3. SVC ichki strategiyasi ===
SVC decision_function shakli: (540, 10)
(sklearn SVC ichida OvO, lekin natijani OvR shakliga keltiradi)
aniq OvO: 45 ta ichki model, aniqlik 0.9852
=== 4. Ehtimollar izchilligi ===
softmax yig'indilari: [1. 1. 1. 1. 1.]
OvR yig'indilari (normallashtirilgandan keyin): [1. 1. 1. 1. 1.]
OvR XOM ehtimollar yig'indisi: [1.4367 1.0675 1.0989 1.0343 0.9899]
⭐ OvR da yig'indi 1 emas — normallashtirish kalibrlashni buzadiNima ko'rsatdi: 2.1, 2.2-bo'limlar.
Misol 2 — Chalkashlik matritsasi tahlili
"""Qaysi sinflar chalkashadi va nega (real numpy/sklearn)."""
import numpy as np
from sklearn.datasets import load_digits
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix, f1_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def main() -> None:
X, y = load_digits(return_X_y=True)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
m = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000, C=0.05))]).fit(Xtr, ytr)
pred = m.predict(Xte)
print("=== 1. Umumiy natija ===")
print(f" aniqlik = {(pred == yte).mean():.4f}")
print(f" F1 macro = {f1_score(yte, pred, average='macro'):.4f}, "
f"weighted = {f1_score(yte, pred, average='weighted'):.4f}")
print("\n=== 2. Eng ko'p chalkashadigan juftliklar ===")
cm = confusion_matrix(yte, pred)
cm_toza = cm.copy()
np.fill_diagonal(cm_toza, 0)
tartib = np.argsort(cm_toza, axis=None)[::-1][:6]
for idx in tartib:
a, b = np.unravel_index(idx, cm.shape)
if cm_toza[a, b] > 0:
print(f" haqiqiy {a} → bashorat {b}: {cm_toza[a, b]} marta "
f"({cm_toza[a, b] / cm[a].sum():.1%} shu sinfdan)")
print("\n=== 3. Har sinf bo'yicha ===")
hisobot = classification_report(yte, pred, output_dict=True, zero_division=0)
qatorlar = [(k, v) for k, v in hisobot.items() if k.isdigit()]
qatorlar.sort(key=lambda t: t[1]["f1-score"])
print(f" eng qiyin uchta sinf:")
for k, v in qatorlar[:3]:
print(f" sinf {k}: F1 {v['f1-score']:.3f}, recall {v['recall']:.3f}, "
f"support {int(v['support'])}")
print(f" eng oson uchta sinf:")
for k, v in qatorlar[-3:]:
print(f" sinf {k}: F1 {v['f1-score']:.3f}, recall {v['recall']:.3f}, "
f"support {int(v['support'])}")
print("\n=== 4. Qatorlar bo'yicha normallashtirilgan matritsa ===")
cmn = confusion_matrix(yte, pred, normalize="true")
eng_qiyin = int(qatorlar[0][0])
qator = cmn[eng_qiyin]
top = np.argsort(qator)[::-1][:3]
print(f" sinf {eng_qiyin} qayerga ketadi: "
f"{ {int(i): round(float(qator[i]), 3) for i in top} }")
print(f" diagonal o'rtachasi (har sinf recall i): {np.diag(cmn).mean():.4f}")
print(f" eng past diagonal: sinf {int(np.argmin(np.diag(cmn)))} "
f"({np.diag(cmn).min():.3f})")
print(" ⭐ Chalkashlik matritsasi — ko'p sinfli diagnostikaning markazi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Umumiy natija ===
aniqlik = 0.9630
F1 macro = 0.9634, weighted = 0.9635
=== 2. Eng ko'p chalkashadigan juftliklar ===
haqiqiy 8 → bashorat 1: 5 marta (9.6% shu sinfdan)
haqiqiy 9 → bashorat 5: 2 marta (3.7% shu sinfdan)
haqiqiy 4 → bashorat 8: 2 marta (3.7% shu sinfdan)
haqiqiy 6 → bashorat 1: 2 marta (3.7% shu sinfdan)
haqiqiy 3 → bashorat 8: 2 marta (3.6% shu sinfdan)
haqiqiy 1 → bashorat 8: 1 marta (1.8% shu sinfdan)
=== 3. Har sinf bo'yicha ===
eng qiyin uchta sinf:
sinf 8: F1 0.904, recall 0.904, support 52
sinf 1: F1 0.908, recall 0.982, support 55
sinf 3: F1 0.962, recall 0.927, support 55
eng oson uchta sinf:
sinf 7: F1 0.982, recall 1.000, support 54
sinf 2: F1 0.990, recall 0.981, support 53
sinf 0: F1 1.000, recall 1.000, support 54
=== 4. Qatorlar bo'yicha normallashtirilgan matritsa ===
sinf 8 qayerga ketadi: {8: 0.904, 1: 0.096, 9: 0.0}
diagonal o'rtachasi (har sinf recall i): 0.9628
eng past diagonal: sinf 8 0.904-bob
⭐ Chalkashlik matritsasi — ko'p sinfli diagnostikaning markaziNima ko'rsatdi: 2.3, 2.4-bo'limlar.
Misol 3 — Nomutanosib ko'p sinf
"""Kichik sinflar yo'qolganda nima bo'ladi (real numpy/sklearn)."""
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, f1_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 7, n: int = 6000, K: int = 8):
"""Sinf hajmlari keskin farq qiladi."""
rng = np.random.default_rng(seed)
ulush = np.array([0.40, 0.25, 0.15, 0.08, 0.05, 0.04, 0.02, 0.01])
y = rng.choice(K, n, p=ulush)
markazlar = rng.normal(0, 2.0, (K, 6))
X = markazlar[y] + rng.normal(0, 1.6, (n, 6))
return X, y
def main() -> None:
X, y = yarat()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0,
stratify=y)
print("=== 1. Sinf hajmlari ===")
sinf, soni = np.unique(ytr, return_counts=True)
print(f" {dict(zip(sinf.tolist(), soni.tolist()))}")
print(f" eng katta / eng kichik nisbati: {soni.max() / soni.min():.0f}x")
print("\n=== 2. Oddiy model ===")
oddiy = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000))]).fit(Xtr, ytr)
p1 = oddiy.predict(Xte)
print(f" aniqlik {(p1 == yte).mean():.4f}, "
f"F1 macro {f1_score(yte, p1, average='macro'):.4f}, "
f"weighted {f1_score(yte, p1, average='weighted'):.4f}")
bashorat_qilingan = set(np.unique(p1).tolist())
yoq = sorted(set(range(8)) - bashorat_qilingan)
print(f" hech qachon bashorat qilinmagan sinflar: {yoq}")
print("\n=== 3. class_weight='balanced' ===")
balans = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000,
class_weight="balanced"))]).fit(Xtr, ytr)
p2 = balans.predict(Xte)
print(f" aniqlik {(p2 == yte).mean():.4f}, "
f"F1 macro {f1_score(yte, p2, average='macro'):.4f}, "
f"weighted {f1_score(yte, p2, average='weighted'):.4f}")
print(f" bashorat qilingan sinflar: {sorted(np.unique(p2).tolist())}")
print("\n=== 4. Kichik sinflar bo'yicha recall ===")
h1 = classification_report(yte, p1, output_dict=True, zero_division=0)
h2 = classification_report(yte, p2, output_dict=True, zero_division=0)
print(f" {'sinf':>5} {'support':>8} {'oddiy R':>9} {'balanced R':>11}")
for k in ["4", "5", "6", "7"]:
if k in h1:
print(f" {k:>5} {int(h1[k]['support']):>8} "
f"{h1[k]['recall']:>9.3f} {h2[k]['recall']:>11.3f}")
print(" ⭐ macro va weighted farqi nomutanosiblikni ko'rsatadi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Sinf hajmlari ===
{0: 1727, 1: 1003, 2: 618, 3: 353, 4: 215, 5: 170, 6: 70, 7: 44}
eng katta / eng kichik nisbati: 39x
=== 2. Oddiy model ===
aniqlik 0.9494, F1 macro 0.8820, weighted 0.9486
hech qachon bashorat qilinmagan sinflar: []
=== 3. class_weight='balanced' ===
aniqlik 0.9244, F1 macro 0.8341, weighted 0.9299
bashorat qilingan sinflar: [0, 1, 2, 3, 4, 5, 6, 7]
=== 4. Kichik sinflar bo'yicha recall ===
sinf support oddiy R balanced R
4 92 0.880 0.826
5 73 0.918 0.973
6 30 0.567 0.867
7 19 0.684 0.947
⭐ macro va weighted farqi nomutanosiblikni ko'rsatadiNima ko'rsatdi: 2.4, 2.5-bo'limlar.
Misol 4 — Ierarxik yondashuv
"""Ikki bosqichli tasniflash va kaskad xatosi (real numpy/sklearn)."""
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
def yarat(seed: int = 9, n: int = 9000):
"""12 ta sinf, 3 ta yirik guruhga birlashgan (guruh ichida o'xshash)."""
rng = np.random.default_rng(seed)
K = 12
y = rng.integers(0, K, n)
guruh = y // 4 # 0,1,2 — yirik guruhlar
# guruhlar yaqin - 1-bosqich ham yanglishadi (kaskad xatosi ko'rinsin)
guruh_markaz = np.array([[1.0, 0.0], [-0.5, 0.87], [-0.5, -0.87]]) * 2.0
sinf_siljish = rng.normal(0, 0.9, (K, 2))
X2 = guruh_markaz[guruh] + sinf_siljish[y] + rng.normal(0, 0.75, (n, 2))
qoshimcha = rng.normal(0, 1, (n, 4))
X = np.column_stack([X2, qoshimcha])
return X, y, guruh
def main() -> None:
X, y, guruh = yarat()
Xtr, Xte, ytr, yte, gtr, gte = train_test_split(X, y, guruh, test_size=0.3,
random_state=0, stratify=y)
print("=== 1. Vazifa ===")
print(f" {len(X)} namuna, 12 sinf, 3 yirik guruh (har guruhda 4 sinf)")
print("\n=== 2. Yassi (flat) model: 12 sinf birdaniga ===")
yassi = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000))]).fit(Xtr, ytr)
p_yassi = yassi.predict(Xte)
print(f" aniqlik {(p_yassi == yte).mean():.4f}, "
f"F1 macro {f1_score(yte, p_yassi, average='macro'):.4f}, "
f"modellar: 1 ta (12 sinf uchun)")
print("\n=== 3. Ierarxik model ===")
bosqich1 = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000))]).fit(Xtr, gtr)
bosqich2 = {}
for g in range(3):
mos = gtr == g
bosqich2[g] = Pipeline([("sc", StandardScaler()),
("m", LogisticRegression(max_iter=5000))]).fit(
Xtr[mos], ytr[mos])
g_bash = bosqich1.predict(Xte)
p_ier = np.empty(len(Xte), dtype=int)
for g in range(3):
mos = g_bash == g
if mos.any():
p_ier[mos] = bosqich2[g].predict(Xte[mos])
print(f" 1-bosqich (guruh) aniqligi: {(g_bash == gte).mean():.4f}")
print(f" yakuniy aniqlik {(p_ier == yte).mean():.4f}, "
f"F1 macro {f1_score(yte, p_ier, average='macro'):.4f}, "
f"modellar: 4 ta (1 + 3), har biri kichikroq vazifada")
print("\n=== 4. Kaskad xatosi ===")
togri_guruh = g_bash == gte
print(f" guruh to'g'ri topilganda aniqlik: "
f"{(p_ier[togri_guruh] == yte[togri_guruh]).mean():.4f}")
if (~togri_guruh).any():
print(f" guruh noto'g'ri bo'lganda aniqlik: "
f"{(p_ier[~togri_guruh] == yte[~togri_guruh]).mean():.4f}")
else:
print(" guruh noto'g'ri bo'lgan holat yo'q (1-bosqich xatosiz)")
print(f" guruh xatosi ulushi: {(~togri_guruh).mean():.1%}")
print("\n yassi model xatolari qanday taqsimlangan:")
yassi_xato = p_yassi != yte
guruh_ichida = (p_yassi[yassi_xato] // 4) == (yte[yassi_xato] // 4)
print(f" guruh ichida: {guruh_ichida.mean():.1%}, "
f"guruhlar orasida: {1 - guruh_ichida.mean():.1%}")
print(" ⭐ Bu yerda ierarxiya YUTMADI - 1-bosqich xatosi qaytarilmaydi")
if __name__ == "__main__":
main()Natijaning muhim qismi:
=== 1. Vazifa ===
9000 namuna, 12 sinf, 3 yirik guruh (har guruhda 4 sinf)
=== 2. Yassi (flat) model: 12 sinf birdaniga ===
aniqlik 0.5219, F1 macro 0.5099, modellar: 1 ta (12 sinf uchun)
=== 3. Ierarxik model ===
1-bosqich (guruh) aniqligi: 0.9037
yakuniy aniqlik 0.5019, F1 macro 0.4938, modellar: 4 ta (1 + 3), har biri kichikroq vazifada
=== 4. Kaskad xatosi ===
guruh to'g'ri topilganda aniqlik: 0.5553
guruh noto'g'ri bo'lganda aniqlik: 0.0000
guruh xatosi ulushi: 9.6%
yassi model xatolari qanday taqsimlangan:
guruh ichida: 81.6%, guruhlar orasida: 18.4%
⭐ Bu yerda ierarxiya YUTMADI - 1-bosqich xatosi qaytarilmaydiNima ko'rsatdi: 2.6-bo'lim.
5. To'g'ri va noto'g'ri tushunishlar
| Noto'g'ri fikr | To'g'risi |
|---|---|
| "OvR va softmax bir xil" | Ehtimollar izchilligi farq qiladi |
| "OvO har doim sekin" | Har model kichikroq ma'lumotda |
| "macro va weighted yaqin" | Nomutanosiblikda juda farqli |
| "micro-F1 — alohida metrika" | Ko'p sinfda = accuracy |
| "Chalkashlik matritsasi — formallik" | Asosiy diagnostika |
| "class_weight yetarli" | Ko'pincha emas |
| "Ierarxiya har doim yaxshi" | Kaskad xatosi bor |
| "sklearn o'zi hal qiladi" | Qaysi strategiya — bilish kerak |
6. Keng tarqalgan xatolar va yechimlari
1. average ni ko'rsatmaslik
f1_score(y, pred) # ko'p sinfda xato # ⚠️
f1_score(y, pred, average="macro") # ✅2. Stratifikatsiyasiz CV
KFold(5, shuffle=True) # kichik sinf yo'qoladi # ⚠️
StratifiedKFold(5, shuffle=True, random_state=0) # ✅3. OvR ehtimollarini kalibrlangan deb bilish
foyda = ovr.predict_proba(X) * qiymatlar # ⚠️
# softmax ishlating yoki kalibrlang 14.10-bob # ✅4. Katta K da OvO
OneVsOneClassifier(SVC()).fit(X, y) # K = 200 → 19900 model # ⚠️
LinearSVC() # yoki ierarxik yondashuv # ✅5. Chalkashlik matritsasini ko'rmaslik
print("aniqlik:", acc) # ⚠️
print(confusion_matrix(y, pred, normalize="true")) # ✅6. Faqat weighted berish
print(f1_score(y, pred, average="weighted")) # ⚠️
# macro ni ham bering (kichik sinflar ko'rinadi) # ✅7. Kichik sinflarni e'tiborsiz qoldirish
# 3 ta sinf hech qachon bashorat qilinmayapti # ⚠️
# class_weight, birlashtirish yoki ierarxiya # ✅7. Integratsiya — bu bilim qayerda kerak bo'ladi
- 12.7-dars (o'tilgan): Ko'p sinfli metrikalar
- 13.10-dars (o'tilgan): Softmax
- 14.9-dars: Nomutanosib sinflar
- 14.10-dars: Kalibrlash
- 14.13-dars: Xatolar tahlili
8. Eng yaxshi amaliyotlar
Qaysi strategiya ishlatilayotganini biling.
macro va weighted ni birga bering.
Chalkashlik matritsasini ko'ring.
Stratifikatsiya qiling.
Ehtimol kerak bo'lsa softmax yoki kalibrlash.
Katta K da ierarxiyani o'ylang.
Kichik sinflarni alohida tekshiring.
Model va vaqt narxini hisoblang.
9. Amaliy topshiriq
Vazifa 1: Bashorat qiling
1. # OvR nechta model?
2. # OvO nechta model?
3. # softmax formulasi?
4. # OvR ehtimollari yig'indisi?
5. # sklearn LogReg qaysi strategiya?
6. # SVC qaysi?
7. # macro nima?
8. # weighted nima?
9. # ko'p sinfda micro-F1?
10. # stratifikatsiya nega kerak?
11. # ierarxiyaning xavfi?
12. # kichik sinf bashorat qilinmasa?Javoblar
- K
- K(K-1)/2
- exp(z_k)/sum(exp(z_j))
- 1 ga teng emas
- Softmax
- OvO
- Sinflar bo'yicha oddiy o'rtacha
- Hajmga qarab vaznlangan
- Accuracy ga teng
- Kichik sinf foldda yo'qolmasligi uchun
- Kaskad xatosi
- class_weight, birlashtirish, ierarxiya
Vazifa 2: Xatolarni tuzating
1. f1_score(y, pred) # 12 sinf
2. KFold(5).split(X) # kichik sinflar bor
3. OneVsOneClassifier(SVC()).fit(X, y) # 150 sinf
4. print(f"aniqlik {acc:.3f}") # 20 sinf
5. foyda = ovr.predict_proba(X) @ qiymatlarJavoblar
1. f1_score(y, pred, average="macro")
2. StratifiedKFold(5, shuffle=True, random_state=0)
3. LinearSVC() # yoki ierarxik yondashuv
4. print(confusion_matrix(y, pred, normalize="true"))
5. # softmax model yoki kalibrlash (14.10)Vazifa 3: Strategiyalar
Modellang:
- OvR, OvO, softmax
- Aniqlik va vaqt
- Model soni
- Ehtimollar
Vazifa 4: Chalkashlik
Modellang:
- Matritsa
- Eng chalkash juftliklar
- Sinf bo'yicha F1
- Xulosa
Vazifa 5: Nomutanosiblik
Modellang:
- Turli hajmli sinflar
- Oddiy va balanced
- Kichik sinf recall
- macro va weighted
Vazifa 6: Ierarxiya
Modellang:
- Guruhlangan sinflar
- Yassi va ierarxik
- Kaskad xatosi
- Tavsiya
Vazifa 7: O'ylash
Ko'p sinfli vazifalarda sinflar ro'yxati ko'pincha biznes tomonidan beriladi (masalan, 320 ta mahsulot kategoriyasi) va Data Scientist uni o'zgarmas deb qabul qiladi. Bu to'g'ri yondashuvmi?
Javob
Qisqa javob: yo'q — sinflar ro'yxati modellashtirish qarori hamdir. Agar ikki sinf ma'lumotda ajralmasa yoki bir sinfda 12 ta namuna bo'lsa, ularni o'zgarmas deb qabul qilish modelni ham, foydalanuvchini ham yomon ahvolga soladi.
1. Qachon ro'yxatni qayta ko'rish kerak
| Belgi | Taklif |
|---|---|
| Ikki sinf doim chalkashadi | Birlashtirish yoki qo'shimcha belgi |
| Sinfda < 50 namuna | "Boshqa" ga qo'shish yoki ma'lumot yig'ish |
| Sinflar ierarxik | Ikki bosqichli model |
| Sinf ta'rifi noaniq | Yorliqlash qo'llanmasini aniqlashtirish |
2. Qanday asoslash
- Chalkashlik matritsasi — eng ishonchli dalil
- Yorliqlar orasidagi kelishuv (inter-annotator agreement)
- Har sinf uchun biznes qiymati (ba'zi sinflar qarorga ta'sir qilmaydi)
3. Nima taklif qilish mumkin
- Sinflarni birlashtirish (past qiymatli va chalkashadiganlar)
- Ierarxiya: yirik guruh + ichki model
- "Ishonchsiz" javob: past ehtimolda inson ko'rigiga yuborish
- Yorliqlash sifatini yaxshilash
4. Muzokara tili
- "Model bu sinflarni ajrata olmaydi"
- "Ushbu ikki kategoriya ma'lumotda 38% holatda chalkashadi; ularni birlashtirsak F1 0.71 dan 0.79 ga ko'tariladi — qaysi biri sizga muhimroq?"
5. Xulosa
- Sinflar ro'yxati — muzokara predmeti
- Dalil — chalkashlik matritsasi
- Ierarxiya va "boshqa" sinfi amaliy yechim
- Yorliqlash sifati modeldan muhimroq bo'lishi mumkin
Nimani mustahkamlaydi: 2.3, 2.6-bo'limlar.
Xulosa
Bu darsda ko'p sinfli strategiyalarni o'rgandik.
Eng muhim uch fikr:
Uch strategiya, uch narx. OvR —
Kta model, tez, lekin ballar bir shkalada emas; OvO —K(K-1)/2ta model (har biri kichik ma'lumotda), kattaKda qimmat; softmax — bitta model va izchil ehtimollar.sklearnbuni avtomatik tanlaydi (LogisticRegression— softmax,SVC— OvO,LinearSVC— OvR), lekin qaysi biri ishlatilayotganini bilish kerak.macro va weighted birga beriladi. Nomutanosib ko'p sinfli vazifada ular keskin farq qiladi:
weightedkatta sinflar hisobiga yuqori bo'lib turishi,macroesa kichik sinflar yo'qolganini ko'rsatishi mumkin. Chalkashlik matritsasi — asosiy diagnostika: u qaysi sinflar o'xshashligini, qaysi sinf hech qachon bashorat qilinmasligini ko'rsatadi.Ierarxiya — katta vazifalar uchun. Sinflar tabiiy guruhlarga bo'linsa, ikki bosqichli model tezroq o'qitiladi va xatolarni "yaqin" sinflar ichida ushlab qoladi. Asosiy xavf — kaskad xatosi: birinchi bosqichdagi yanglishish tuzatilmaydi. Va eslang: sinflar ro'yxati — o'zgarmas berilgan emas, muzokara predmeti.
Keyingi darsda nomutanosib sinflarni chuqurroq o'rganamiz: resampling, SMOTE, chegara siljitish va ularning haqiqiy foydasi.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!