بعد تعلّم أساسيات Python، وقراءة البيانات باستخدام NumPy وPandas، وتصوير البيانات باستخدام Matplotlib وSeaborn، تأتي الخطوة التي ينتظرها كثير من الطلاب: بناء أول نموذج تعلم آلي.
لكن تدريب النموذج لا يبدأ باختيار خوارزمية معقدة أو الضغط على أمر fit. المهمة الحقيقية هي تحديد السؤال، واختيار البيانات المناسبة، ومنع النموذج من رؤية الإجابة مسبقًا، ثم قياس ما إذا كان تعلّم شيئًا مفيدًا فعلًا.
في هذا الدرس سنبني نموذجًا بسيطًا يتوقع الدرجة النهائية لطالب اعتمادًا على ساعات المذاكرة ونسبة الحضور وعدد الواجبات المنجزة. البيانات المستخدمة اصطناعية ومخصصة للتعليم فقط، وليست مناسبة لتقييم طلاب حقيقيين أو اتخاذ قرارات أكاديمية.
الخلاصة السريعة
لبناء نموذج تعلم آلي بصورة صحيحة:
- حدّد القيمة التي تريد توقعها.
- افصل الميزات عن الهدف.
- قسّم البيانات إلى تدريب واختبار.
- أنشئ خط أساس بسيطًا قبل تدريب النموذج.
- درّب النموذج على بيانات التدريب فقط.
- اختبره على بيانات لم يرها أثناء التدريب.
- قِس الخطأ ولا تكتفِ بمشاهدة بعض التوقعات.
- افحص تسرّب البيانات قبل الوثوق بالنتيجة.
النجاح ليس أن يعمل الكود دون خطأ، بل أن يتفوق النموذج على توقع بسيط ويعمل بصورة معقولة على بيانات جديدة.
ما نموذج تعلم الآلة؟
نموذج تعلم الآلة هو دالة تتعلم علاقة تقريبية بين المدخلات والنتيجة المطلوبة من أمثلة سابقة.
في مثالنا ستكون المدخلات:
- عدد ساعات المذاكرة.
- نسبة الحضور.
- عدد الواجبات المنجزة.
أما النتيجة التي نريد توقعها فهي:
- الدرجة النهائية.
يتعلم النموذج من سجلات سابقة، ثم يستخدم العلاقة التي وجدها لإنتاج توقع لسجل جديد.
هذا لا يعني أن النموذج فهم الطالب أو عرف مستقبله. هو فقط تعلّم نمطًا رياضيًا موجودًا في البيانات التي قدمناها له.
التصنيف أم الانحدار؟
قبل اختيار الخوارزمية، حدّد نوع الإجابة التي تريدها.
| نوع المسألة | شكل النتيجة | مثال |
|---|---|---|
| التصنيف Classification | فئة أو اسم | ناجح أو متعثر |
| الانحدار Regression | قيمة رقمية | توقع درجة من 100 |
| التجميع Clustering | مجموعات غير معروفة مسبقًا | تقسيم العملاء حسب السلوك |
سنستخدم في هذا الدرس الانحدار؛ لأن الدرجة النهائية قيمة رقمية مستمرة.
إذا حوّلنا السؤال إلى: «هل سيجتاز الطالب المقرر؟»، فستصبح المسألة تصنيفًا بدلًا من انحدار.
ما الأدوات التي نحتاجها؟
سنستخدم:
- NumPy لإنشاء بيانات اصطناعية قابلة لإعادة التجربة.
- Pandas لتنظيم البيانات في جدول.
- Matplotlib لتصوير النتائج.
- Scikit-learn لتقسيم البيانات وتدريب النموذج وقياس أدائه.
ثبّت المكتبات عند الحاجة:
pip install numpy pandas matplotlib scikit-learn
وفي Google Colab تكون معظم هذه المكتبات مثبتة عادةً.
إنشاء بيانات التدريب
سننشئ 120 سجلًا اصطناعيًا. استخدام random_state أو مولّد عشوائي برقم ثابت يجعل النتائج قابلة لإعادة التجربة.
import numpy as npimport pandas as pdrng = np.random.default_rng(42)n = 120data = pd.DataFrame({ "study_hours": rng.uniform(1, 8, n).round(1), "attendance": rng.uniform(55, 100, n).round(1), "assignments": rng.integers(2, 11, n)})noise = rng.normal(0, 5, n)data["final_score"] = ( 5 + 5 * data["study_hours"] + 0.35 * data["attendance"] + 1.4 * data["assignments"] + noise).clip(0, 100).round(1)print(data.head())
استخدمنا ضوضاء عشوائية بسيطة حتى لا تكون العلاقة مثالية. البيانات الواقعية تحتوي عادةً على عوامل غير مقاسة وأخطاء واختلافات لا يستطيع النموذج تفسيرها بالكامل.
اختبار سلامة البيانات
لا تنتقل مباشرة إلى التدريب. افحص شكل الجدول وأنواع الأعمدة والقيم المفقودة والتكرار:
print(data.shape)print(data.dtypes)print(data.isna().sum())print("Duplicated rows:", data.duplicated().sum())print(data.describe())
تأكد من أن:
- كل صف يمثل طالبًا واحدًا.
- كل عمود يحمل معنى ثابتًا.
- النسب ضمن حدود منطقية.
- الدرجة المستهدفة بين صفر و100.
- لا توجد أعمدة نصية غير مجهزة.
- لا توجد معلومات تكشف الإجابة مسبقًا.
النموذج لا يصلح البيانات الرديئة، بل يتعلم منها أخطاءً جديدة.
تحديد الميزات والهدف
نستخدم الحرف X عادةً للميزات التي سيدخلها النموذج، والحرف y للهدف المطلوب توقعه.
X = data[ ["study_hours", "attendance", "assignments"]]y = data["final_score"]
لدينا هنا ثلاث ميزات وهدف واحد.
لا تضع final_score داخل X؛ لأن النموذج سيشاهد الإجابة التي نحاول توقعها، وستظهر نتيجة ممتازة لكنها مضللة تمامًا.
لماذا نقسّم البيانات؟
إذا درّبت النموذج واختبرته على الصفوف نفسها، فقد تحصل على نتيجة مرتفعة لأنه شاهد تلك البيانات أثناء التدريب.
نحتاج إلى مجموعتين:
- بيانات التدريب: يتعلم النموذج منها.
- بيانات الاختبار: نقيس عليها أداءه بعد التدريب.
سنخصص 25% من البيانات للاختبار:
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.25, random_state=42)print("Training:", X_train.shape)print("Testing:", X_test.shape)
النتيجة المتوقعة:
Training: (90, 3)Testing: (30, 3)
وجود random_state=42 يجعل التقسيم نفسه يتكرر في كل تشغيل، وهذا يساعدك على مقارنة التجارب بعد تغيير النموذج أو البيانات.
الرقم 42 لا يمنح النموذج دقة إضافية؛ هو مجرد قيمة ثابتة لضبط العشوائية.
لا تبدأ بالنموذج: أنشئ خط أساس
قبل تدريب نموذج حقيقي، اسأل: هل يستطيع التفوق على توقع بسيط جدًا؟
سنستخدم نموذجًا أساسيًا يتجاهل الميزات ويتوقع دائمًا متوسط درجات بيانات التدريب:
from sklearn.dummy import DummyRegressorbaseline = DummyRegressor(strategy="mean")baseline.fit(X_train, y_train)baseline_predictions = baseline.predict(X_test)
هذا النموذج ليس حلًا للمشكلة. فائدته أنه يمنحنا حدًا أدنى للمقارنة.
إذا لم يستطع النموذج الحقيقي التفوق عليه، فقد تكون الميزات ضعيفة، أو البيانات قليلة، أو توجد مشكلة في خطوات التدريب.
تدريب أول نموذج
سنستخدم الانحدار الخطي:
from sklearn.linear_model import LinearRegressionmodel = LinearRegression()model.fit(X_train, y_train)
الأمر fit يجعل النموذج يتعلم العلاقة بين الميزات والدرجة النهائية من بيانات التدريب.
بعد التدريب، نطلب منه توقع درجات مجموعة الاختبار:
predictions = model.predict(X_test)
حتى هذه اللحظة لا نعرف هل النموذج جيد. نجاح fit وpredict يعني أن الكود عمل، وليس أن التوقعات موثوقة.
قياس الأداء باستخدام MAE
متوسط الخطأ المطلق، أو MAE، يقيس متوسط المسافة بين التوقعات والقيم الحقيقية.
from sklearn.metrics import mean_absolute_errorbaseline_mae = mean_absolute_error( y_test, baseline_predictions)model_mae = mean_absolute_error( y_test, predictions)print("Baseline MAE:", round(baseline_mae, 2))print("Model MAE:", round(model_mae, 2))
في تجربتنا كانت النتيجة التقريبية:
Baseline MAE: 9.81Model MAE: 4.14
هذا يعني أن خط الأساس يخطئ بنحو 9.81 درجات في المتوسط، بينما يخطئ نموذج الانحدار الخطي بنحو 4.14 درجات.
المهم ليس الرقم وحده، بل مقارنته بخط الأساس وبحجم الخطأ المقبول في المشكلة الحقيقية.
قياس R² دون إساءة فهمه
يمكننا أيضًا حساب معامل R²:
from sklearn.metrics import r2_scorer2 = r2_score(y_test, predictions)print("R2:", round(r2, 2))
في التجربة ظهرت قيمة تقارب:
R2: 0.84
القيمة الأقرب إلى 1 تشير عادةً إلى أن النموذج يفسر جزءًا أكبر من الاختلاف في القيم. لكن لا تستخدم R² وحده للحكم على النموذج.
قد تكون القيمة سالبة إذا كان النموذج أسوأ من توقع متوسط الهدف، كما أن النتيجة المرتفعة لا تكشف وحدها عن التحيز أو تسرّب البيانات أو سوء اختيار مجموعة الاختبار.
| المقياس | ماذا يخبرك؟ | الاتجاه الأفضل |
|---|---|---|
| MAE | متوسط مقدار الخطأ بوحدة الهدف | الأقرب إلى صفر |
| R² | مدى تفسير النموذج لتباين الهدف | الأقرب إلى 1 غالبًا |
| مقارنة خط الأساس | هل تعلّم النموذج شيئًا مفيدًا؟ | النموذج أفضل بوضوح |
مقارنة القيم الحقيقية بالتوقعات
أنشئ جدولًا صغيرًا للمقارنة:
results = pd.DataFrame({ "actual": y_test, "predicted": predictions})results["absolute_error"] = ( results["actual"] - results["predicted"]).abs()print(results.head(10))
لا تنظر إلى المتوسط فقط. افحص الصفوف ذات الخطأ الأكبر:
print( results.sort_values( "absolute_error", ascending=False ).head())
هذه الصفوف قد تكشف:
- قيمًا شاذة.
- بيانات ناقصة.
- علاقة غير خطية.
- عاملًا مهمًا لم نضفه إلى الميزات.
- سجلات تنتمي إلى ظروف مختلفة عن بقية البيانات.
تصوير أداء النموذج
يمكن تصوير القيم الحقيقية مقابل التوقعات:
import matplotlib.pyplot as pltplt.figure(figsize=(7, 5))plt.scatter( y_test, predictions, alpha=0.75)minimum = min(y_test.min(), predictions.min())maximum = max(y_test.max(), predictions.max())plt.plot( [minimum, maximum], [minimum, maximum], linestyle="--", color="red")plt.xlabel("Actual score")plt.ylabel("Predicted score")plt.title("Actual vs Predicted Scores")plt.tight_layout()plt.show()
الخط المتقطع يمثل التوقع المثالي. كلما اقتربت النقاط منه، اقتربت التوقعات من القيم الحقيقية.
لكن الرسم لا يغني عن المقاييس، والمقاييس لا تغني عن فحص البيانات. نحتاج إلى الثلاثة معًا.
توقع نتيجة لسجل جديد
بعد تقييم النموذج، يمكن تجربة سجل جديد:
new_student = pd.DataFrame({ "study_hours": [5.0], "attendance": [85.0], "assignments": [8]})predicted_score = model.predict(new_student)[0]print(round(predicted_score, 1))
في تجربتنا ظهر توقع يقارب:
71.4
هذه النتيجة ليست حكمًا على طالب حقيقي. النموذج بُني على بيانات اصطناعية وعلاقات أنشأناها نحن، لذلك قيمته تعليمية فقط.
ما تسرّب البيانات؟
يحدث تسرّب البيانات عندما تصل إلى النموذج معلومة لم تكن متاحة فعلًا وقت إجراء التوقع، أو عندما تتضمن الميزات جزءًا من الإجابة.
أمثلة:
- استخدام الدرجة النهائية ضمن المدخلات لتوقع الدرجة النهائية.
- استخدام حالة النجاح لتوقع الدرجة.
- حساب متوسط يشمل بيانات الاختبار قبل تقسيم البيانات.
- تدريب النموذج على سجلات من المستقبل لا ينبغي أن يعرفها.
- وجود السجل نفسه في التدريب والاختبار.
- استخدام بيانات الطالب نفسه في المجموعتين بسبب تكرار السجلات.
التسرّب قد يعطيك نتيجة ممتازة ظاهريًا، لكنه ينهار عند استخدام النموذج على بيانات جديدة.
قاعدة دليل التقنية
كل نتيجة تبدو مثالية بصورة غير معتادة تستحق الشك قبل الاحتفال.
افحص الأعمدة وطريقة التقسيم وتوقيت جمع البيانات قبل تجربة نموذج أكثر تعقيدًا.
لماذا لا تكفي الدقة المرتفعة؟
قد يحقق النموذج رقمًا جيدًا ويظل غير مناسب للاستخدام، بسبب:
- صغر حجم البيانات.
- عدم تمثيل البيانات للفئة المستهدفة.
- وجود تحيز في السجلات.
- تغير الظروف بعد جمع البيانات.
- اعتماد النموذج على علاقة عارضة.
- اختلاف البيانات الجديدة عن بيانات التدريب.
إذا كانت البيانات من جامعة أو مقرر واحد، فلا تفترض أن النموذج سيعمل بالطريقة نفسها في جامعة أو تخصص أو سنة أخرى.
بطاقة مصغرة لتوثيق النموذج
لا تحفظ النموذج وحده؛ احفظ وصف التجربة أيضًا.
اكتب بعد كل تجربة:
- ما السؤال الذي يجيب عنه النموذج؟
- ما مصدر البيانات؟
- ما المتغير المستهدف؟
- ما الميزات المستخدمة؟
- كيف قُسمت البيانات؟
- ما خط الأساس؟
- ما MAE وR²؟
- ما أكبر قيود التجربة؟
- أين لا ينبغي استخدام النموذج؟
هذه البطاقة القصيرة تمنعك من نسيان سبب إنشاء النموذج وحدود نتائجه عند العودة إلى المشروع لاحقًا.
كيف تحسّن النموذج بطريقة صحيحة؟
إذا كانت النتيجة ضعيفة، لا تبدأ فورًا بتغيير الخوارزمية.
اتبع هذا الترتيب:
- افحص تعريف السؤال والهدف.
- راجع جودة البيانات والقيم المفقودة.
- ابحث عن تسرّب البيانات.
- قارن النموذج بخط الأساس.
- افحص الأخطاء الكبيرة يدويًا.
- أضف ميزات لها معنى حقيقي.
- اجمع بيانات أكثر تمثيلًا.
- جرّب نموذجًا آخر بعد معرفة سبب الحاجة إليه.
النموذج المعقد لا يعوّض السؤال الخاطئ أو البيانات غير المناسبة.
مشروع عملي مقترح
أنشئ مشروعًا بعنوان:
توقع مدة إنجاز المهام الدراسية
اجمع أو أنشئ بيانات تعليمية غير شخصية تحتوي على:
- عدد صفحات المهمة.
- مستوى الصعوبة من 1 إلى 5.
- عدد المصادر المطلوبة.
- الخبرة السابقة بالموضوع.
- مدة الإنجاز بالساعات.
ثم نفّذ الخطوات التالية:
- افحص البيانات ونظفها.
- صوّر علاقة كل ميزة بمدة الإنجاز.
- افصل الميزات عن الهدف.
- قسّم البيانات إلى تدريب واختبار.
- أنشئ
DummyRegressor. - درّب
LinearRegression. - قارن MAE بين النموذجين.
- اعرض أكبر خمسة أخطاء.
- اكتب بطاقة توثيق مختصرة.
- وضّح لماذا لا ينبغي استخدام التجربة للحكم على أداء أشخاص حقيقيين.
لا ترفع بيانات شخصية أو سجلات جامعية حقيقية إلى مستودع عام.
أخطاء شائعة في أول نموذج
- التدريب والاختبار على البيانات نفسها.
- اختيار الخوارزمية قبل تحديد السؤال.
- تجاهل خط الأساس.
- الاعتماد على R² وحده.
- استخدام بيانات قليلة ثم تعميم النتيجة.
- حذف القيم الشاذة لمجرد أنها أضعفت الأداء.
- تغيير البيانات حتى تظهر نتيجة جميلة.
- إدخال أعمدة تكشف الهدف.
- نسيان تثبيت
random_stateأثناء المقارنة. - التعامل مع التوقع على أنه حقيقة مؤكدة.
- استخدام بيانات حساسة دون تصريح واضح.
رأي دليل التقنية
أول نموذج ناجح ليس النموذج الذي يحقق أعلى رقم، بل النموذج الذي تستطيع شرح سؤاله وبياناته وخطئه وحدوده.
تعلم قياس الخطأ ومقارنة النموذج بخط أساس أهم من حفظ أسماء عشرات الخوارزميات. وإذا لم يتفوق النموذج على توقع متوسط بسيط، فهذه نتيجة مفيدة وليست فشلًا؛ لأنها تخبرك أن المشكلة تحتاج إلى مراجعة قبل إضافة مزيد من التعقيد.
ابدأ بنموذج مفهوم، ثم حسّن البيانات والتقييم، وبعدها انتقل إلى النماذج الأكثر تقدمًا.
قائمة فحص قبل اعتماد التجربة
- ☐ حددت السؤال والهدف بوضوح.
- ☐ تأكدت أن كل صف يمثل حالة مستقلة.
- ☐ فحصت القيم المفقودة والتكرار.
- ☐ فصلت الميزات عن الهدف.
- ☐ تحققت من عدم وجود تسرّب بيانات.
- ☐ قسمت البيانات إلى تدريب واختبار.
- ☐ ثبّت
random_stateللمقارنة العادلة. - ☐ أنشأت خط أساس بسيطًا.
- ☐ درّبت النموذج على بيانات التدريب فقط.
- ☐ حسبت MAE وقارنته بخط الأساس.
- ☐ فحصت R² دون الاعتماد عليه وحده.
- ☐ راجعت أكبر أخطاء النموذج.
- ☐ وثقت مصدر البيانات وقيود الاستخدام.
- ☐ لم أستخدم بيانات شخصية أو حساسة.
- ☐ لم أصف التوقع على أنه حقيقة مؤكدة.
أسئلة شائعة
هل أحتاج إلى رياضيات متقدمة لبناء أول نموذج؟
لا. يمكنك البدء بالمفاهيم الأساسية وتطبيق نموذج بسيط، لكن فهم الإحصاء والجبر الخطي سيصبح مهمًا كلما تقدمت في تعلم الآلة.
لماذا استخدمنا الانحدار الخطي؟
لأنه نموذج بسيط ومفهوم ومناسب لتعلم دورة العمل الأساسية: تجهيز البيانات وتقسيمها وتدريب النموذج وقياس الخطأ.
هل يجب دائمًا تخصيص 25% للاختبار؟
لا. النسبة تعتمد على حجم البيانات وطبيعة المشكلة. استخدمنا 25% لأنها مناسبة للتجربة التعليمية، وليست قاعدة ثابتة لكل مشروع.
هل R² بقيمة 0.84 يعني دقة 84%؟
لا. R² ليس نسبة دقة مباشرة، ولا ينبغي وصفه بأنه «دقة 84%». هو مقياس يوضح مقدارًا من التباين الذي يفسره النموذج وفق طريقة حساب محددة.
لماذا نحتاج إلى خط أساس؟
حتى نعرف هل تعلّم النموذج شيئًا يفوق توقعًا بسيطًا. من دون خط الأساس قد ننخدع بنتيجة تبدو جيدة لكنها لا تضيف قيمة حقيقية.
هل يمكن استخدام هذا النموذج لتقييم الطلاب؟
لا. البيانات اصطناعية والمثال تعليمي. تقييم الطلاب الحقيقي يتطلب بيانات موثوقة وضوابط للخصوصية والعدالة ومراجعة بشرية وسياسات واضحة.
ماذا أتعلم بعد هذا الدرس؟
الخطوة التالية هي فهم مشكلات التصنيف، ثم تجربة نموذج يتوقع فئة مثل «نعم أو لا»، مع تعلم مقاييس مناسبة مثل Precision وRecall ومصفوفة الالتباس.
المصادر الرسمية
توثيق تقسيم بيانات التدريب والاختبار في Scikit-learn:
توثيق LinearRegression:
توثيق DummyRegressor:
توثيق Mean Absolute Error:
توثيق R²:
الخلاصة
بناء أول نموذج تعلم آلي لا يعني اختيار خوارزمية متقدمة، بل تنفيذ دورة عمل يمكن فحصها وإعادة تجربتها.
بدأنا بتحديد هدف رقمي، ثم فحصنا البيانات وفصلنا الميزات عن الهدف وقسمنا السجلات إلى تدريب واختبار. بعد ذلك أنشأنا خط أساس، ودرّبنا نموذج انحدار خطي، وقارنّا الأداء باستخدام MAE وR².
الأهم من النتيجة هو قدرتك على اكتشاف التسرّب، وفهم الخطأ، وتوثيق القيود، وعدم تقديم التوقع على أنه حقيقة. بهذه العقلية تنتقل من تشغيل نموذج إلى إجراء تجربة تعلم آلي يمكن الوثوق بمنهجها.
ولمتابعة الدروس بالترتيب الصحيح، انتقل إلى خريطة تعلم الذكاء الاصطناعي لطالب الجامعة، أو تصفح قسم طلاب الحاسب للوصول إلى جميع المسارات والدروس العملية.


شاركنا رأيك