Machine Learning: البدء مع Scikit-learn
آخر تحديث: 2026-08-26
واجهة Scikit-learn الموحدة تعني أن كل خوارزمية تُستدعى بنفس الطريقة — تعلّم واحدة، وتعرفها جميعًا.
1. ما ستتعلمه
- فلسفة تصميم Scikit-learn وواجهة API الموحدة: fit → predict → score
- الواجهات الأساسية الثلاث: Estimator و Transformer و Predictor
- نموذجك الأول: تدريب شجرة قرار على مجموعة بيانات Iris، مع السير في سير العمل الكامل train-test-split → fit → predict → evaluate
- خطوط أنابيب المعالجة المسبقة للبيانات: ربط StandardScaler + النموذج في كائن واحد
- محاولة Bob الأولى: استخدام sklearn لعمل تنبؤات بسيطة على مجموعة البيانات الصغيرة SalesPredict
2. قصة حقيقية من مبتدئ في ML
(1) نقطة الألم: كل مكتبة لها واجهة مختلفة
جرّب Bob ثلاث مكتبات ML مختلفة، ولكل واحدة منها اصطلاح الاستدعاء الخاص بها — واحدة تستخدم train()، وأخرى تستخدم fit_model()، وثالثة تستخدم learn(). قضى يومين في قراءة الوثائق فقط ليكتشف كيفية استدعائها، وكان التبديل إلى خوارزمية مختلفة يعني البدء من الصفر. واجهات API غير المتسقة هي أكبر عائق أمام البدء في ML.
(2) حل Scikit-learn
يحدد Scikit-learn تصميم واجهة API موحدة: كل خوارزمية تتبع نمط fit → predict → score. التبديل بين الخوارزميات يتطلب فقط تغيير سطر واحد.
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
# نفس الواجهة، خوارزمية مختلفة - فقط غيّر فئة النموذج
models = {
"LinearRegression": LinearRegression(),
"RandomForest": RandomForestRegressor(n_estimators=100),
}
for name, model in models.items():
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f"{name}: R² = {score:.3f}")
(3) النتيجة: واجهة واحدة تغطي 30+ خوارزمية
بعد أن أتقن Bob واجهة sklearn الموحدة، أصبح اصطلاح الاستدعاء لـ 30+ خوارزمية متطابقًا — من LinearRegression إلى XGBoost، فقط استبدل اسم الفئة.
3. فلسفة تصميم Scikit-learn والواجهة الموحدة
(1) نمط الواجهة الموحدة
graph LR
A[Estimator<br/>الفئة الأساسية] --> B[Transformer<br/>fit + transform]
A --> C[Predictor<br/>fit + predict]
A --> D[Model<br/>fit + predict + score]
B --> E[StandardScaler<br/>PCA<br/>OneHotEncoder]
C --> F[KMeans<br/>DBSCAN]
D --> G[LinearRegression<br/>RandomForest<br/>SVM]
(2) الواجهات الأساسية الثلاث
| الواجهة | الطرق الأساسية | الغرض | الأمثلة |
|---|---|---|---|
| Estimator | fit(X, y) |
تعلم المعاملات من البيانات | الفئة الأساسية لجميع النماذج |
| Transformer | fit() + transform() + fit_transform() |
المعالجة المسبقة للبيانات | StandardScaler, PCA |
| Predictor | fit() + predict() |
توليد التنبؤات | LinearRegression, SVM |
▶ مثال: أنماط استخدام Estimator/Transformer/Predictor
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np
# توليد بيانات عينة
rng = np.random.default_rng(42)
X = rng.uniform(0, 100, (200, 3))
y = 50 + 0.8 * X[:, 0] + 1.2 * X[:, 1] - 0.5 * X[:, 2] + rng.normal(0, 5, 200)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Transformer: StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit + transform في خطوة واحدة
X_test_scaled = scaler.transform(X_test) # فقط transform (يستخدم إحصائيات التدريب)
# Predictor: LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train)
predictions = model.predict(X_test_scaled)
score = model.score(X_test_scaled, y_test)
print(f"R² score: {score:.4f}")
print(f"Coefficients: {model.coef_}")
print(f"Intercept: {model.intercept_:.2f}")
Output:
# Executed successfully
4. نموذج ML الأول: تصنيف Iris
(1) سير عمل ML الكامل
▶ مثال: خط أنابيب كامل لتصنيف Iris بشجرة القرار
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# الخطوة 1: تحميل البيانات
iris = load_iris()
X, y = iris.data, iris.target
print(f"Features: {iris.feature_names}")
print(f"Classes: {iris.target_names}")
print(f"Shape: {X.shape}")
# الخطوة 2: تقسيم التدريب/الاختبار
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"Train: {X_train.shape[0]}, Test: {X_test.shape[0]}")
# الخطوة 3: تدريب النموذج
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)
# الخطوة 4: التنبؤ
y_pred = model.predict(X_test)
# الخطوة 5: التقييم
acc = accuracy_score(y_test, y_pred)
print(f"\nAccuracy: {acc:.4f}")
print(f"\nClassification Report:\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")
print(f"Confusion Matrix:\n{confusion_matrix(y_test, y_pred)}")
Output:
Features: ['sepal length (cm)', 'sepal width (cm)', ...]
Classes: ['setosa' 'versicolor' 'virginica']
Shape: (150, 4)
Train: 105, Test: 45
Accuracy: 1.0000
▶ مثال: تصور شجرة القرار
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 8))
plot_tree(model, feature_names=iris.feature_names,
class_names=iris.target_names, filled=True, ax=ax)
plt.title("Iris Decision Tree (max_depth=3)")
plt.tight_layout()
plt.savefig("iris_tree.png", dpi=150)
Output:
# Executed successfully
(2) فهم train_test_split بالتفصيل
| المعامل | المعنى | القيمة الموصى بها |
|---|---|---|
| test_size | نسبة مجموعة الاختبار | 0.2-0.3 |
| random_state | البذرة العشوائية | 42 (للتكرار) |
| stratify | عينة طبقية | مطلوب لمهام التصنيف |
| shuffle | ما إذا كان يجب خلط البيانات | True افتراضيًا |
5. خطوط أنابيب المعالجة المسبقة للبيانات
(1) لماذا تحتاج إلى Pipeline
يربط Pipeline المعالجة المسبقة والنموذج معًا كوحدة واحدة، مما يمنع تسرب البيانات (حيث تتسرب معلومات مجموعة الاختبار إلى عملية التدريب).
▶ مثال: Pipeline مع StandardScaler + نموذج
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
# بناء pipeline
pipe = Pipeline([
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=200)),
])
# التحقق المتقاطع مع pipeline (بدون تسرب بيانات!)
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"CV Accuracy: {scores.mean():.4f} +/- {scores.std():.4f}")
# التدريب على البيانات الكاملة والتنبؤ
pipe.fit(X, y)
new_sample = [[5.1, 3.5, 1.4, 0.2]]
prediction = pipe.predict(new_sample)
print(f"Prediction: {iris.target_names[prediction[0]]}")
Output:
# Executed successfully
(2) Pipeline مقابل المعالجة المسبقة اليدوية
| الجانب | المعالجة المسبقة اليدوية | Pipeline |
|---|---|---|
| خطر تسرب البيانات | مرتفع (سهل تركيب الـ scaler على بيانات الاختبار بالخطأ) | منخفض (Pipeline يعزل تلقائيًا) |
| قابلية قراءة الكود | متناثرة عبر خطوات متعددة | مجمعة في كائن واحد |
| التحقق المتقاطع | يتطلب حلقات يدوية | cross_val_score(pipe) |
| سهولة النشر | يجب حفظ الـ scaler والنموذج بشكل منفصل | احفظ كائن pipeline واحد |
▶ مثال: Pipeline خط الأساس SalesPredict
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
# محاكاة بيانات SalesPredict
rng = np.random.default_rng(42)
n = 500
df = pd.DataFrame({
"ad_spend": rng.uniform(10, 100, n),
"traffic": rng.uniform(100, 1000, n),
"category": rng.choice(["Elec", "Cloth", "Food"], n),
"is_weekend": rng.choice([0, 1], n),
})
df["revenue"] = 50 + 0.8 * df["ad_spend"] + 0.1 * df["traffic"] + rng.normal(0, 10, n)
# تحديد مجموعات الميزات
num_features = ["ad_spend", "traffic"]
cat_features = ["category", "is_weekend"]
# ColumnTransformer للمعالجة المسبقة المختلطة
preprocessor = ColumnTransformer([
("num", StandardScaler(), num_features),
("cat", OneHotEncoder(drop="first"), cat_features),
])
# Pipeline كامل
pipe = Pipeline([
("preprocessor", preprocessor),
("model", LinearRegression()),
])
X = df.drop(columns=["revenue"])
y = df["revenue"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)
print(f"SalesPredict Baseline R²: {score:.4f}")
# التنبؤ
sample = pd.DataFrame({"ad_spend": [50], "traffic": [500], "category": ["Elec"], "is_weekend": [1]})
pred = pipe.predict(sample)
print(f"Predicted revenue: {pred[0]:.1f} thousand USD")
Output:
# Executed successfully
6. أساسيات تقييم النموذج
(1) مقاييس التصنيف مقابل الانحدار
| المهمة | المقياس | المعنى | دالة sklearn |
|---|---|---|---|
| التصنيف | Accuracy | نسبة التنبؤات الصحيحة | accuracy_score |
| التصنيف | Precision | نسبة الإيجابيات الحقيقية بين الإيجابيات المتنبأ بها | precision_score |
| التصنيف | Recall | نسبة الإيجابيات الحقيقية بين الإيجابيات الفعلية | recall_score |
| التصنيف | F1 | المتوسط التوافقي للدقة والاستدعاء | f1_score |
| الانحدار | MAE | متوسط الخطأ المطلق | mean_absolute_error |
| الانحدار | MSE | متوسط مربع الخطأ | mean_squared_error |
| الانحدار | R² | معامل التحديد | r2_score |
▶ مثال: تقييم شامل لنموذج الانحدار
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([95, 160, 190, 260, 310])
mae = mean_absolute_error(y_true, y_pred)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_true, y_pred)
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
print(f"MAE: {mae:.2f} thousand USD")
print(f"RMSE: {rmse:.2f} thousand USD")
print(f"R²: {r2:.4f}")
print(f"MAPE: {mape:.1f}%")
Output:
# Executed successfully
❓ أسئلة شائعة
📖 ملخص
- واجهة sklearn الموحدة: Estimator(fit) → Transformer(fit+transform) → Predictor(fit+predict+score)
- سير عمل ML الكامل: تحميل البيانات → تقسيمها إلى تدريب/اختبار → التدريب على التدريب → التنبؤ → التقييم بالنتيجة
- تربط Pipelines المعالجة المسبقة + النموذج في وحدة واحدة، مما يمنع تسرب البيانات ويبسط النشر
- يتعامل ColumnTransformer مع الميزات ذات الأنواع المختلطة (StandardScaler للأعمدة الرقمية، OneHotEncoder للأعمدة الفئوية)
- يستخدم تقييم التصنيف accuracy/precision/recall/F1؛ ويستخدم تقييم الانحدار MAE/RMSE/R²/MAPE
- يُجري cross_val_score التحقق المتقاطع، وهو أكثر موثوقية من تقسيم تدريب/اختبار واحد
📝 تمارين
- أساسي (الصعوبة ⭐): استخدم sklearn لتحميل مجموعة بيانات Iris، وتدريب مصنف LogisticRegression، وطباعة الدقة. تلميح: اتبع سير العمل الكامل من القسم 4.
- متوسط (الصعوبة ⭐⭐): أنشئ Pipeline (StandardScaler + LogisticRegression) واستخدم التحقق المتقاطع بـ 5 طيات لمقارنة الدقة مع الـ scaler وبدونه. تلميح: شغّل cross_val_score على Pipeline مقابل النموذج المستقل.
- تحدي (الصعوبة ⭐⭐⭐): استخدم ColumnTransformer لبناء Pipeline من النوع المختلط لبيانات SalesPredict (توحيد الأعمدة الرقمية + ترميز one-hot للأعمدة الفئوية)، ثم درب نموذج LinearRegression واحسب R² و MAE. تلميح: راجع مثال SalesPredict Pipeline في القسم 5.
← الدرس السابق: تصور البيانات باستخدام Matplotlib و Seaborn | الدرس التالي: تمرين شامل — مشروع المبتدئين →