الوحدة 2 · الانحدار
الـ Polynomial Features والإفراط في التوافق
20 دقراءة 4 دتمرين Python
الدرس في لمحة
أضف polynomial features لتجعل النموذج الخطي ينحني، وراقب نتيجة التدريب ترتفع بينما تنهار نتيجة الاختبار، واستخدم جزء تحقق (validation) لتختار تعقيد النموذج بأمانة.
- 1جعل النموذج الخطي ينحني
- 2نتيجة التدريب تواصل الصعود
- 3الـ Underfitting والـ Overfitting
- 4اختيار الدرجة بأمانة
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
الخط المستقيم افتراض قوي. فإذا كان تقدّم المرض يرتفع أسرع عند مؤشر كتلة جسم مرتفع منه عند مؤشر منخفض، فلا خط مستقيم يستطيع التقاط ذلك، مهما طال تشغيل الـ gradient descent. والحل يبدو بريئًا: دع النموذج ينحني. يبيّن هذا الدرس كيف، وكيف يتحوّل الانحناء سريعًا إلى حفظ.
جعل النموذج الخطي ينحني
الحيلة أن تُبقي الانحدار الخطي وتغيّر المدخلات. فإذا أضفت عمودًا bmi²، فإن نموذجًا “خطيًا” في bmi وbmi² يرسم قطعًا مكافئًا في bmi. ويولّد PolynomialFeatures هذه الأعمدة: كل قوة حتى الدرجة المختارة، إضافة إلى كل حاصل ضرب بين الـ features (أي التفاعلات (interactions)).
from sklearn.datasets import load_diabetes
from sklearn.preprocessing import PolynomialFeatures
X, y = load_diabetes(return_X_y=True, as_frame=True)
poly = PolynomialFeatures(degree=2, include_bias=False).fit(X[["bmi", "bp"]])
print(poly.get_feature_names_out())
for degree in [1, 2, 3]:
n = PolynomialFeatures(degree=degree, include_bias=False).fit(X).n_output_features_
print(f"degree {degree}: {n} columns from 10 features")يتحوّل الـ features الاثنان إلى خمسة أعمدة عند الدرجة 2. وتتحوّل الـ features العشرة إلى 65 عمودًا عند الدرجة 2 و285 عند الدرجة 3. يحذف include_bias=False العمود الثابت، لأن LinearRegression يحسب الـ intercept بنفسه.
لتسلسل التوسيع والانحدار، استخدم make_pipeline. فهي تنشئ estimator واحدًا ينفّذ كل خطوة بالترتيب؛ يدرّب fit كل خطوة على بيانات التدريب، ويمرّر predict البيانات الجديدة عبر الخطوات نفسها. ستبني pipelines أغنى في القسم 4.
نتيجة التدريب تواصل الصعود
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
X, y = load_diabetes(return_X_y=True, as_frame=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
for degree in [1, 2, 3]:
model = make_pipeline(PolynomialFeatures(degree=degree, include_bias=False),
LinearRegression()).fit(X_train, y_train)
print(f"degree {degree}: train R2 {model.score(X_train, y_train):6.3f} "
f"test R2 {model.score(X_test, y_test):7.3f} "
f"test MAE {mean_absolute_error(y_test, model.predict(X_test)):6.1f}")اقرأ الصفوف الثلاثة على مهل. الدرجة 2 تحسّن نتيجة التدريب وتسوّئ نتيجة الاختبار. والدرجة 3 كارثة متنكّرة في ثوب نجاح: R² بقيمة 0.90 في التدريب، وR² بقيمة -8.5 في الاختبار، وخطأ اختبار معتاد مقداره 151 نقطة، وهذا أسوأ من التنبؤ بالمتوسط للجميع. مع 285 عمودًا و331 مريض تدريب فقط، يكاد يملك النموذج من المقابض ما يكفي ليمرّ عبر كل نقطة تدريب. لقد تعلّم الضجيج.
الـ Underfitting والـ Overfitting
هذه الصفوف الثلاثة تقابل صورة ستراها في كل دورة لتعلّم الآلة، لأنها المفاضلة المركزية في هذا المجال.
- الـ Underfitting (انحياز مرتفع، high bias): النموذج أبسط من النمط. نتيجتا التدريب والاختبار ضعيفتان ومتقاربتان. والمزيد من المرونة يساعد.
- الـ Overfitting (تباين مرتفع، high variance): النموذج مرن بما يكفي ليطارد الضجيج. نتيجة التدريب مرتفعة، ونتيجة الاختبار أقل بكثير. وما يساعد هنا مرونة أقل، أو بيانات أكثر، أو الـ regularization.
تشخّص الجهة التي أنت فيها بمقارنة النتيجتين، لا بالنظر إلى نتيجة التدريب وحدها أبدًا. الفجوة الصغيرة مع نتائج ضعيفة تقول “أضف قدرة”؛ والفجوة الكبيرة تقول “انزعها”.
كمية البيانات تغيّر هذا التوازن. فمع 331 مريضًا، 285 عمودًا تهوّر؛ أما مع 300,000 مريض، فسيكون لنموذج الدرجة 3 نفسه مجال أضيق بكثير للحفظ، لأن ضجيج الصفوف الفردية يتلاشى بالتوسيط عبر هذا العدد الكبير من الأمثلة. لهذا تُعدّ “اجمع بيانات أكثر” علاجًا مشروعًا للـ overfitting وعديم الفائدة للـ underfitting: فالنموذج العاجز عن التعبير عن النمط لن يتحسّن فيه برؤية المزيد منه. وحين لا تكون متأكدًا من الجهة التي أنت فيها، يحسم الأمرَ منحنى التعلّم (learning curve)، أي نتيجتا التدريب والتحقق مرسومتين مقابل عدد صفوف التدريب: منحنيان يلتقيان عند مستوى منخفض يحتاجان إلى نموذج أغنى، ومنحنيان يبقيان متباعدين يحتاجان إلى بيانات أكثر أو نموذج أبسط.
اختيار الدرجة بأمانة
إليك هذه الوصفة مع ثلاثة features. جزء التحقق يأتي من X_train؛ ولا تُمسّ بيانات الاختبار حتى السطر الأخير تمامًا.
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
X, y = load_diabetes(return_X_y=True, as_frame=True)
X = X[["bmi", "bp", "s5"]]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
X_fit, X_val, y_fit, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=0)
def poly_model(degree):
return make_pipeline(PolynomialFeatures(degree=degree, include_bias=False), LinearRegression())
val_scores = {d: poly_model(d).fit(X_fit, y_fit).score(X_val, y_val) for d in range(1, 7)}
for d, s in val_scores.items():
print(f"degree {d}: validation R2 {s:6.3f}")
best = max(val_scores, key=val_scores.get)
final = poly_model(best).fit(X_train, y_train)
print("chosen degree", best, "| test R2", round(final.score(X_test, y_test), 3))يختار التحقق الدرجة 1، أي الخط المستقيم. على هذه البيانات لا يستحق المنحنى التباينَ الإضافي الذي يجلبه. وهذه نتيجة شائعة ومفيدة: فالإجراء الأمين كثيرًا ما يفضّل النموذج البسيط الذي كانت نظرة خاطفة إلى بيانات الاختبار ستُقنعك بالعدول عنه.
جزء تحقق واحد من نحو 80 مريضًا مليء بالضجيج هو أيضًا؛ فقد تفضّل قيمة مختلفة لـ random_state الدرجة 2. سيستبدله القسم 4 بالتحقق المتقاطع، الذي يأخذ المتوسط عبر عدة تقسيمات. والمبدأ يبقى كما هو.
خفض الدرجة طريقة فظّة للتحكم في التعقيد: إما أن يكون لديك عمود bmi × bp وإما لا. الدرس القادم يحتفظ بكل الأعمدة، ويعاقب النموذج بدلًا من ذلك على الاعتماد عليها بشدة، وهذا مقبض أدقّ.
أهم النقاط
- يضيف
PolynomialFeaturesأعمدة للمربعات وللتفاعلات، فيستطيع النموذج الخطي ملاءمة المنحنيات؛ ويتزايد عدد الأعمدة بسرعة كبيرة مع الدرجة. - الـ underfitting (ضعف التوافق) يعني أن النموذج أبسط من أن يلتقط النمط؛ فتكون نتيجتا التدريب والاختبار ضعيفتين معًا.
- الـ overfitting (الإفراط في التوافق) يعني أن النموذج تعلّم الضجيج في صفوف التدريب؛ فتكون نتيجة التدريب مرتفعة ونتيجة الاختبار أقل بكثير.
- اختر التعقيد (الدرجة، أو العمق، أو عدد الـ features) على جزء تحقق مقتطع من بيانات التدريب، ولا تختره أبدًا على بيانات الاختبار.
- العلاجات المعتادة للـ overfitting هي نموذج أبسط، أو بيانات أكثر، أو features أقل، أو الـ regularization.