Kodax

Overfitting و Regularization — تعلم الآلة

Overfitting و Regularization

مشكلتان متعاكستان

| | Underfitting (نقص التعلم) | Overfitting (الحفظ) |

|---|---|---|

| ما يحدث | النموذج أبسط من الأنماط الحقيقية | النموذج يحفظ التدريب بما فيه الضوضاء |

| أداء التدريب | ضعيف | ممتاز (قد يكون مثالياً) |

| أداء الاختبار | ضعيف | ضعيف |

| تشبيه | طالب لم يذاكر | طالب حفظ أسئلة السنة الماضية حرفياً |

العلامة الأوضح لـ Overfitting: فجوة كبيرة بين أداء التدريب وأداء الاختبار.

التحيز والتباين (Bias–Variance)

- تحيز عالٍ: افتراضات مبسطة جداً (خط مستقيم لبيانات منحنية) ← Underfitting.

- تباين عالٍ: النموذج يتغير كثيراً مع أي تغيير صغير في البيانات ← Overfitting.

زيادة تعقيد النموذج تقلل التحيز وتزيد التباين. نبحث عن النقطة المتوازنة. المثال الكامل يرسم ثلاث درجات من كثيرات الحدود: الدرجة 1 (نقص)، 4 (مناسبة)، 15 (حفظ).

العلاج

| المشكلة | الحلول |

|---|---|

| Underfitting | نموذج أعقد، ميزات أفضل، تنظيم أقل |

| Overfitting | بيانات أكثر، نموذج أبسط، ميزات أقل، Regularization، إيقاف مبكر (في الشبكات العصبية)، Cross-Validation لاختيار التعقيد |

Regularization: عقوبة على الأوزان الكبيرة

النموذج الذي يحفظ الضوضاء غالباً يستخدم أوزاناً ضخمة متذبذبة. التنظيم يضيف إلى الخسارة عقوبة على حجم الأوزان:

الخسارة الكلية = خطأ التنبؤ + α × حجم الأوزان
Ridge (L2): α × Σ w²     ← يصغّر كل الأوزان، نادراً ما يجعلها صفراً
Lasso (L1): α × Σ |w|    ← يجعل بعض الأوزان صفراً تماماً = اختيار ميزات تلقائي

α (alpha) يتحكم بالقوة: 0 = بلا تنظيم، كبير جداً = Underfitting. اختره بـ Cross-Validation، وقيّس الميزات قبل التنظيم (وإلا عوقبت الميزات ذات الأرقام الصغيرة ظلماً).

import numpy as np
from sklearn.linear_model import Lasso, Ridge

rng = np.random.default_rng(1)
X = rng.normal(size=(100, 10))
y = 3 * X[:, 0] - 2 * X[:, 1] + rng.normal(0, 0.5, 100)   # ميزتان فقط مفيدتان من عشر

print("Ridge:", Ridge(alpha=1.0).fit(X, y).coef_.round(2))
print("Lasso:", Lasso(alpha=0.1).fit(X, y).coef_.round(2))   # لاحظ الأصفار

منحنى التعلم: هل تفيد بيانات أكثر؟

ارسم أداء التدريب والتحقق مع زيادة حجم البيانات (learning_curve في scikit-learn):

- الفجوة كبيرة والمنحنيان يقتربان ← بيانات أكثر ستفيد (Overfitting).

- المنحنيان منخفضان ومتقاربان ← بيانات أكثر لن تفيد؛ تحتاج نموذجاً أو ميزات أفضل (Underfitting).

تمرين

في المثال الكامل جرّب قيم alpha مختلفة لـ Ridge على الدرجة 15 (0.001، 0.1، 10) ولاحظ متى يتحسن الاختبار ومتى يسوء. ثم استخدم RidgeCV ليختار alpha تلقائياً.

from sklearn.linear_model import Ridge, Lasso, LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
import numpy as np
import matplotlib.pyplot as plt

# إنشاء بيانات
np.random.seed(42)
X = np.linspace(0, 1, 50).reshape(-1, 1)
y = np.sin(2 * np.pi * X).ravel() + np.random.randn(50) * 0.3

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# ===== مقارنة درجات Polynomial =====
degrees = [1, 4, 15]
plt.figure(figsize=(15, 4))

for i, degree in enumerate(degrees):
    plt.subplot(1, 3, i + 1)
    
    poly = PolynomialFeatures(degree)
    X_poly_train = poly.fit_transform(X_train)
    X_poly_test = poly.transform(X_test)
    
    from sklearn.linear_model import LinearRegression
    model = LinearRegression()
    model.fit(X_poly_train, y_train)
    
    train_score = model.score(X_poly_train, y_train)
    test_score = model.score(X_poly_test, y_test)
    
    plt.scatter(X_train, y_train, label='Training')
    X_plot = np.linspace(0, 1, 100).reshape(-1, 1)
    y_plot = model.predict(poly.transform(X_plot))
    plt.plot(X_plot, y_plot, 'r-')
    plt.title(f'Degree {degree}\nTrain: {train_score:.2f}, Test: {test_score:.2f}')

plt.show()

# ===== Regularization =====
print("\n=== Regularization ===")
poly = PolynomialFeatures(15)
X_poly = poly.fit_transform(X_train)
X_poly_test = poly.transform(X_test)

# بدون Regularization
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_poly, y_train)
print(f"Linear: Train={lr.score(X_poly, y_train):.2f}, Test={lr.score(X_poly_test, y_test):.2f}")

# Ridge (L2)
ridge = Ridge(alpha=0.1)
ridge.fit(X_poly, y_train)
print(f"Ridge:  Train={ridge.score(X_poly, y_train):.2f}, Test={ridge.score(X_poly_test, y_test):.2f}")

# Lasso (L1)
lasso = Lasso(alpha=0.01)
lasso.fit(X_poly, y_train)
print(f"Lasso:  Train={lasso.score(X_poly, y_train):.2f}, Test={lasso.score(X_poly_test, y_test):.2f}")
اختبر فهمك