Machine Learning: تمرين شامل
آخر تحديث: 2026-08-26
لقد قضيت خمس دروس في تعلم الأدوات. حان الوقت لتجميعها معًا وإكمال مشروع ML حقيقي.
1. ما ستتعلمه
- سير العمل الشامل: تحميل البيانات → EDA → اختيار الميزات → نموذج خط الأساس → التقييم
- EDA عمليًا: تحليل التوزيع والارتباط والاتجاه على بيانات التجارة الإلكترونية SalesPredict
- بناء نموذج خط الأساس: LinearRegression كمعيار للتنبؤ بالمبيعات
- تفسير النتائج: حساب R² و MAE و RMSE — وما تعنيه للأعمال
- مراجعة المشروع: الخلاصات الرئيسية من مرحلة المبتدئين واتجاهات النمو
2. قصة حقيقية من مبتدئ في ML
(1) نقطة الألم: معرفة جميع الأدوات ولكن ليس كيفية ربطها
أنهى Bob تعلم NumPy و Pandas و Seaborn و Sklearn. ولكن عندما واجه مجموعة بيانات SalesPredict الحقيقية، لم يكن لديه أي فكرة من أين يبدأ — ينظف أولًا أم يصور أولًا؟ أي نموذج يستخدم؟ كيف تعرف ما إذا كان النموذج جيدًا؟ كان يعرف الأدوات، لكن سير عمل المشروع كان لغزًا.
(2) الحل: سير عمل شامل
يتبع كل مشروع ML خط أنابيب ثابتًا: تحميل → استكشاف → تنظيف → ميزات → خط أساس → تقييم → تكرار. ابدأ تشغيل خط الأساس أولًا، ثم حسّن خطوة بخطوة.
# قالب سير عمل 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) خط أنابيب المشروع الكامل
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 المحاكاة
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:
# Executed successfully
4. تحليل البيانات الاستكشافي (EDA)
(1) نظرة عامة على البيانات
▶ مثال: EDA شامل
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:
=
DATA OVERVIEW
=
(2) تحليل التوزيع والاتجاه
▶ مثال: EDA بصري
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:
# Executed successfully
(3) قالب النتائج الرئيسية لـ EDA
| رقم النتيجة | النتيجة | التأثير التجاري | الإجراء التالي |
|---|---|---|---|
| 1 | أيام العروض الترويجية تحقق متوسط 50 ألف دولار زيادة في الإيرادات | العروض الترويجية فعالة للغاية | الاحتفاظ بميزة is_promotion |
| 2 | ارتباط ad_spend و revenue = 0.72 | الإعلانات تدفع المبيعات | ميزة أساسية |
| 3 | 10 قيم متطرفة عالية جدًا | على الأرجح أخطاء إدخال بيانات | تحتاج إلى تنظيف |
| 4 | 5% من البيانات بها قيم مفقودة | يؤثر على تدريب النموذج | ملء أو حذف |
5. تنظيف البيانات وإعداد الميزات
▶ مثال: خط أنابيب تنظيف البيانات
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:
# Functions defined successfully
6. بناء نموذج خط الأساس وتقييمه
▶ مثال: تدريب خط أساس LinearRegression
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:
=
BASELINE MODEL EVALUATION
=
▶ مثال: تصور نتائج التنبؤ
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:
# Executed successfully
(1) تفسير مقاييس الأعمال
| المقياس | قيمة خط الأساس | المعنى التجاري | الهدف |
|---|---|---|---|
| MAE | ~12 ألف دولار | متوسط خطأ التنبؤ 12 ألف دولار | < 10 آلاف |
| RMSE | ~15 ألف دولار | الأخطاء الكبيرة تُعاقب أكثر | < 12 آلاف |
| R² | ~0.72 | يفسر 72% من التباين | > 0.85 |
| MAPE | ~15% | متوسط خطأ النسبة المئوية | < 10% |
❓ أسئلة شائعة
📖 ملخص
- خط أنابيب مشروع ML القياسي: تحميل → EDA → تنظيف → ميزات → خط أساس → تقييم → تكرار
- الأهداف الأساسية لـ EDA: فهم التوزيعات، وتحديد الحالات الشاذة، وإيجاد الميزات شديدة الارتباط، والتحقق من افتراضات الأعمال
- أربع خطوات لتنظيف البيانات: معالجة القيم المفقودة → معالجة القيم المتطرفة → تحويل الأنواع → ترميز الميزات
- استخدم LinearRegression + Pipeline لخط الأساس لتأسيس معيار أداء
- اربط مقاييس التقييم بالمعنى التجاري: يعني MAPE بنسبة 15% خطأ 150 ألف دولار على توقع بمليون دولار
- خلاصات مرحلة المبتدئين: تم ربط مجموعة الأدوات، وتم إنشاء سير عمل المشروع، وتم بناء خط الأساس — الآن كرر وحسّن
📝 تمارين
- أساسي (الصعوبة ⭐): استخدم بياناتك الخاصة (أو مجموعة بيانات sklearn المدمجة مثل housing) لإكمال خط الأنابيب الكامل: تحميل → EDA → نموذج خط الأساس → التقييم. تلميح: راجع قوالب الكود في الأقسام 4-6.
- متوسط (الصعوبة ⭐⭐): فوق نموذج خط الأساس، أضف ميزتين جديدتين (مثلًا حد تفاعل
ad_spend * is_promotion)، وقارن ما إذا كان R² و MAPE يتحسنان. تلميح: استخدمdf.assign()لإضافة أعمدة جديدة. - تحدي (الصعوبة ⭐⭐⭐): نفّذ إطار مقارنة نموذج بسيط — درب LinearRegression و DecisionTreeRegressor و RandomForestRegressor في وقت واحد، وأخرج جدول مقارنة لـ MAE/RMSE/R²/MAPE لكل نموذج. تلميح: حلقة فوق النماذج باستخدام قاموس واجمع النتائج في DataFrame.
← الدرس السابق: البدء مع Scikit-learn | الدرس التالي: الانحدار الخطي →