Asosiy qismga o'tish

Confusion matrix

3-bob 8 kod bloki 1287 so'z

Nega "confusion" deb ataladi?

Inglizchada to confuse — "adashtirmoq", "chalkashtirmoq" degani. Masalan: "I confused 3 with 5" — "3 ni 5 bilan adashtirdim".

Confusion matrix — model qaysi klassni qaysi klass bilan adashtirganini sanaydigan jadval. Har bir katakda bitta savolga javob bor: "haqiqatda A klass bo'lgan rasmlarning nechtasini model B deb aytdi?"

Masalan, 10 ta raqamli masalada 5 lar necha marta 3 deb aytilganini bilish uchun "haqiqat 5" qatori va "bashorat 3" ustuni kesishgan katakka qaraysiz.

Nega test set emas, cross_val_predict?

Matritsa uchun har bir rasmga bashorat kerak. Test set ni oxirigacha ochmaymiz. model.predict(X_train) ham bo'lmaydi: model bu rasmlarni o'qishda ko'rgan, natija haddan tashqari yaxshi chiqadi.

cross_val_predict cross-validation qiladi, lekin baho o'rniga bashoratlarning o'zini qaytaradi. Har bir rasmga bashoratni o'sha rasmni ko'rmagan model beradi. Shuning uchun bu bashoratlar halol: xuddi model hali ko'rmagan yangi rasmlarga bergan javoblardek.

python6 qator
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix

y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
cm = confusion_matrix(y_train_5, y_train_pred)
cm
Chiqish
array([[53892,   687],
       [ 1891,  3530]])

Natija — 2 × 2 jadval, ichida 4 ta son. Ularni to'g'ri o'qish uchun ikkita qoidani bilish kerak.

1-qoida: qatorlar — haqiqat, ustunlar — bashorat

confusion_matrix(y_true, y_pred) da birinchi argument qatorlarga, ikkinchisi ustunlarga aylanadi. Matritsadagi cm[i, j] — haqiqiy klassi i bo'lgan va model j deb aytgan rasmlar soni.

Nega aynan shunday? sklearn hujjatida shunday belgilangan. Argumentlar tartibi (y_true, y_pred), matritsa ham shu tartibda quriladi. Buni yodlash shart emas: funksiyaga birinchi nimani bersangiz, qatorlar o'sha bo'ladi.

2-qoida: klasslar o'sish tartibida

Klasslar saralanadi: False < True (yoki 0 < 1). Shuning uchun birinchi qator va birinchi ustun — False, ya'ni "5 emas". Natijada:

yaml3 qator
                 bashorat: 5 emas   bashorat: 5
haqiqat: 5 emas        TN               FP
haqiqat: 5             FN               TP

Diqqat: ko'p kitob va Wikipedia matritsani teskari chizadi: TP ni yuqori chapga qo'yadi. Ikkalasi ham to'g'ri, faqat joylashuvi boshqa. Shuning uchun boshqa manbadan rasm ko'rsangiz, avval o'qlarga nima yozilganini o'qing, keyin raqamni talqin qiling. sklearn da TN har doim yuqori chapda turadi.

Yuqoridagi matritsani nomlar bilan chiqaramiz:

python2 qator
pd.DataFrame(cm, index=["haqiqat: 5 emas", "haqiqat: 5"],
             columns=["bashorat: 5 emas", "bashorat: 5"])
Chiqish
                 bashorat: 5 emas  bashorat: 5
haqiqat: 5 emas             53892          687
haqiqat: 5                   1891         3530

Nega TN, FP, FN, TP deb ataladi?

Har bir nom ikki so'zdan iborat va ikkalasi alohida savolga javob beradi:

  • Ikkinchi so'z (Positive / Negative) — model nima dedi? Positive = "5", Negative = "5 emas".
  • Birinchi so'z (True / False) — model to'g'ri aytdimi? True = to'g'ri, False = xato.

Shunda:

Nom Model nima dedi To'g'rimi Ma'nosi
TP (True Positive) 5 to'g'ri 5 ni topdi
TN (True Negative) 5 emas to'g'ri 5 bo'lmagan rasmga to'g'ri "5 emas" dedi
FP (False Positive) 5 xato 5 bo'lmagan rasmni 5 dedi — noto'g'ri signal
FN (False Negative) 5 emas xato haqiqiy 5 ni topmadi — o'tkazib yubordi

Bu qoidani bilsangiz, nomlarni yodlash shart emas. "False Negative" ni eshitsangiz: "model Negative dedi, bu False (xato)" → demak haqiqatda Positive edi → o'tkazib yuborilgan.

Nega "Positive" — yaxshi degani emas?

"Positive" — biz qidirayotgan klass: 5, kasallik, firibgarlik, spam. Tibbiy tahlil "positive" chiqsa, bu kasallik topildi degani. Bemor uchun bu yomon xabar, lekin model uchun u "positive". Qaysi klass positive bo'lishini o'zimiz tanlaymiz: odatda kam uchraydigan va topish muhim bo'lgan klass.

Nega diagonal — to'g'ri javoblar?

Yuqori chapdan pastki o'ngga ketgan diagonalda qator klassi va ustun klassi bir xil: haqiqat "5 emas" — bashorat "5 emas", haqiqat "5" — bashorat "5". Diagonaldan tashqaridagi hamma narsa — xato.

To'rtta raqamni alohida o'zgaruvchilarga olamiz. ravel() matritsani qatorma-qator bitta qatorga yoyadi, shuning uchun tartib har doim TN, FP, FN, TP:

python2 qator
tn, fp, fn, tp = cm.ravel()
pd.Series({"TN": tn, "FP": fp, "FN": fn, "TP": tp})
Chiqish
TN    53892
FP      687
FN     1891
TP     3530
dtype: int64

Qator va ustun yig'indilari nima deydi?

  • Qator yig'indisi — haqiqatda nechta bor. 53 892 + 687 = 54 579 ta "5 emas", 1891 + 3530 = 5421 ta "5". Bu 1-bobdagi jadval bilan bir xil. Qator yig'indisi modelga bog'liq emas, u ma'lumotning o'zi.
  • Ustun yig'indisi — model nechta marta shunday dedi. Model 687 + 3530 = 4217 marta "5" dedi, 53 892 + 1891 = 55 783 marta "5 emas" dedi. Bu modelga bog'liq.

Bu farq keyin juda muhim bo'ladi: precision ustunga, recall qatorga qaraydi.

Har bir katakda qanday rasmlar bor?

Matritsadagi sonlar faqat nechta xato bo'lganini aytadi. Model qanday rasmlarda adashganini ko'rish uchun har bir katakdan 6 tadan haqiqiy rasm olamiz (kitobdagi 3-2 rasm kabi).

Har bir rasmning nomini 3-bobdagi qoida bo'yicha yasaymiz: - birinchi harf — model to'g'ri aytdimi: haqiqat bashoratga teng bo'lsa "T", aks holda "F"; - ikkinchi harf — model nima dedi: "5" desa "P", "5 emas" desa "N".

Ikki harfni qo'shsak, har bir rasm uchun "TP", "FP", "FN" yoki "TN" chiqadi:

python8 qator
turi = np.where(y_train_5 == y_train_pred, "T", "F") + np.where(y_train_pred, "P", "N")

fig, axes = plt.subplots(2, 2, figsize=(9, 3.2))
for ax, nom in zip(axes.flat, ["TN", "FP", "FN", "TP"]):
    ax.imshow(np.hstack(X_train[turi == nom][:6].reshape(-1, 28, 28)), cmap="binary")
    ax.set_title(f"{nom}: {(turi == nom).sum()} ta")
    ax.axis("off")
plt.show()

grafik

Endi har bir katakda qanday rasmlar borligini ko'rib turibmiz:

  • TN — boshqa raqamlar: 0, 4, 1, 9, 2. Model ularga to'g'ri "5 emas" dedi.
  • FP — model 5 dedi, lekin bular 0 va 6. Qarang: hammasi yumaloq shakllar. 5 ning pastki qismi ham yumaloq, shuning uchun model adashdi.
  • FN — haqiqiy 5 lar, lekin ingichka, qiyshiq yoki g'alati yozilgan. Model ularni tanimadi.
  • TP — aniq, odatdagidek yozilgan 5 lar.

Confusion matrix ning eng katta foydasi shu: u faqat "qancha xato" demaydi, qaysi xato ekanini ko'rsatadi. Har bir katakni ochib, real misollarni ko'rish mumkin.

Mukammal model qanday matritsa beradi?

Model hamma rasmga to'g'ri javob bersa, nima bo'ladi? Bashorat sifatida haqiqatning o'zini beramiz:

python1 qator
confusion_matrix(y_train_5, y_train_5)
Chiqish
array([[54579,     0],
       [    0,  5421]])

Faqat diagonalda raqam bor, FP = 0 va FN = 0. Real modelda bunday bo'lmaydi. Lekin maqsad aniq: raqamlarni diagonalga yig'ish.

Rasm ko'rinishi

ConfusionMatrixDisplay xuddi shu matritsani rangli chizadi. Qator va ustun nomlari o'qlarda yozilgan, shuning uchun adashish qiyin:

python4 qator
from sklearn.metrics import ConfusionMatrixDisplay

ConfusionMatrixDisplay.from_predictions(y_train_5, y_train_pred, display_labels=["5 emas", "5"], cmap="Blues")
plt.show()

grafik

Rang raqamga mos: katta raqam — to'q rang. Diagonaldagi TN juda katta, shuning uchun u eng to'q. Bu ham nomutanosiblikning belgisi: TN qolgan uchta katakdan bir necha barobar katta.

Ko'p uchraydigan xato: argumentlar tartibini almashtirish

Agar confusion_matrix(y_pred, y_true) deb teskari yozsangiz nima bo'ladi?

python1 qator
confusion_matrix(y_train_pred, y_train_5)
Chiqish
array([[53892,  1891],
       [  687,  3530]])

Matritsa transpose bo'ldi, ya'ni qatorlar ustunlarga aylandi: 687 va 1891 joy almashdi. Python hech qanday xato chiqarmaydi, lekin endi FP o'rnida FN, FN o'rnida FP turibdi. Shuning uchun precision va recall ham joy almashib ketadi.

Qoida: har doim (y_true, y_pred) — avval haqiqat, keyin bashorat. sklearn ning barcha metrika funksiyalari shu tartibda ishlaydi.


Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar