الوحدة 1 · ما هو تعلّم الآلة
النماذج في scikit-learn: fit وpredict وscore
18 دقراءة 4 دتمرين Python
الدرس في لمحة
استخدم أي نموذج في scikit-learn عبر الاستدعاءات الثلاثة نفسها (fit وpredict وscore)، واقرأ ما تعلّمه النموذج بعد التدريب، واكتشف الحفظ بمقارنة نتيجتي التدريب والاختبار.
- 1ثلاثة استدعاءات
- 2ما الذي يعرفه النموذج بعد التدريب
- 3نتيجة التدريب تكذب
- 4العقد نفسه، والافتراضات مختلفة
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
يأتي scikit-learn بعشرات النماذج، من الخطوط المستقيمة إلى غابات الأشجار، وتستخدمها جميعًا بالطريقة نفسها. تعلّم ثلاثة استدعاءات وستستطيع تجربة أيّ منها على بيانات الانقطاع في بضعة أسطر. هذا الاتساق هو السبب الرئيسي في كون scikit-learn المكتبة الافتراضية لتعلّم الآلة الكلاسيكي.
ثلاثة استدعاءات
النموذج في scikit-learn هو estimator (مقدِّر): كائن Python تنشئه بإعداداته، وتدرّبه بـ fit، وتستخدمه بـ predict وscore.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
churn = pd.read_csv("churn.csv")
features = ["tenure_days", "orders", "total_spent", "avg_order_value",
"days_since_last_order", "used_coupon", "support_tickets", "mobile_share"]
X, y = churn[features], churn["churned"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42, stratify=y)
model = DecisionTreeClassifier(max_depth=3, random_state=42) # 1. create
model.fit(X_train, y_train) # 2. learn
print(model.predict(X_test)[:10]) # 3. use
print("train accuracy:", round(model.score(X_train, y_train), 3))
print("test accuracy: ", round(model.score(X_test, y_test), 3))ما يفعله كل استدعاء:
- الـ constructor يأخذ الـ hyperparameters: خيارات تحدّدها قبل التدريب.
max_depth=3تعني أن الشجرة لا تطرح أكثر من ثلاثة أسئلة متتالية. وrandom_state=42تجعل كسر التعادلات قابلًا للتكرار. fit(X_train, y_train)تنظر في الأمثلة وتتعلّم معاملات (parameters) النموذج. في الشجرة، هذه المعاملات هي الأسئلة والعتبات (“هلdays_since_last_orderأكبر من 236.5؟”). وتُعيد النموذج نفسه، لذا يعمل أيضًاmodel = DecisionTreeClassifier().fit(X, y).predict(X)تُعيد تنبؤًا واحدًا لكل صف: وهنا مصفوفة من الأصفار والآحاد.score(X, y)تتنبأ ثم تقارن بالإجابات الحقيقية. في المصنِّفات تُعيد الـ accuracy (الدقة)، أي نسبة التنبؤات الصحيحة. وفي نماذج الانحدار تُعيد R²، الذي ستتعرّف عليه في القسم 2.
ما الذي يعرفه النموذج بعد التدريب
كل ما يتعلّمه النموذج أثناء fit يُخزَّن في سمات (attributes) تنتهي أسماؤها بشرطة سفلية. وهي غير موجودة قبل fit؛ فطلب إحداها يرفع AttributeError، واستدعاء predict على نموذج غير مدرَّب يرفع NotFittedError.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
churn = pd.read_csv("churn.csv")
features = ["tenure_days", "orders", "total_spent", "avg_order_value",
"days_since_last_order", "used_coupon", "support_tickets", "mobile_share"]
X_train, X_test, y_train, y_test = train_test_split(
churn[features], churn["churned"], test_size=0.25, random_state=42,
stratify=churn["churned"])
model = DecisionTreeClassifier(max_depth=3, random_state=42).fit(X_train, y_train)
print(model.classes_) # the labels it saw: [0 1]
print(model.n_features_in_) # 8
print(model.feature_names_in_[:3])
new_customer = pd.DataFrame([{
"tenure_days": 400, "orders": 2, "total_spent": 180.0, "avg_order_value": 90.0,
"days_since_last_order": 150, "used_coupon": 0, "support_tickets": 1,
"mobile_share": 0.5}])
print(model.predict(new_customer)) # [1]: likely to churn
print(model.predict_proba(new_customer)) # [[0.36 0.64]]تعطيك predict_proba الاحتمال الذي يقدّره النموذج لكل فئة، بترتيب classes_. هذا العميل يحصل على 64% للانقطاع. ستعتمد على الاحتمالات كثيرًا في القسم 3، لأنها تتيح لك أن تختار مقدار الحذر الذي تريده.
نتيجة التدريب تكذب
أزل الآن حدّ العمق وراقب ما يحدث. الشجرة غير المحدودة تواصل طرح الأسئلة حتى يجلس كل عميل من عملاء التدريب في ورقة لا تحوي إلا فئته.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
churn = pd.read_csv("churn.csv")
features = ["tenure_days", "orders", "total_spent", "avg_order_value",
"days_since_last_order", "used_coupon", "support_tickets", "mobile_share"]
X_train, X_test, y_train, y_test = train_test_split(
churn[features], churn["churned"], test_size=0.25, random_state=42,
stratify=churn["churned"])
for model in [DecisionTreeClassifier(max_depth=3, random_state=42),
DecisionTreeClassifier(random_state=42),
KNeighborsClassifier(n_neighbors=5)]:
model.fit(X_train, y_train)
print(f"{model!r:55} train {model.score(X_train, y_train):.2f} test {model.score(X_test, y_test):.2f}")الشجرة غير المحدودة مثالية على العملاء الـ 298 الذين درستهم، وأسوأ من الشجرة الضحلة على المئة الذين لم ترَهم. لقد حفظت خصوصيات العملاء الأفراد. هذه الفجوة بين أداء التدريب وأداء الاختبار هي الـ overfitting (الإفراط في التوافق)، وستقضي جزءًا كبيرًا من القسم 2 في تعلّم كيفية التحكم فيها.
لاحظ أيضًا النموذج الثالث. خوارزمية أقرب k جيران (k-nearest neighbours) لا تشبه الشجرة في شيء (فهي تتنبأ بالنظر إلى أكثر خمسة عملاء تدريب تشابهًا)، ومع ذلك الكود متطابق. تبديل النموذج يكلّفك سطرًا واحدًا.
العقد نفسه، والافتراضات مختلفة
الواجهة المشتركة تُخفي أفكارًا مختلفة جدًا عن العالم. فالشجرة تفترض أن الانقطاع يمكن وصفه بعدد قليل من أسئلة نعم/لا ذات حدود فاصلة حادة. وأقرب k جيران تفترض أن العملاء المتشابهين يتصرّفون بالطريقة نفسها، حيث “التشابه” يعني القرب حين يُعامَل كل عمود كمسافة. لا أحد الافتراضين صحيح بإطلاق؛ كلٌّ منهما مفيد في مواقف وخاطئ في أخرى. ولهذا تجرّب عدة نماذج على التقسيم نفسه بدل أن تتجادل حول أيّها يجب أن يفوز.
نماذج الانحدار تلتزم العقد نفسه. DecisionTreeRegressor وLinearRegression تأخذان y رقميًا، وتُعيد predict أرقامًا بدل الفئات، وتُعيد score قيمة R² بدل الـ accuracy. كل ما تتعلّمه عن estimator واحد ينتقل إلى البقية.
تفصيلتان توفّران عليك الارتباك لاحقًا. استدعاء fit مرة ثانية يمحو ما تعلّمه النموذج من قبل ويبدأ من الصفر؛ ولا يضيف إلى معرفته القديمة. والإعدادات التي مرّرتها إلى الـ constructor تبقى مقروءة كسمات عادية (model.max_depth)، فيمكنك دائمًا التحقق مما طُلب من نموذج مدرَّب أن يفعله.
لديك الآن نموذج بدقة 73% على بيانات الاختبار. هل هذا جيد؟ لا يمكنك الحكم بعد، لأنك لم تسأل كم سيحقق نموذج بلا أي ذكاء على الإطلاق. هذا هو موضوع الدرس القادم.
أهم النقاط
- كل estimator في scikit-learn يُنشأ بإعداداته، ويتعلّم في
fit(X, y)، ويُستخدم عبرpredict(X)وscore(X, y). - الـ hyperparameters مثل
max_depthتحدّدها أنت قبل التدريب؛ أما المعاملات (parameters) مثل عتبات التقسيم فتُتعلَّم أثناءfit. - سمات (attributes) النموذج المدرَّب تنتهي بشرطة سفلية (
classes_وfeature_names_in_) ولا توجد إلا بعدfit. - تُعيد
scoreقيمة الـ accuracy للمصنِّفات وقيمة R² لنماذج الانحدار. - الفجوة الكبيرة بين نتيجتي التدريب والاختبار تعني أن النموذج حفظ صفوف تدريبه.