{"id":"l-ml-5-2","courseId":"ml-crash-course","lang":"ar","kind":"lesson","summary":"اشرح ما هي الطبقات ودوال التنشيط والـ epochs والـ backpropagation، ودرّب شبكة عصبية صغيرة باستخدام MLPClassifier، واحكم بأمانة متى يتفوّق التعلّم العميق على النماذج الأبسط.","html":"<p>يُستخدم “التعلّم العميق” مرادفًا للذكاء الاصطناعي، وهو يشغّل التعرّف على الصور وتحويل الكلام إلى نص والنماذج اللغوية الكبيرة التي يتناولها الدرس القادم. لكنه في العمق مبني من قطع تعرفها أصلًا: مجاميع موزونة كالانحدار الخطي، ودالة ضغط كالـ sigmoid، والـ gradient descent. يجمع هذا الدرس هذه القطع، ويدرّب شبكة صغيرة، ثم يضعها بجانب الانحدار اللوجستي ليرى ما تساويه فعلًا.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">من عصبون واحد إلى شبكة</h2>\n<p><strong>العصبون (neuron)</strong> يفعل ما يفعله الانحدار اللوجستي دون الضغط الأخير: يضرب كل مُدخل في وزن، ويجمع النتائج، ويضيف bias. ثم يطبّق <strong>دالة تنشيط (activation function)</strong>. والأكثر شيوعًا هي <strong>ReLU</strong>، التي تُخرج المجموع إن كان موجبًا و0 فيما عدا ذلك. <strong>الطبقة (layer)</strong> مجموعة من العصبونات تقرأ كلها المدخلات نفسها، ولكلٍّ منها أوزانه. و<strong>الشبكة</strong> تكدّس الطبقات: مخرجات إحداها تصبح مدخلات التالية.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 640 300\" role=\"img\" aria-labelledby=\"l-ml-5-2-t1\"><defs><marker id=\"arrow-l-ml-5-2-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-ml-5-2-t1\">ثلاث عقد مدخلات تتصل بكل عقدة من أربع عقد مخفية، وهذه تتصل بكل عقدة من ثلاث عقد مخرجات. تطبّق العقد المخفية ReLU؛ وتطبّق المخرجات softmax لتعطي احتمالات الفئات.</title>\n  <text class=\"d-label-strong\" x=\"90\" y=\"24\" text-anchor=\"middle\">المدخلات</text>\n  <text class=\"d-label-strong\" x=\"320\" y=\"24\" text-anchor=\"middle\">طبقة مخفية (ReLU)</text>\n  <text class=\"d-label-strong\" x=\"550\" y=\"24\" text-anchor=\"middle\">المخرجات (softmax)</text>\n  <g class=\"d-line\">\n    <path d=\"M110 90 L300 60 M110 90 L300 125 M110 90 L300 190 M110 90 L300 255\"/>\n    <path d=\"M110 155 L300 60 M110 155 L300 125 M110 155 L300 190 M110 155 L300 255\"/>\n    <path d=\"M110 220 L300 60 M110 220 L300 125 M110 220 L300 190 M110 220 L300 255\"/>\n    <path d=\"M340 60 L530 90 M340 60 L530 155 M340 60 L530 220\"/>\n    <path d=\"M340 125 L530 90 M340 125 L530 155 M340 125 L530 220\"/>\n    <path d=\"M340 190 L530 90 M340 190 L530 155 M340 190 L530 220\"/>\n    <path d=\"M340 255 L530 90 M340 255 L530 155 M340 255 L530 220\"/>\n  </g>\n  <circle class=\"d-box\" cx=\"90\" cy=\"90\" r=\"20\"/><circle class=\"d-box\" cx=\"90\" cy=\"155\" r=\"20\"/><circle class=\"d-box\" cx=\"90\" cy=\"220\" r=\"20\"/>\n  <circle class=\"d-box-primary\" cx=\"320\" cy=\"60\" r=\"20\"/><circle class=\"d-box-primary\" cx=\"320\" cy=\"125\" r=\"20\"/><circle class=\"d-box-primary\" cx=\"320\" cy=\"190\" r=\"20\"/><circle class=\"d-box-primary\" cx=\"320\" cy=\"255\" r=\"20\"/>\n  <circle class=\"d-box-accent\" cx=\"550\" cy=\"90\" r=\"20\"/><circle class=\"d-box-accent\" cx=\"550\" cy=\"155\" r=\"20\"/><circle class=\"d-box-accent\" cx=\"550\" cy=\"220\" r=\"20\"/>\n  <text class=\"d-label-muted\" x=\"430\" y=\"290\" text-anchor=\"middle\">كل خط وزن واحد</text>\n</svg><figcaption>شبكة صغيرة متصلة بالكامل</figcaption></figure>\n<p>دالة التنشيط هي الحيلة كلها. فبدونها تكون الطبقة دالة خطية، والدالة الخطية لدالة خطية تظل خطية: عشر طبقات لن تكون أقوى من انحدار لوجستي واحد. ومع ReLU بينها، تستطيع كل طبقة أن تثني وتجمع ما أنتجته سابقتها، فتستطيع الشبكة تمثيل منحنيات وتفاعلات لم تكتبها قط. وبعبارة أخرى، <strong>تتعلّم الطبقات المخفية features خاصة بها</strong>.</p>\n<p>وفي التصنيف، تحتوي طبقة المخرجات على عصبون لكل فئة ودالة <strong>softmax</strong>، التي تحوّل المخرجات إلى احتمالات مجموعها 1، وهي القريب متعدد الفئات للـ sigmoid.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">كيف تتعلّم الشبكة</h2>\n<p>يكرّر التدريب أربع خطوات:</p>\n<ol>\n<li><strong>الـ forward pass (المرور الأمامي)</strong>: مرّر دفعة من الأمثلة عبر الشبكة لتحصل على التنبؤات.</li>\n<li><strong>دالة الخسارة</strong>: قِس مقدار خطئها، باستخدام الـ log loss في التصنيف.</li>\n<li><strong>الـ backpropagation (الانتشار العكسي)</strong>: احسب تدرّج الخسارة بالنسبة إلى كل وزن، رجوعًا من طبقة المخرجات بقاعدة السلسلة.</li>\n<li><strong>خطوة المُحسِّن</strong>: ادفع كل وزن قليلًا عكس تدرّجه. و<code dir=\"ltr\">adam</code>، الخيار الافتراضي، هو gradient descent بمعدّل تعلّم متكيّف لكل وزن.</li>\n</ol>\n<p>المرور الواحد على بيانات التدريب كلها <strong>epoch</strong>. ويستمر التدريب لعدد كبير من الـ epochs، وتراقب الخسارة تنخفض تمامًا كما انخفضت في الـ gradient descent الذي كتبته بيدك في القسم 2، لكن عبر آلاف الأوزان بدل وزنين.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">شبكة على الأرقام المكتوبة بخط اليد</h2>\n<p>تحتوي بيانات الأرقام (digits) على 1,797 صورة لأرقام مكتوبة بخط اليد، كلٌّ منها 8×8 بكسل مسطّحة إلى 64 رقمًا. و<code dir=\"ltr\">MLPClassifier</code> في scikit-learn (الـ multi-layer perceptron) شبكة صغيرة متصلة بالكامل.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"0\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.datasets </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> load_digits</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.linear_model </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> LogisticRegression</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.model_selection </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> train_test_split</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.neural_network </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> MLPClassifier</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.pipeline </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> make_pipeline</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.preprocessing </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> StandardScaler</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">X, y </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> load_digits(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">return_X_y</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">True</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">X_train, X_test, y_train, y_test </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> train_test_split(X, y, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">test_size</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.25</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">random_state</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">42</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">stratify</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">y)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">net </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> make_pipeline(StandardScaler(),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">                    MLPClassifier(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">hidden_layer_sizes</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">64</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">max_iter</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">500</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">random_state</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">42</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">net.fit(X_train, y_train)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">mlp </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> net[</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"weight matrices:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, [w.shape </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> w </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> mlp.coefs_])</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"parameters:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">sum</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(w.size </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> w </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> mlp.coefs_) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> sum</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(b.size </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> b </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> mlp.intercepts_))</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"epochs run:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, mlp.n_iter_, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"| loss first, 10th, last:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">float</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(mlp.loss_curve_[i]), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> i </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">9</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)])</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"network test accuracy: \"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(net.score(X_test, y_test), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">linear </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> make_pipeline(StandardScaler(), LogisticRegression(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">max_iter</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2000</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)).fit(X_train, y_train)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"logistic test accuracy:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(linear.score(X_test, y_test), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>طبقة مخفية واحدة من 64 عصبونًا تعني مصفوفتي أوزان: 64×64 من البكسلات إلى الوحدات المخفية و64×10 من الوحدات المخفية إلى الأرقام، أي 4,810 معاملًا مع الـ biases. تنخفض الخسارة من 2.31 (تخمين متساوٍ على عشر فئات) إلى ما دون 0.01، ويتوقف التدريب من تلقاء نفسه بعد 164 epoch لأن التحسّن تعثّر. الدقة على الاختبار: 98%.</p>\n<p>والانحدار اللوجستي؟ نحو 98% أيضًا. مع صور 8×8 وبضع مئات من الأمثلة لكل فئة، يكفي حدّ مستقيم أصلًا. ولا تجد القوة الإضافية للشبكة شيئًا يُذكر تعمل عليه. جرّبها على بيانات الانقطاع وستكون النتيجة نفسها، أسوأ قليلًا: نحو 0.79 من الـ ROC AUC مقابل 0.81 للانحدار اللوجستي.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>توقّع أن تتفوّق الشبكة العصبية على كل شيء</span></p>\n<p>في كثير من مجموعات البيانات الجدولية يكون للشبكات معاملات أكثر من الصفوف، وتحتاج إلى مدخلات موحّدة المقاييس، وتتأثر بالإعدادات (أحجام الطبقات، ومعدّل التعلّم، و<code dir=\"ltr\">alpha</code> للـ regularization من نوع L2، وعدد الـ epochs). وفي الجداول الصغيرة أو المتوسطة ذات الـ features المصمَّمة، تكون النماذج الخطية المنظَّمة والـ gradient boosting عادةً بالجودة نفسها، وأسهل بكثير في التشغيل والشرح. والجأ إلى التعلّم العميق حين تكون البيانات كبيرة وخامًا.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">حيث يفوز التعلّم العميق</h2>\n<p>الشبكات التي تقف وراء الذكاء الاصطناعي الحديث تختلف عن <code dir=\"ltr\">MLPClassifier</code> في الحجم وفي البنية. فـ <strong>الشبكات الالتفافية (convolutional networks)</strong> تعيد استخدام المرشّحات الصغيرة نفسها عبر الصورة، فتتعلّم الحواف، ثم الأشكال، ثم الأجسام. و<strong>الـ Transformers</strong>، التي تقف وراء النماذج اللغوية الحالية، تتيح لكل كلمة في النص أن تزن كل كلمة أخرى. وكلاهما يُدرَّب على ملايين أو مليارات الأمثلة، على وحدات GPU، بمكتبات مثل PyTorch أو Keras أو JAX، لا scikit-learn.</p>\n<p>وما تشترك فيه مع شبكتك ذات الـ 4,810 وزنًا هو كل ما هو مفاهيمي: الطبقات، ودوال التنشيط، ودالة الخسارة، والـ backpropagation، والـ epochs، والـ overfitting، وبيانات التحقق. وحين تقول ورقة بحثية في التعلّم العميق “درّبنا لـ 20 epoch مع early stopping على خسارة التحقق”، فأنت تعرف الآن معنى كل كلمة.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>متى تبدّل الأدوات</span></p>\n<p>إذا كانت مدخلاتك بكسلات أو عيّنات صوتية أو نصوصًا خامًا، أو كان لديك مئات الآلاف من الأمثلة ذات الـ labels، فقد حان وقت إطار تعلّم عميق، أو على نحو متزايد، نموذج مُدرَّب مسبقًا تكيّفه. أما إذا كانت مدخلاتك جدولًا من حقائق العملاء، فابقَ مع scikit-learn.</p>\n</aside>\n<p>النماذج المدرَّبة مسبقًا هي الجسر بين العالمين، وأبرزها النماذج اللغوية الكبيرة. يشرح الدرس القادم ما تفعله، وكيف تحوّل الـ embeddings النص إلى نوع المتّجهات التي ظللت تغذّي بها النماذج طوال الدورة، وأين تقع بجانب نموذج الانقطاع.</p>\n","toc":[{"id":"sec-1","text":"من عصبون واحد إلى شبكة","level":2},{"id":"sec-2","text":"كيف تتعلّم الشبكة","level":2},{"id":"sec-3","text":"شبكة على الأرقام المكتوبة بخط اليد","level":2},{"id":"sec-4","text":"حيث يفوز التعلّم العميق","level":2}],"takeaways":["يحسب العصبون مجموعًا موزونًا لمدخلاته مضافًا إليه bias، ثم يمرّره عبر دالة تنشيط مثل ReLU؛ والطبقة عصبونات كثيرة متجاورة.","دون دوال تنشيط غير خطية، تنهار أي كومة من الطبقات إلى نموذج خطي واحد.","يكرّر التدريب الـ forward pass، ثم دالة الخسارة، ثم الـ backpropagation (تدرّجات لكل وزن)، ثم خطوة المُحسِّن؛ والمرور الواحد على بيانات التدريب هو epoch.","<code dir=\"ltr\">MLPClassifier</code> شبكة صغيرة متصلة بالكامل لمسائل بحجم البيانات الجدولية؛ أما التعلّم العميق الحقيقي فيستخدم PyTorch أو Keras أو JAX على وحدات GPU.","تتألّق الشبكات العصبية مع كميات كبيرة من البيانات الخام غير المهيكلة مثل الصور والصوت والنصوص؛ أما في الجداول الصغيرة فتجاريها النماذج الخطية والأشجار المعزّزة أو تتفوّق عليها عادةً."],"further":[{"title":"Neural network models (supervised)","url":"https://scikit-learn.org/stable/modules/neural_networks_supervised.html"},{"title":"MLPClassifier","url":"https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html"}],"quiz":[{"q":"<p>لماذا تحتاج الشبكات العصبية إلى دوال تنشيط غير خطية بين الطبقات؟</p>","options":[{"text":"لأنها تجعل التدريب أسرع على وحدات GPU.","why":"السرعة ليست السبب؛ السبب هو ما تستطيع الشبكة تمثيله أصلًا."},{"text":"لأنها تُبقي المخرجات بين 0 و1.","why":"هذا لا يصح إلا على بعض دوال التنشيط (sigmoid)؛ فمخرجات ReLU قد تكون أي رقم غير سالب."},{"text":"لأنها تمنع الأوزان من أن تكبر أكثر من اللازم.","why":"هذه مهمة الـ regularization (<code dir=\"ltr\">alpha</code> في <code dir=\"ltr\">MLPClassifier</code>)، لا مهمة دالة التنشيط."},{"text":"لأنه بدونها تتضاعف عدة طبقات خطية لتصبح دالة خطية واحدة، فلا يضيف العمق شيئًا.","why":"صحيح. اللاخطية هي ما يتيح للطبقات المكدّسة نمذجة المنحنيات والتفاعلات."}],"answer":3},{"q":"<p>تتدرّب شبكة على 1,347 صورة مع <code dir=\"ltr\">max_iter=500</code>، ويُبلغ <code dir=\"ltr\">n_iter_</code> عن 164. ماذا حدث؟</p>","options":[{"text":"توقّف التدريب بعد 164 epoch لأن الخسارة توقفت عن التحسّن بأكثر من حدّ التسامح.","why":"صحيح. مع المُحسِّنين <code dir=\"ltr\">adam</code> و<code dir=\"ltr\">sgd</code>، يحدّد <code dir=\"ltr\">max_iter</code> سقف عدد الـ epochs، ويتوقف التدريب مبكرًا بمجرد أن يتعثّر التقدّم."},{"text":"لم ترَ إلا 164 صورة من أصل 1,347.","why":"الـ epoch مرور كامل على كل صفوف التدريب؛ وكل epoch من الـ 164 استخدم كل الصور."},{"text":"انهارت عند الـ epoch رقم 164 واحتفظت بآخر أوزان سليمة.","why":"التوقف المبكر تقارب طبيعي، لا انهيار؛ والفشل في التقارب كان سيرفع <code dir=\"ltr\">ConvergenceWarning</code> عند 500."}],"answer":0},{"q":"<p>على جدول الانقطاع، تبلغ شبكة MLP صغيرة ROC AUC بالتحقق المتقاطع قدره 0.79 بينما يبلغ الانحدار اللوجستي 0.81. ما القراءة الأكثر معقولية؟</p>","options":[{"text":"تحتاج الـ MLP إلى طبقات أكثر؛ فالتعلّم العميق يفوز دائمًا بعمق كافٍ.","why":"مع 298 صفًا وثمانية features، القدرة الإضافية تضيف تباينًا في الغالب. والعمق ليس مجانيًا."},{"text":"في جدول صغير من features مفيدة، يصعب التفوّق على نموذج بسيط؛ فالشبكة تضيف تعقيدًا دون إشارة تستفيد منها.","why":"صحيح. تستحق الشبكات مكانها حين توجد بيانات كثيرة ومدخلات خام يصعب تصميم features لها يدويًا."},{"text":"لا يمكن استخدام الشبكات العصبية للتصنيف الثنائي.","why":"إنها تتعامل مع التصنيف الثنائي بشكل روتيني؛ والمسألة تتعلّق بحجم البيانات ونوعها."}],"answer":1}],"exercise":{"kind":"python","starter":"from sklearn.datasets import load_digits\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.neural_network import MLPClassifier\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import StandardScaler\n\nX, y = load_digits(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)\n\n# 1. Pipeline: StandardScaler, then an MLPClassifier with ONE hidden layer of 32 neurons,\n#    max_iter=500, random_state=42. Fit it on the training data.\nnet = MLPClassifier(hidden_layer_sizes=(32, 32), max_iter=500, random_state=42)\n\n# 2. Facts about the trained network\nn_params = None      # total number of weights + biases\nepochs = None        # epochs actually run\ntest_acc = None      # test accuracy\n","solution":"from sklearn.datasets import load_digits\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.neural_network import MLPClassifier\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import StandardScaler\n\nX, y = load_digits(return_X_y=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42, stratify=y)\n\nnet = make_pipeline(StandardScaler(),\n                    MLPClassifier(hidden_layer_sizes=(32,), max_iter=500, random_state=42))\nnet.fit(X_train, y_train)\n\nmlp = net[-1]\nn_params = sum(w.size for w in mlp.coefs_) + sum(b.size for b in mlp.intercepts_)\nepochs = mlp.n_iter_\ntest_acc = net.score(X_test, y_test)\nprint(n_params, epochs, round(test_acc, 3))\n","checks":[{"id":"pipeline","test":"hasattr(net, 'steps') and type(net[0]).__name__ == 'StandardScaler' and type(net[-1]).__name__ == 'MLPClassifier'"},{"id":"architecture","test":"tuple(net[-1].hidden_layer_sizes) == (32,) and [w.shape for w in net[-1].coefs_] == [(64, 32), (32, 10)]"},{"id":"params","test":"n_params is not None and int(n_params) == 64 * 32 + 32 + 32 * 10 + 10"},{"id":"trained","test":"epochs is not None and int(epochs) == net[-1].n_iter_ and net[-1].loss_curve_[-1] < net[-1].loss_curve_[0]"},{"id":"accuracy","test":"test_acc is not None and 0.95 < float(test_acc) <= 1.0"}],"title":"درّب شبكة صغيرة وافحصها","prompt":"<ol>\n<li><code dir=\"ltr\">net</code>: pipeline يتكوّن من <code dir=\"ltr\">StandardScaler</code> ثم <code dir=\"ltr\">MLPClassifier</code> بطبقة مخفية <strong>واحدة</strong> من 32 عصبونًا (<code dir=\"ltr\">max_iter=500, random_state=42</code>)، مدرَّبًا على بيانات تدريب الأرقام.</li>\n<li>من الشبكة المدرَّبة، اضبط <code dir=\"ltr\">n_params</code> (كل الأوزان مع كل الـ biases)، و<code dir=\"ltr\">epochs</code> (عدد الـ epochs التي جرى فيها التدريب فعلًا)، و<code dir=\"ltr\">test_acc</code> (الدقة على بيانات الاختبار).</li>\n</ol>\n","hints":["طبقة مخفية واحدة من 32 تُكتب <code dir=\"ltr\">hidden_layer_sizes=(32,)</code>؛ والفاصلة في الآخر تجعلها tuple.","<code dir=\"ltr\">net[-1]</code> هو الـ <code dir=\"ltr\">MLPClassifier</code> المدرَّب. و<code dir=\"ltr\">coefs_</code> و<code dir=\"ltr\">intercepts_</code> فيه قوائم من مصفوفات NumPy؛ اجمع قيم <code dir=\"ltr\">.size</code> لها.","يحمل <code dir=\"ltr\">n_iter_</code> عدد الـ epochs التي جرى فيها التدريب."],"explanation":"<p>للشبكة مصفوفة أوزان 64×32 إلى الطبقة المخفية ومصفوفة 32×10 إلى الأرقام العشرة، إضافة إلى 32 و10 من الـ biases: أي 2,410 معاملًا. يتوقف التدريب من تلقاء نفسه بمجرد أن تتوقف الخسارة عن التحسّن، قبل 500 epoch بكثير، وتستقر الدقة على الاختبار حول 97–98%، أي بمستوى الانحدار اللوجستي على هذه الصور الصغيرة. ودون الـ scaler، تجعل قيم البكسلات من 0 إلى 16 التدريب أبطأ وأقل استقرارًا.</p>\n","checkLabels":{"pipeline":"يوحّد net المقاييس، ثم يشغّل MLPClassifier","architecture":"طبقة مخفية واحدة من 32 عصبونًا","params":"يعدّ n_params كل وزن وكل bias","trained":"تطابق epochs عدد الـ epochs المنفَّذة، وقد انخفضت الخسارة","accuracy":"test_acc أعلى من 0.95"}},"words":734,"readMinutes":4}