Machine Learning: تمرين شامل

آخر تحديث: 2026-08-26

لقد قضيت خمس دروس في تعلم الأدوات. حان الوقت لتجميعها معًا وإكمال مشروع ML حقيقي.

1. ما ستتعلمه


2. قصة حقيقية من مبتدئ في ML

(1) نقطة الألم: معرفة جميع الأدوات ولكن ليس كيفية ربطها

أنهى Bob تعلم NumPy و Pandas و Seaborn و Sklearn. ولكن عندما واجه مجموعة بيانات SalesPredict الحقيقية، لم يكن لديه أي فكرة من أين يبدأ — ينظف أولًا أم يصور أولًا؟ أي نموذج يستخدم؟ كيف تعرف ما إذا كان النموذج جيدًا؟ كان يعرف الأدوات، لكن سير عمل المشروع كان لغزًا.

(2) الحل: سير عمل شامل

يتبع كل مشروع ML خط أنابيب ثابتًا: تحميل → استكشاف → تنظيف → ميزات → خط أساس → تقييم → تكرار. ابدأ تشغيل خط الأساس أولًا، ثم حسّن خطوة بخطوة.

PYTHON
# قالب سير عمل ML الشامل
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error, r2_score

# الخطوة 1: التحميل والاستكشاف
df = pd.read_csv("sales_data.csv")
print(df.describe())

# الخطوة 2: التنظيف وإعداد الميزات
features = ["ad_spend", "traffic", "last_month_sales"]
target = "monthly_revenue"
df = df.dropna(subset=features + [target])

# الخطوة 3: تدريب خط الأساس
X_train, X_test, y_train, y_test = train_test_split(df[features], df[target], test_size=0.2)
model = LinearRegression().fit(X_train, y_train)
pred = model.predict(X_test)

# الخطوة 4: التقييم
print(f"R²: {r2_score(y_test, pred):.3f}, MAE: {mean_absolute_error(y_test, pred):.0f} USD")

(3) النتيجة: أول نموذج شامل في 30 دقيقة

باتباع سير العمل القياسي، حصل Bob على نموذج خط الأساس الأول يعمل في 30 دقيقة فقط. كان R² 0.72 فقط، ولكن مع وجود خط أساس، كل تحسين لاحق لديه نقطة مرجعية.


3. سير عمل ML الشامل

(1) خط أنابيب المشروع الكامل

100%
graph LR
    A[1. تحميل البيانات] --> B[2. EDA]
    B --> C[3. تنظيف البيانات]
    C --> D[4. اختيار الميزات]
    D --> E[5. تدريب خط الأساس]
    E --> F[6. التقييم]
    F --> G{جيد بما فيه الكفاية؟}
    G -->|لا| H[7. التكرار<br/>ميزات / نموذج أفضل]
    H --> D
    G -->|نعم| I[8. النشر]

▶ مثال: توليد بيانات SalesPredict المحاكاة

PYTHON
import pandas as pd
import numpy as np

rng = np.random.default_rng(42)
n = 1000

df = pd.DataFrame({
    "date": pd.date_range("2023-01-01", periods=n, freq="D"),
    "ad_spend_k": rng.uniform(5, 100, n),
    "traffic_k": rng.uniform(10, 500, n),
    "category": rng.choice(["Electronics", "Clothing", "Food", "Books", "Home"], n),
    "is_promotion": rng.choice([0, 1], n, p=[0.8, 0.2]),
    "customer_count": rng.integers(50, 500, n),
})

# صيغة الإيرادات بعلاقات واقعية
df["revenue_k"] = (
    20
    + 0.6 * df["ad_spend_k"]
    + 0.08 * df["traffic_k"]
    + 0.5 * df["customer_count"]
    + 50 * df["is_promotion"]
    + rng.normal(0, 15, n)
)
df["revenue_k"] = df["revenue_k"].clip(lower=0)

# حقن بعض القيم المفقودة والقيم المتطرفة
missing_idx = rng.choice(n, size=50, replace=False)
df.loc[missing_idx[:25], "ad_spend_k"] = np.nan
df.loc[missing_idx[25:], "traffic_k"] = np.nan

outlier_idx = rng.choice(n, size=10, replace=False)
df.loc[outlier_idx, "revenue_k"] *= 5

print(f"Dataset shape: {df.shape}")
print(f"Missing values:\n{df.isnull().sum()}")
df.to_csv("salespredict_data.csv", index=False)

Output:

TEXT 📖 للعرض فقط
# Executed successfully

4. تحليل البيانات الاستكشافي (EDA)

(1) نظرة عامة على البيانات

▶ مثال: EDA شامل

PYTHON
import pandas as pd
import numpy as np

df = pd.read_csv("salespredict_data.csv", parse_dates=["date"])

# نظرة عامة أساسية
print("=" * 50)
print("DATA OVERVIEW")
print("=" * 50)
print(f"Shape: {df.shape}")
print(f"\nDtypes:\n{df.dtypes}")
print(f"\nBasic Stats:\n{df.describe().round(2)}")
print(f"\nMissing Values:\n{df.isnull().sum()}")
print(f"\nCategory Distribution:\n{df['category'].value_counts()}")

Output:

TEXT 📖 للعرض فقط
=
DATA OVERVIEW
=

(2) تحليل التوزيع والاتجاه

▶ مثال: EDA بصري

PYTHON
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

df = pd.read_csv("salespredict_data.csv", parse_dates=["date"])
sns.set_theme(style="whitegrid")

fig, axes = plt.subplots(2, 3, figsize=(18, 10))

# (1) توزيع الإيرادات
sns.histplot(df["revenue_k"], bins=40, kde=True, ax=axes[0, 0], color="#2196F3")
axes[0, 0].set_title("Revenue Distribution (thousand USD)")

# (2) الإيرادات حسب الفئة
sns.boxplot(data=df, x="category", y="revenue_k", ax=axes[0, 1], palette="Set2")
axes[0, 1].set_title("Revenue by Category")

# (3) تأثير العروض الترويجية
sns.barplot(data=df, x="is_promotion", y="revenue_k", ax=axes[0, 2], palette="Pastel1")
axes[0, 2].set_title("Promotion Effect on Revenue")

# (4) الإنفاق الإعلاني مقابل الإيرادات
axes[1, 0].scatter(df["ad_spend_k"], df["revenue_k"], alpha=0.3, s=10)
axes[1, 0].set_xlabel("Ad Spend (thousand USD)")
axes[1, 0].set_ylabel("Revenue (thousand USD)")
axes[1, 0].set_title("Ad Spend vs Revenue")

# (5) الزيارات مقابل الإيرادات
axes[1, 1].scatter(df["traffic_k"], df["revenue_k"], alpha=0.3, s=10, color="#4CAF50")
axes[1, 1].set_xlabel("Traffic (thousand)")
axes[1, 1].set_ylabel("Revenue (thousand USD)")
axes[1, 1].set_title("Traffic vs Revenue")

# (6) خريطة حرارية للارتباط
num_cols = ["ad_spend_k", "traffic_k", "customer_count", "is_promotion", "revenue_k"]
corr = df[num_cols].corr()
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r", ax=axes[1, 2], vmin=-1, vmax=1)
axes[1, 2].set_title("Feature Correlations")

plt.tight_layout()
plt.savefig("eda_overview.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
# Executed successfully

(3) قالب النتائج الرئيسية لـ EDA

رقم النتيجة النتيجة التأثير التجاري الإجراء التالي
1 أيام العروض الترويجية تحقق متوسط 50 ألف دولار زيادة في الإيرادات العروض الترويجية فعالة للغاية الاحتفاظ بميزة is_promotion
2 ارتباط ad_spend و revenue = 0.72 الإعلانات تدفع المبيعات ميزة أساسية
3 10 قيم متطرفة عالية جدًا على الأرجح أخطاء إدخال بيانات تحتاج إلى تنظيف
4 5% من البيانات بها قيم مفقودة يؤثر على تدريب النموذج ملء أو حذف

5. تنظيف البيانات وإعداد الميزات

▶ مثال: خط أنابيب تنظيف البيانات

PYTHON
import pandas as pd
import numpy as np

df = pd.read_csv("salespredict_data.csv", parse_dates=["date"])

# الخطوة 1: معالجة القيم المفقودة
print(f"Before cleaning: {len(df)} rows")
df = df.dropna(subset=["revenue_k"])  # حذف إذا كان الهدف مفقودًا
df["ad_spend_k"] = df["ad_spend_k"].fillna(df["ad_spend_k"].median())
df["traffic_k"] = df["traffic_k"].fillna(df["traffic_k"].median())

# الخطوة 2: إزالة القيم المتطرفة باستخدام IQR
def remove_outliers(df, col, factor=1.5):
    q1, q3 = df[col].quantile([0.25, 0.75])
    iqr = q3 - q1
    return df[(df[col] >= q1 - factor * iqr) & (df[col] <= q3 + factor * iqr)]

df = remove_outliers(df, "revenue_k")
print(f"After cleaning: {len(df)} rows")

# الخطوة 3: هندسة الميزات
df["month"] = df["date"].dt.month
df["day_of_week"] = df["date"].dt.dayofweek
df["is_weekend"] = (df["day_of_week"] >= 5).astype(int)

# الخطوة 4: ترميز الفئات
df_encoded = pd.get_dummies(df, columns=["category"], drop_first=True)

# الخطوة 5: اختيار الميزات
feature_cols = [c for c in df_encoded.columns if c not in ["date", "revenue_k"]]
X = df_encoded[feature_cols]
y = df_encoded["revenue_k"]

print(f"Features: {feature_cols}")
print(f"X shape: {X.shape}, y shape: {y.shape}")

Output:

TEXT 📖 للعرض فقط
# Functions defined successfully

6. بناء نموذج خط الأساس وتقييمه

▶ مثال: تدريب خط أساس LinearRegression

PYTHON
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np

# تقسيم البيانات
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# خط أنابيب خط الأساس
baseline = Pipeline([
    ("scaler", StandardScaler()),
    ("model", LinearRegression()),
])

baseline.fit(X_train, y_train)
y_pred = baseline.predict(X_test)

# تقييم شامل
mae = mean_absolute_error(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
mape = np.mean(np.abs((y_test - y_pred) / y_test)) * 100

print("=" * 50)
print("BASELINE MODEL EVALUATION")
print("=" * 50)
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:

TEXT 📖 للعرض فقط
=
BASELINE MODEL EVALUATION
=

▶ مثال: تصور نتائج التنبؤ

PYTHON
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# (1) تشتت الفعلي مقابل المتنبأ به
axes[0].scatter(y_test, y_pred, alpha=0.5, s=20)
axes[0].plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], "r--", lw=2)
axes[0].set_xlabel("Actual Revenue (thousand USD)")
axes[0].set_ylabel("Predicted Revenue (thousand USD)")
axes[0].set_title("Actual vs Predicted")

# (2) توزيع البواقي
residuals = y_test - y_pred
axes[1].hist(residuals, bins=30, edgecolor="white", color="#2196F3")
axes[1].axvline(x=0, color="red", linestyle="--")
axes[1].set_xlabel("Residual (thousand USD)")
axes[1].set_title("Residual Distribution")

plt.tight_layout()
plt.savefig("baseline_evaluation.png", dpi=150)

Output:

TEXT 📖 للعرض فقط
# Executed successfully

(1) تفسير مقاييس الأعمال

المقياس قيمة خط الأساس المعنى التجاري الهدف
MAE ~12 ألف دولار متوسط خطأ التنبؤ 12 ألف دولار < 10 آلاف
RMSE ~15 ألف دولار الأخطاء الكبيرة تُعاقب أكثر < 12 آلاف
~0.72 يفسر 72% من التباين > 0.85
MAPE ~15% متوسط خطأ النسبة المئوية < 10%
📌 نقطة رئيسية: يعني MAPE بنسبة 15% أنه عندما يتنبأ Bob بمبيعات شهرية قدرها مليون دولار، قد يصل الخطأ إلى 150 ألف دولار — مما يؤدي مباشرة إلى تخزين زائد أو نفاد المخزون. ستعمل النماذج المتقدمة في المرحلتين 2-3 على خفض هذا الخطأ إلى أقل من 8%.


❓ أسئلة شائعة

س لماذا نستخدم LinearRegression لخط الأساس بدلاً من نموذج أكثر تعقيدًا؟
ج الغرض من خط الأساس هو إنشاء حد أدنى للأداء وفهم قابلية التنبؤ الجوهرية للبيانات. يمكن للنماذج المعقدة أن تُفرط في التجهيز وتخفي الإشارة الحقيقية. ابدأ بسيطًا لتحديد معيار، ثم حسّن تدريجيًا.
س هل أنظر إلى MAE أم RMSE؟
ج كليهما. MAE قوي ضد القيم المتطرفة ويعكس الأداء المتوسط؛ RMSE يعاقب الأخطاء الكبيرة بشكل أكبر ويعكس سيناريوهات أسوأ الحالات. إذا كان RMSE أكبر بكثير من MAE، فهذا يعني وجود بضعة أخطاء فردية كبيرة.
س هل MAPE بنسبة 15% جيد أم سيء؟
ج ذلك يعتمد على المجال. للتنبؤ بمبيعات التجارة الإلكترونية، MAPE < 10% هو مستوى الإنتاج؛ 15% هو مستوى خط الأساس. ولكن بالنسبة للسلاسل الزمنية المالية، يعتبر MAPE < 2% جيدًا. المفتاح هو ربطه بتكلفة الأعمال.
س كم من الوقت يجب أن أقضيه في EDA؟
ج لمجموعة بيانات جديدة، يجب أن تستغرق EDA 20-30% من إجمالي وقت المشروع. لا تتخطى EDA وتنطلق مباشرة إلى النمذجة — فقد تفوتك ميزات أو مشكلات بيانات حرجة.
س هل أملأ القيم المفقودة بالوسيط أم المتوسط؟
ج استخدم الوسيط عند وجود قيم متطرفة (فهو قوي)؛ استخدم المتوسط عندما يكون التوزيع طبيعيًا تقريبًا. يمكنك أيضًا استخدام طرق أكثر تقدمًا مثل KNNImputer أو IterativeImputer.
س هل أزيل القيم المتطرفة؟
ج ميز بين "الحالات الشاذة الحقيقية" و "الحالات الشاذة الكاذبة". أخطاء إدخال البيانات → احذف. الأحداث المتطرفة الحقيقية (مثل الجمعة السوداء) → احتفظ بها وميّزها بميزة خاصة. الإزالة العمياء للقيم المتطرفة تفقد المعلومات.

📖 ملخص

📝 تمارين

  1. أساسي (الصعوبة ⭐): استخدم بياناتك الخاصة (أو مجموعة بيانات sklearn المدمجة مثل housing) لإكمال خط الأنابيب الكامل: تحميل → EDA → نموذج خط الأساس → التقييم. تلميح: راجع قوالب الكود في الأقسام 4-6.
  2. متوسط (الصعوبة ⭐⭐): فوق نموذج خط الأساس، أضف ميزتين جديدتين (مثلًا حد تفاعل ad_spend * is_promotion)، وقارن ما إذا كان R² و MAPE يتحسنان. تلميح: استخدم df.assign() لإضافة أعمدة جديدة.
  3. تحدي (الصعوبة ⭐⭐⭐): نفّذ إطار مقارنة نموذج بسيط — درب LinearRegression و DecisionTreeRegressor و RandomForestRegressor في وقت واحد، وأخرج جدول مقارنة لـ MAE/RMSE/R²/MAPE لكل نموذج. تلميح: حلقة فوق النماذج باستخدام قاموس واجمع النتائج في DataFrame.

← الدرس السابق: البدء مع Scikit-learn | الدرس التالي: الانحدار الخطي →

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%