Kodax

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 كبير سالب ← σ قريبة من 0
import 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}")
اختبر فهمك