تقييم النماذج — تعلم الآلة
تقييم النماذج
"دقة 99%" قد تعني نموذجاً عديم الفائدة. تخيّل كشف احتيال حيث 1% فقط من العمليات احتيالية: نموذج يقول "سليمة" لكل شيء دقته 99% ولم يكشف احتيالاً واحداً!
مصفوفة الالتباس (Confusion Matrix)
التنبؤ: سلبي التنبؤ: إيجابي
الفعلي: سلبي TN (صحيح سلبي) FP (إنذار كاذب)
الفعلي: إيجابي FN (حالة فائتة) TP (صحيح إيجابي)المقاييس
| المقياس | الصيغة | السؤال الذي يجيبه |
|---|---|---|
| Accuracy | (TP+TN) / الكل | كم نسبة التنبؤات الصحيحة؟ |
| Precision | TP / (TP+FP) | عندما يقول "إيجابي"، كم مرة يصيب؟ |
| Recall | TP / (TP+FN) | من كل الحالات الإيجابية الحقيقية، كم التقط؟ |
| F1 | المتوسط التوافقي للاثنين | توازن بين Precision و Recall |
أيهما أهم؟ حسب كلفة الخطأ
| المشكلة | الخطأ الأسوأ | ركّز على |
|---|---|---|
| كشف مرض خطير | FN: مريض لم نكتشفه | Recall |
| فلتر الرسائل المزعجة | FP: رسالة مهمة ذهبت للمزعج | Precision |
| كشف الاحتيال | الاثنان مكلفان | F1، ثم ضبط الحد |
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score, accuracy_score
y_true = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
y_pred = [0, 0, 0, 0, 0, 0, 0, 1, 1, 0]
print(confusion_matrix(y_true, y_pred))
print("Accuracy", accuracy_score(y_true, y_pred), "Precision", precision_score(y_true, y_pred),
"Recall", recall_score(y_true, y_pred), "F1", f1_score(y_true, y_pred))انتبه: أي فئة هي "الإيجابية"؟
المقاييس تُحسب افتراضياً للفئة 1. في بيانات سرطان الثدي في المثال الكامل، الفئة 1 = حميد والفئة 0 = خبيث — والحالة المهمة طبياً هي الخبيث. لذلك نحسب Recall للفئة 0 أيضاً (pos_label=0). اقرأ وصف البيانات دائماً.
Cross-Validation: تقييم أكثر ثباتاً
تقسيم واحد قد يكون محظوظاً أو سيئ الحظ. في k-fold نقسم البيانات إلى k أجزاء، وندرب k مرات، كل مرة نختبر على جزء مختلف، ثم نأخذ المتوسط والانحراف:
الدورة 1: [اختبار][تدريب][تدريب][تدريب][تدريب]
الدورة 2: [تدريب][اختبار][تدريب][تدريب][تدريب]
... ← 5 نتائج، نحسب المتوسطللتصنيف، scikit-learn يستخدم StratifiedKFold تلقائياً (يحافظ على نسبة الفئات).
القاعدة الذهبية: مجموعة الاختبار مقدسة
استخدم التدريب و Cross-Validation لاختيار النموذج وضبطه، ولا تنظر لنتيجة الاختبار إلا مرة واحدة في النهاية. إذا عدّلت النموذج بناءً على نتيجة الاختبار، أصبح الاختبار جزءاً من التدريب ولم يعد يقيس الأداء الحقيقي.
تمرين
في المثال الكامل احسب Recall للفئة الخبيثة (pos_label=0)، ثم استخدم predict_proba وخفّض حد القرار للفئة الخبيثة. كم حالة خبيثة إضافية التقطت؟ وكم إنذاراً كاذباً أضفت؟
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.metrics import (accuracy_score, precision_score, recall_score,
f1_score, confusion_matrix, classification_report)
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np
# تحميل البيانات
data = load_breast_cancer()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# التدريب
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# ===== المقاييس =====
print("=== مقاييس الأداء ===")
print(f"Accuracy: {accuracy_score(y_test, y_pred):.2%}")
print(f"Precision: {precision_score(y_test, y_pred):.2%}")
print(f"Recall: {recall_score(y_test, y_pred):.2%}")
print(f"F1-Score: {f1_score(y_test, y_pred):.2%}")
# ===== Confusion Matrix =====
cm = confusion_matrix(y_test, y_pred)
print(f"\nConfusion Matrix:\n{cm}")
# ===== تقرير شامل =====
print("\n=== Classification Report ===")
print(classification_report(y_test, y_pred, target_names=data.target_names))
# ===== Cross-Validation =====
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"\nCross-Validation Scores: {scores}")
print(f"Mean: {scores.mean():.2%} (+/- {scores.std()*2:.2%})")اختبر فهمك