Logistic Regression — تعلم الآلة
الانحدار اللوجستي (Logistic Regression)
رغم اسمه، هو نموذج تصنيف: ناجح أم راسب، مزعج أم لا، سيشتري أم لا. ويعطي احتمالاً لا مجرد فئة.
لماذا لا نستخدم الانحدار الخطي للتصنيف؟
الخط المستقيم يعطي قيماً مثل −0.4 أو 1.7 — لا معنى لها كاحتمال. نحتاج دالة تضغط أي رقم إلى ما بين 0 و 1.
دالة Sigmoid
σ(z) = 1 / (1 + e^(−z)) حيث z = w·x + b
z كبير موجب ← σ قريبة من 1
z = 0 ← σ = 0.5
z كبير سالب ← σ قريبة من 0import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
for z in [-6, -2, 0, 2, 6]:
print(z, round(float(sigmoid(z)), 3))من الاحتمال إلى قرار
الافتراضي: احتمال ≥ 0.5 ← الفئة 1. لكن حد القرار قابل للتعديل حسب كلفة الخطأ:
- كشف مرض خطير: خفّض الحد (0.3) لتلتقط حالات أكثر حتى مع إنذارات كاذبة أكثر.
- حظر حساب بتهمة احتيال: ارفع الحد (0.9) لتجنب ظلم المستخدمين.
from sklearn.linear_model import LogisticRegression
import numpy as np
X = np.array([[1], [2], [3], [4], [5], [6], [7], [8]]) # ساعات الدراسة
y = np.array([0, 0, 0, 1, 0, 1, 1, 1]) # نجاح؟
model = LogisticRegression().fit(X, y)
proba = model.predict_proba([[4.5]])[0, 1]
print(f"احتمال النجاح: {proba:.2f}")
print("القرار عند حد 0.5:", int(proba >= 0.5), "| عند حد 0.7:", int(proba >= 0.7))كيف يتعلم؟
لا توجد صيغة مباشرة كما في الانحدار الخطي. النموذج يقلل دالة خسارة اسمها Log Loss (Cross-Entropy) تعاقب بشدة التنبؤ الواثق الخاطئ (احتمال 0.99 لفئة خاطئة)، ويصل للأوزان بالتحسين التكراري.
أكثر من فئتين
LogisticRegression في scikit-learn يدعم تعدد الفئات مباشرة (يستخدم softmax): أعطه y بثلاث فئات وسيعيد predict_proba ثلاثة احتمالات مجموعها 1.
نقاط قوته
- سريع، وقابل للتفسير: إشارة الوزن تقول هل الميزة تزيد الاحتمال أم تنقصه.
- خط أساس ممتاز لأي مشكلة تصنيف. ابدأ به قبل النماذج المعقدة.
- يستفيد من التقييس، ويطبق Regularization افتراضياً (المعامل C؛ أصغر = تنظيم أقوى).
تمرين
في المثال الكامل غيّر حد القرار من 0.5 إلى 0.3 ثم 0.7، ولاحظ كيف تتغير الدقة و Recall (ستفهمهما بالتفصيل في درس التقييم).
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, recall_score
rng = np.random.default_rng(0)
# 200 طالب: ساعات الدراسة ونسبة الحضور ← نجاح؟
hours = rng.uniform(0, 10, 200)
attendance = rng.uniform(40, 100, 200)
score = 0.8 * hours + 0.06 * attendance + rng.normal(0, 1.2, 200)
y = (score > 7).astype(int)
X = np.column_stack([hours, attendance])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
model = LogisticRegression()
model.fit(X_train, y_train)
print("الأوزان:", model.coef_.round(3), "— كلاهما موجب: يزيد احتمال النجاح")
proba = model.predict_proba(X_test)[:, 1]
for threshold in [0.3, 0.5, 0.7]:
pred = (proba >= threshold).astype(int)
print(f"حد {threshold}: الدقة {accuracy_score(y_test, pred):.2f}، Recall {recall_score(y_test, pred):.2f}")
student = [[5, 85]]
print(f"طالب يدرس 5 ساعات وحضوره 85%: احتمال النجاح {model.predict_proba(student)[0, 1]:.2f}")اختبر فهمك