الوحدة 5 · ما بعد الأساسيات
الشبكات العصبية والتعلّم العميق
20 دقراءة 4 دتمرين Python
الدرس في لمحة
اشرح ما هي الطبقات ودوال التنشيط والـ epochs والـ backpropagation، ودرّب شبكة عصبية صغيرة باستخدام MLPClassifier، واحكم بأمانة متى يتفوّق التعلّم العميق على النماذج الأبسط.
- 1من عصبون واحد إلى شبكة
- 2كيف تتعلّم الشبكة
- 3شبكة على الأرقام المكتوبة بخط اليد
- 4حيث يفوز التعلّم العميق
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
يُستخدم “التعلّم العميق” مرادفًا للذكاء الاصطناعي، وهو يشغّل التعرّف على الصور وتحويل الكلام إلى نص والنماذج اللغوية الكبيرة التي يتناولها الدرس القادم. لكنه في العمق مبني من قطع تعرفها أصلًا: مجاميع موزونة كالانحدار الخطي، ودالة ضغط كالـ sigmoid، والـ gradient descent. يجمع هذا الدرس هذه القطع، ويدرّب شبكة صغيرة، ثم يضعها بجانب الانحدار اللوجستي ليرى ما تساويه فعلًا.
من عصبون واحد إلى شبكة
العصبون (neuron) يفعل ما يفعله الانحدار اللوجستي دون الضغط الأخير: يضرب كل مُدخل في وزن، ويجمع النتائج، ويضيف bias. ثم يطبّق دالة تنشيط (activation function). والأكثر شيوعًا هي ReLU، التي تُخرج المجموع إن كان موجبًا و0 فيما عدا ذلك. الطبقة (layer) مجموعة من العصبونات تقرأ كلها المدخلات نفسها، ولكلٍّ منها أوزانه. والشبكة تكدّس الطبقات: مخرجات إحداها تصبح مدخلات التالية.
دالة التنشيط هي الحيلة كلها. فبدونها تكون الطبقة دالة خطية، والدالة الخطية لدالة خطية تظل خطية: عشر طبقات لن تكون أقوى من انحدار لوجستي واحد. ومع ReLU بينها، تستطيع كل طبقة أن تثني وتجمع ما أنتجته سابقتها، فتستطيع الشبكة تمثيل منحنيات وتفاعلات لم تكتبها قط. وبعبارة أخرى، تتعلّم الطبقات المخفية features خاصة بها.
وفي التصنيف، تحتوي طبقة المخرجات على عصبون لكل فئة ودالة softmax، التي تحوّل المخرجات إلى احتمالات مجموعها 1، وهي القريب متعدد الفئات للـ sigmoid.
كيف تتعلّم الشبكة
يكرّر التدريب أربع خطوات:
- الـ forward pass (المرور الأمامي): مرّر دفعة من الأمثلة عبر الشبكة لتحصل على التنبؤات.
- دالة الخسارة: قِس مقدار خطئها، باستخدام الـ log loss في التصنيف.
- الـ backpropagation (الانتشار العكسي): احسب تدرّج الخسارة بالنسبة إلى كل وزن، رجوعًا من طبقة المخرجات بقاعدة السلسلة.
- خطوة المُحسِّن: ادفع كل وزن قليلًا عكس تدرّجه. و
adam، الخيار الافتراضي، هو gradient descent بمعدّل تعلّم متكيّف لكل وزن.
المرور الواحد على بيانات التدريب كلها epoch. ويستمر التدريب لعدد كبير من الـ epochs، وتراقب الخسارة تنخفض تمامًا كما انخفضت في الـ gradient descent الذي كتبته بيدك في القسم 2، لكن عبر آلاف الأوزان بدل وزنين.
شبكة على الأرقام المكتوبة بخط اليد
تحتوي بيانات الأرقام (digits) على 1,797 صورة لأرقام مكتوبة بخط اليد، كلٌّ منها 8×8 بكسل مسطّحة إلى 64 رقمًا. وMLPClassifier في scikit-learn (الـ multi-layer perceptron) شبكة صغيرة متصلة بالكامل.
from sklearn.datasets import load_digits
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_digits(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)
net = make_pipeline(StandardScaler(),
MLPClassifier(hidden_layer_sizes=(64,), max_iter=500, random_state=42))
net.fit(X_train, y_train)
mlp = net[-1]
print("weight matrices:", [w.shape for w in mlp.coefs_])
print("parameters:", sum(w.size for w in mlp.coefs_) + sum(b.size for b in mlp.intercepts_))
print("epochs run:", mlp.n_iter_, "| loss first, 10th, last:",
[round(float(mlp.loss_curve_[i]), 3) for i in (0, 9, -1)])
print("network test accuracy: ", round(net.score(X_test, y_test), 3))
linear = make_pipeline(StandardScaler(), LogisticRegression(max_iter=2000)).fit(X_train, y_train)
print("logistic test accuracy:", round(linear.score(X_test, y_test), 3))طبقة مخفية واحدة من 64 عصبونًا تعني مصفوفتي أوزان: 64×64 من البكسلات إلى الوحدات المخفية و64×10 من الوحدات المخفية إلى الأرقام، أي 4,810 معاملًا مع الـ biases. تنخفض الخسارة من 2.31 (تخمين متساوٍ على عشر فئات) إلى ما دون 0.01، ويتوقف التدريب من تلقاء نفسه بعد 164 epoch لأن التحسّن تعثّر. الدقة على الاختبار: 98%.
والانحدار اللوجستي؟ نحو 98% أيضًا. مع صور 8×8 وبضع مئات من الأمثلة لكل فئة، يكفي حدّ مستقيم أصلًا. ولا تجد القوة الإضافية للشبكة شيئًا يُذكر تعمل عليه. جرّبها على بيانات الانقطاع وستكون النتيجة نفسها، أسوأ قليلًا: نحو 0.79 من الـ ROC AUC مقابل 0.81 للانحدار اللوجستي.
حيث يفوز التعلّم العميق
الشبكات التي تقف وراء الذكاء الاصطناعي الحديث تختلف عن MLPClassifier في الحجم وفي البنية. فـ الشبكات الالتفافية (convolutional networks) تعيد استخدام المرشّحات الصغيرة نفسها عبر الصورة، فتتعلّم الحواف، ثم الأشكال، ثم الأجسام. والـ Transformers، التي تقف وراء النماذج اللغوية الحالية، تتيح لكل كلمة في النص أن تزن كل كلمة أخرى. وكلاهما يُدرَّب على ملايين أو مليارات الأمثلة، على وحدات GPU، بمكتبات مثل PyTorch أو Keras أو JAX، لا scikit-learn.
وما تشترك فيه مع شبكتك ذات الـ 4,810 وزنًا هو كل ما هو مفاهيمي: الطبقات، ودوال التنشيط، ودالة الخسارة، والـ backpropagation، والـ epochs، والـ overfitting، وبيانات التحقق. وحين تقول ورقة بحثية في التعلّم العميق “درّبنا لـ 20 epoch مع early stopping على خسارة التحقق”، فأنت تعرف الآن معنى كل كلمة.
النماذج المدرَّبة مسبقًا هي الجسر بين العالمين، وأبرزها النماذج اللغوية الكبيرة. يشرح الدرس القادم ما تفعله، وكيف تحوّل الـ embeddings النص إلى نوع المتّجهات التي ظللت تغذّي بها النماذج طوال الدورة، وأين تقع بجانب نموذج الانقطاع.
أهم النقاط
- يحسب العصبون مجموعًا موزونًا لمدخلاته مضافًا إليه bias، ثم يمرّره عبر دالة تنشيط مثل ReLU؛ والطبقة عصبونات كثيرة متجاورة.
- دون دوال تنشيط غير خطية، تنهار أي كومة من الطبقات إلى نموذج خطي واحد.
- يكرّر التدريب الـ forward pass، ثم دالة الخسارة، ثم الـ backpropagation (تدرّجات لكل وزن)، ثم خطوة المُحسِّن؛ والمرور الواحد على بيانات التدريب هو epoch.
MLPClassifierشبكة صغيرة متصلة بالكامل لمسائل بحجم البيانات الجدولية؛ أما التعلّم العميق الحقيقي فيستخدم PyTorch أو Keras أو JAX على وحدات GPU.- تتألّق الشبكات العصبية مع كميات كبيرة من البيانات الخام غير المهيكلة مثل الصور والصوت والنصوص؛ أما في الجداول الصغيرة فتجاريها النماذج الخطية والأشجار المعزّزة أو تتفوّق عليها عادةً.