لقد قمت بتدريب نموذج التعلم الآلي الأول الخاص بك. إنه يعمل بشكل رائع على بيانات التدريب الخاصة بك - دقة تصل إلى 98%! قمت باختباره على بيانات جديدة، لكنه انهار: دقة تبلغ 61%. ما الخطأ الذي حدث؟
من المؤكد تقريبًا أن النموذج الخاص بك به ملاءمة زائدة. يعد هذا أحد وضعي الفشل الأكثر شيوعًا في التعلم الآلي، وفهمه - جنبًا إلى جنب مع نقيضه، القصور - أمر ضروري لبناء نماذج تعمل بالفعل في العالم الحقيقي.
قبل التعمق في الأمثلة، من المفيد فهم الإطار النظري وراء هذه المفاهيم: مفاضلة التحيز والتباين.
كل نموذج يرتكب أخطاء في التنبؤ. ويمكن تقسيم هذه الأخطاء إلى ثلاثة أجزاء:
Total Error = Bias² + Variance + Irreducible Noise
التحيز هو الخطأ الناتج عن الافتراضات الخاطئة في النموذج. يعتبر نموذج التحيز العالي بسيطًا للغاية، فهو يخطئ بشكل منهجي في فهم النمط الحقيقي في البيانات.
التباين هو الخطأ الناتج عن الحساسية للتقلبات الصغيرة في بيانات التدريب. يعد النموذج عالي التباين معقدًا للغاية، فهو يحفظ بيانات التدريب، بما في ذلك الضوضاء، بدلاً من تعلم النمط الأساسي.
الضوضاء غير القابلة للاختزال هي العشوائية الطبيعية في البيانات التي لا يمكن لأي نموذج التخلص منها.
المقايضة: تقليل التحيز يميل إلى زيادة التباين، والعكس صحيح. مهمتك كممارس للتعلم الآلي هي العثور على المكان المناسب.
يحدث نقص التجهيز عندما يكون نموذجك بسيطًا للغاية بحيث لا يتمكن من التقاط النمط الحقيقي في البيانات. إنه يعمل بشكل سيئ على * كل من * بيانات التدريب والبيانات الجديدة.
تخيل أن لديك بيانات توضح أسعار المنازل بناءً على حجمها. العلاقة الحقيقية هي تقريبًا منحنى لطيف - ترتفع الأسعار مع الحجم، ولكن مع بعض الثبات عند النهاية العليا.
إذا قمت بتناسب خط أفقي مستقيم مع هذه البيانات:
# Underfitting: overly simple model
from sklearn.linear_model import LinearRegression
import numpy as np
# True relationship is quadratic, but we're fitting a simple mean
model = DummyRegressor(strategy='mean')
model.fit(X_train, y_train)
# Training accuracy: 55%
# Test accuracy: 54%
# Both are bad — classic underfitting
يتجاهل النموذج العلاقة الفعلية بين حجم المنزل وسعره. لا يهم ما إذا كنت تعرض بيانات التدريب أو البيانات الجديدة، فهذا خطأ في كلتا الحالتين.
تسجيل الدخول للانضمام إلى النقاش
التجاوز يحدث عندما يتعلم نموذجك بيانات التدريب جيدًا جدًا - بما في ذلك الضوضاء والتنوع العشوائي - ويفشل في التعميم على الأمثلة الجديدة.
باستخدام كثيرة الحدود 15 درجة لتناسب نفس بيانات أسعار المنازل:
# Overfitting: overly complex model
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
# Degree-15 polynomial — wildly complex for this problem
model = make_pipeline(PolynomialFeatures(15), LinearRegression())
model.fit(X_train, y_train)
train_score = model.score(X_train, y_train) # 0.99 — looks amazing!
test_score = model.score(X_test, y_test) # 0.43 — terrible on new data
لقد قام كثير الحدود بتحريف نفسه إلى عقد لتمريره عبر كل نقطة تدريب، بما في ذلك القيم المتطرفة الصاخبة. لقد حفظ مجموعة التدريب بدلاً من تعلم النمط الأساسي. أما بالنسبة للبيانات غير المرئية، فلا فائدة منها.
من الأدوات الأساسية لاكتشاف التجاوز هو تقسيم بياناتك إلى ثلاث مجموعات:
from sklearn.model_selection import train_test_split
# First split: hold out 20% as the final test set
X_train_val, X_test, y_train_val, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# Second split: hold out 20% of remaining as validation set
X_train, X_val, y_train, y_val = train_test_split(
X_train_val, y_train_val, test_size=0.25, random_state=42
)
# Result: 60% train / 20% validation / 20% test
مجموعة التحقق من الصحة هي نظام الإنذار المبكر الخاص بك. إذا استمرت دقة التدريب في التحسن ولكن ثبات أو انخفاض دقة التحقق من الصحة، فأنت في حالة فرط في التجهيز.
يضيف التنظيم عقوبة إلى دالة الخسارة التي تثبط النموذج عن تعلم الأنماط المعقدة للغاية.
تسوية L2 (ريدج) تعاقب الأوزان الكبيرة:
from sklearn.linear_model import Ridge
model = Ridge(alpha=1.0) # alpha controls regularisation strength
model.fit(X_train, y_train)
يمكن أن يؤدي تنظيم L1 (Lasso) إلى دفع بعض الأوزان إلى الصفر، مع إجراء تحديد الميزات:
from sklearn.linear_model import Lasso
model = Lasso(alpha=0.1)
model.fit(X_train, y_train)
أثناء التدريب، "أسقط" بشكل عشوائي (اضبط على الصفر) نسبة من الخلايا العصبية:
import torch.nn as nn
model = nn.Sequential(
nn.Linear(128, 64),
nn.ReLU(),
nn.Dropout(p=0.5), # 50% of neurons randomly deactivated during training
nn.Linear(64, 1)
)
وهذا يمنع الخلايا العصبية من التكيف المشترك ويجبر الشبكة على تعلم تمثيلات أكثر قوة وموزعة.
مراقبة فقدان التحقق من الصحة أثناء التدريب والتوقف عندما يبدأ في الزيادة:
from tensorflow.keras.callbacks import EarlyStopping
early_stop = EarlyStopping(
monitor='val_loss',
patience=5, # stop after 5 epochs without improvement
restore_best_weights=True
)
model.fit(X_train, y_train,
validation_data=(X_val, y_val),
callbacks=[early_stop],
epochs=1000)
المزيد من البيانات يجعل من الصعب على النموذج حفظ الضوضاء - هناك ببساطة الكثير مما لا يمكن ملاءمته تمامًا. عندما يكون جمع البيانات مكلفًا، يمكن أن يكون تعزيز البيانات (إنشاء نسخ معدلة من الأمثلة الموجودة) مفيدًا.
في بعض الأحيان يكون الحل الصحيح هو ببساطة اختيار نموذج أقل تعقيدًا للمشكلة.
مع مجموعات البيانات الصغيرة، قد يكون تقسيم قطار/فال واحد مضللاً بسبب العشوائية. يعطي التحقق المتبادل من K-fold تقديرًا أكثر موثوقية:
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier(n_estimators=100)
# 5-fold cross-validation
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')
print(f"Mean accuracy: {scores.mean():.3f} ± {scores.std():.3f}")
# Mean accuracy: 0.847 ± 0.023
يتم تقسيم البيانات إلى 5 طيات؛ يتدرب النموذج على 4 ويتم التحقق من صحته على 1، ويتناوب في كل مرة. النتيجة النهائية هي المتوسط في جميع النقاط الخمس — وهي أكثر موثوقية بكثير من تقسيم واحد.
يحقق النموذج دقة بنسبة 99% في بيانات التدريب و62% فقط في بيانات الاختبار. ماذا يدل هذا؟