{"id":"l-ml-2-3","courseId":"ml-crash-course","lang":"ar","kind":"lesson","summary":"أضف polynomial features لتجعل النموذج الخطي ينحني، وراقب نتيجة التدريب ترتفع بينما تنهار نتيجة الاختبار، واستخدم جزء تحقق (validation) لتختار تعقيد النموذج بأمانة.","html":"<p>الخط المستقيم افتراض قوي. فإذا كان تقدّم المرض يرتفع أسرع عند مؤشر كتلة جسم مرتفع منه عند مؤشر منخفض، فلا خط مستقيم يستطيع التقاط ذلك، مهما طال تشغيل الـ gradient descent. والحل يبدو بريئًا: دع النموذج ينحني. يبيّن هذا الدرس كيف، وكيف يتحوّل الانحناء سريعًا إلى حفظ.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">جعل النموذج الخطي ينحني</h2>\n<p>الحيلة أن تُبقي الانحدار الخطي وتغيّر المدخلات. فإذا أضفت عمودًا <code dir=\"ltr\">bmi²</code>، فإن نموذجًا “خطيًا” في <code dir=\"ltr\">bmi</code> و<code dir=\"ltr\">bmi²</code> يرسم قطعًا مكافئًا في <code dir=\"ltr\">bmi</code>. ويولّد <code dir=\"ltr\">PolynomialFeatures</code> هذه الأعمدة: كل قوة حتى الدرجة المختارة، إضافة إلى كل حاصل ضرب بين الـ features (أي <strong>التفاعلات (interactions)</strong>).</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_diabetes</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\"> PolynomialFeatures</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_diabetes(</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 style=\"color:#953800;--shiki-dark:#FFA657\">as_frame</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\">poly </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> PolynomialFeatures(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">include_bias</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).fit(X[[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"bmi\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"bp\"</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\">(poly.get_feature_names_out())</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> degree </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\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    n </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> PolynomialFeatures(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">degree, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">include_bias</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).fit(X).n_output_features_</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:#CF222E;--shiki-dark:#FF7B72\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"degree </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">: </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">n</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> columns from 10 features\"</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>يتحوّل الـ features الاثنان إلى خمسة أعمدة عند الدرجة 2. وتتحوّل الـ features العشرة إلى 65 عمودًا عند الدرجة 2 و285 عند الدرجة 3. يحذف <code dir=\"ltr\">include_bias=False</code> العمود الثابت، لأن <code dir=\"ltr\">LinearRegression</code> يحسب الـ intercept بنفسه.</p>\n<p>لتسلسل التوسيع والانحدار، استخدم <code dir=\"ltr\">make_pipeline</code>. فهي تنشئ estimator واحدًا ينفّذ كل خطوة بالترتيب؛ يدرّب <code dir=\"ltr\">fit</code> كل خطوة على بيانات التدريب، ويمرّر <code dir=\"ltr\">predict</code> البيانات الجديدة عبر الخطوات نفسها. ستبني pipelines أغنى في القسم 4.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">نتيجة التدريب تواصل الصعود</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"1\"><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=\"1\" 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_diabetes</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\"> LinearRegression</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.metrics </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> mean_absolute_error</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.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\"> PolynomialFeatures</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_diabetes(</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 style=\"color:#953800;--shiki-dark:#FFA657\">as_frame</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>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> degree </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\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    model </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> make_pipeline(PolynomialFeatures(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">degree, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">include_bias</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">                          LinearRegression()).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:#CF222E;--shiki-dark:#FF7B72\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"degree </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">: train R2 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">model.score(X_train, y_train)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:6.3f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">  \"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">          f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"test R2 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">model.score(X_test, y_test)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:7.3f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">  \"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">          f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"test MAE </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">mean_absolute_error(y_test, model.predict(X_test))</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:6.1f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>اقرأ الصفوف الثلاثة على مهل. الدرجة 2 تحسّن نتيجة التدريب وتسوّئ نتيجة الاختبار. والدرجة 3 كارثة متنكّرة في ثوب نجاح: R² بقيمة 0.90 في التدريب، وR² بقيمة -8.5 في الاختبار، وخطأ اختبار معتاد مقداره 151 نقطة، وهذا أسوأ من التنبؤ بالمتوسط للجميع. مع 285 عمودًا و331 مريض تدريب فقط، يكاد يملك النموذج من المقابض ما يكفي ليمرّ عبر كل نقطة تدريب. لقد تعلّم الضجيج.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">الـ Underfitting والـ Overfitting</h2>\n<p>هذه الصفوف الثلاثة تقابل صورة ستراها في كل دورة لتعلّم الآلة، لأنها المفاضلة المركزية في هذا المجال.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 220\" role=\"img\" aria-labelledby=\"l-ml-2-3-t1\"><defs><marker id=\"arrow-l-ml-2-3-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-2-3-t1\">ثلاث لوحات لنقاط منحنية التوزيع نفسها. اليسرى: خط مستقيم يفوّت المنحنى (underfit). الوسطى: منحنى لطيف يتبع الاتجاه (توافق جيد). اليمنى: خط متعرّج يمرّ بكل نقطة (overfit).</title>\n  <rect class=\"d-box\" x=\"10\" y=\"10\" width=\"220\" height=\"170\" rx=\"10\"/>\n  <rect class=\"d-box-success\" x=\"240\" y=\"10\" width=\"220\" height=\"170\" rx=\"10\"/>\n  <rect class=\"d-box\" x=\"470\" y=\"10\" width=\"220\" height=\"170\" rx=\"10\"/>\n  <circle class=\"d-dot\" cx=\"40\" cy=\"150\" r=\"4\"/><circle class=\"d-dot\" cx=\"70\" cy=\"118\" r=\"4\"/><circle class=\"d-dot\" cx=\"100\" cy=\"112\" r=\"4\"/><circle class=\"d-dot\" cx=\"130\" cy=\"88\" r=\"4\"/><circle class=\"d-dot\" cx=\"160\" cy=\"86\" r=\"4\"/><circle class=\"d-dot\" cx=\"190\" cy=\"60\" r=\"4\"/>\n  <path class=\"d-arrow\" d=\"M30 140 L210 70\"/>\n  <circle class=\"d-dot\" cx=\"270\" cy=\"150\" r=\"4\"/><circle class=\"d-dot\" cx=\"300\" cy=\"118\" r=\"4\"/><circle class=\"d-dot\" cx=\"330\" cy=\"112\" r=\"4\"/><circle class=\"d-dot\" cx=\"360\" cy=\"88\" r=\"4\"/><circle class=\"d-dot\" cx=\"390\" cy=\"86\" r=\"4\"/><circle class=\"d-dot\" cx=\"420\" cy=\"60\" r=\"4\"/>\n  <path class=\"d-arrow\" d=\"M260 160 Q330 90 440 50\" fill=\"none\"/>\n  <circle class=\"d-dot\" cx=\"500\" cy=\"150\" r=\"4\"/><circle class=\"d-dot\" cx=\"530\" cy=\"118\" r=\"4\"/><circle class=\"d-dot\" cx=\"560\" cy=\"112\" r=\"4\"/><circle class=\"d-dot\" cx=\"590\" cy=\"88\" r=\"4\"/><circle class=\"d-dot\" cx=\"620\" cy=\"86\" r=\"4\"/><circle class=\"d-dot\" cx=\"650\" cy=\"60\" r=\"4\"/>\n  <path class=\"d-arrow\" d=\"M490 165 C495 140 500 150 500 150 C515 100 525 125 530 118 C545 95 550 125 560 112 C575 60 580 95 590 88 C605 110 610 80 620 86 C635 95 640 40 650 60 C660 75 665 40 670 30\" fill=\"none\"/>\n  <text class=\"d-label-strong\" x=\"120\" y=\"205\" text-anchor=\"middle\">Underfit</text>\n  <text class=\"d-label-strong\" x=\"350\" y=\"205\" text-anchor=\"middle\">توافق جيد</text>\n  <text class=\"d-label-strong\" x=\"580\" y=\"205\" text-anchor=\"middle\">Overfit</text>\n</svg><figcaption>الـ underfitting، والتوافق الجيد، والـ overfitting</figcaption></figure>\n<ul>\n<li><strong>الـ Underfitting</strong> (انحياز مرتفع، high bias): النموذج أبسط من النمط. نتيجتا التدريب والاختبار ضعيفتان ومتقاربتان. والمزيد من المرونة يساعد.</li>\n<li><strong>الـ Overfitting</strong> (تباين مرتفع، high variance): النموذج مرن بما يكفي ليطارد الضجيج. نتيجة التدريب مرتفعة، ونتيجة الاختبار أقل بكثير. وما يساعد هنا مرونة أقل، أو بيانات أكثر، أو الـ regularization.</li>\n</ul>\n<p>تشخّص الجهة التي أنت فيها بمقارنة النتيجتين، لا بالنظر إلى نتيجة التدريب وحدها أبدًا. الفجوة الصغيرة مع نتائج ضعيفة تقول “أضف قدرة”؛ والفجوة الكبيرة تقول “انزعها”.</p>\n<p>كمية البيانات تغيّر هذا التوازن. فمع 331 مريضًا، 285 عمودًا تهوّر؛ أما مع 300,000 مريض، فسيكون لنموذج الدرجة 3 نفسه مجال أضيق بكثير للحفظ، لأن ضجيج الصفوف الفردية يتلاشى بالتوسيط عبر هذا العدد الكبير من الأمثلة. لهذا تُعدّ “اجمع بيانات أكثر” علاجًا مشروعًا للـ overfitting وعديم الفائدة للـ underfitting: فالنموذج العاجز عن التعبير عن النمط لن يتحسّن فيه برؤية المزيد منه. وحين لا تكون متأكدًا من الجهة التي أنت فيها، يحسم الأمرَ منحنى التعلّم (learning curve)، أي نتيجتا التدريب والتحقق مرسومتين مقابل عدد صفوف التدريب: منحنيان يلتقيان عند مستوى منخفض يحتاجان إلى نموذج أغنى، ومنحنيان يبقيان متباعدين يحتاجان إلى بيانات أكثر أو نموذج أبسط.</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>من المغري أن تمرّ في حلقة على الدرجات من 1 إلى 6 وتحتفظ بأيّها حقق أفضل نتيجة على بيانات الاختبار. هذا يحوّل بيانات الاختبار إلى أداة ضبط، ولا تعود النتيجة التي تنشرها تقديرًا صادقًا. اقتطع <strong>جزء تحقق (validation)</strong> من بيانات التدريب، واختر الدرجة عليه، ثم أعد التدريب على بيانات التدريب كلها والمس بيانات الاختبار مرة واحدة.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">اختيار الدرجة بأمانة</h2>\n<p>إليك هذه الوصفة مع ثلاثة features. جزء التحقق يأتي من <code dir=\"ltr\">X_train</code>؛ ولا تُمسّ بيانات الاختبار حتى السطر الأخير تمامًا.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"2\"><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=\"2\" 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_diabetes</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\"> LinearRegression</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.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\"> PolynomialFeatures</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_diabetes(</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 style=\"color:#953800;--shiki-dark:#FFA657\">as_frame</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 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> X[[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"bmi\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"bp\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"s5\"</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>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">X_fit, X_val, y_fit, y_val </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> train_test_split(X_train, y_train, </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\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> poly_model</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(degree):</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> make_pipeline(PolynomialFeatures(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">degree</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">degree, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">include_bias</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), LinearRegression())</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">val_scores </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {d: poly_model(d).fit(X_fit, y_fit).score(X_val, y_val) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> d </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> range</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">7</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)}</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> d, s </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> val_scores.items():</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:#CF222E;--shiki-dark:#FF7B72\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"degree </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">d</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">: validation R2 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">s</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:6.3f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">best </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> max</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(val_scores, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">key</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">val_scores.get)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">final </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> poly_model(best).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\">\"chosen degree\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, best, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"| test R2\"</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\">(final.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=\"2\" hidden></div></div>\n<p>يختار التحقق الدرجة 1، أي الخط المستقيم. على هذه البيانات لا يستحق المنحنى التباينَ الإضافي الذي يجلبه. وهذه نتيجة شائعة ومفيدة: فالإجراء الأمين كثيرًا ما يفضّل النموذج البسيط الذي كانت نظرة خاطفة إلى بيانات الاختبار ستُقنعك بالعدول عنه.</p>\n<p>جزء تحقق واحد من نحو 80 مريضًا مليء بالضجيج هو أيضًا؛ فقد تفضّل قيمة مختلفة لـ <code dir=\"ltr\">random_state</code> الدرجة 2. سيستبدله القسم 4 بالتحقق المتقاطع، الذي يأخذ المتوسط عبر عدة تقسيمات. والمبدأ يبقى كما هو.</p>\n<p>خفض الدرجة طريقة فظّة للتحكم في التعقيد: إما أن يكون لديك عمود <code dir=\"ltr\">bmi × bp</code> وإما لا. الدرس القادم يحتفظ بكل الأعمدة، ويعاقب النموذج بدلًا من ذلك على الاعتماد عليها بشدة، وهذا مقبض أدقّ.</p>\n","toc":[{"id":"sec-1","text":"جعل النموذج الخطي ينحني","level":2},{"id":"sec-2","text":"نتيجة التدريب تواصل الصعود","level":2},{"id":"sec-3","text":"الـ Underfitting والـ Overfitting","level":2},{"id":"sec-4","text":"اختيار الدرجة بأمانة","level":2}],"takeaways":["يضيف <code dir=\"ltr\">PolynomialFeatures</code> أعمدة للمربعات وللتفاعلات، فيستطيع النموذج الخطي ملاءمة المنحنيات؛ ويتزايد عدد الأعمدة بسرعة كبيرة مع الدرجة.","الـ underfitting (ضعف التوافق) يعني أن النموذج أبسط من أن يلتقط النمط؛ فتكون نتيجتا التدريب والاختبار ضعيفتين معًا.","الـ overfitting (الإفراط في التوافق) يعني أن النموذج تعلّم الضجيج في صفوف التدريب؛ فتكون نتيجة التدريب مرتفعة ونتيجة الاختبار أقل بكثير.","اختر التعقيد (الدرجة، أو العمق، أو عدد الـ features) على جزء تحقق مقتطع من بيانات التدريب، ولا تختره أبدًا على بيانات الاختبار.","العلاجات المعتادة للـ overfitting هي نموذج أبسط، أو بيانات أكثر، أو features أقل، أو الـ regularization."],"further":[{"title":"PolynomialFeatures","url":"https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html"},{"title":"Underfitting vs. Overfitting","url":"https://scikit-learn.org/stable/auto_examples/model_selection/plot_underfitting_overfitting.html"},{"title":"Validation curves","url":"https://scikit-learn.org/stable/modules/learning_curve.html"}],"quiz":[{"q":"<p>يحقق نموذج قيمة R² تبلغ 0.52 على بيانات التدريب و0.49 على بيانات الاختبار. ونسخة أعقد منه تحقق 0.90 و-8.5. أيّ تشخيص يناسب؟</p>","options":[{"text":"النموذج البسيط يعاني من الـ underfitting، والمعقّد أفضل لأنه تعلّم أكثر.","why":"نتيجة اختبار النموذج المعقّد أدنى من الصفر بكثير، فكل ما تعلّمه لا ينتقل إلى بيانات جديدة. والفجوة الصغيرة بين التدريب والاختبار علامة صحية، لا علامة underfitting."},{"text":"النموذج المعقّد يعاني من الـ overfitting؛ فقد حفظ صفوف التدريب ويفشل مع الصفوف الجديدة.","why":"صحيح. القفزة الهائلة في نتيجة التدريب مع انهيار نتيجة الاختبار هي البصمة المميّزة للـ overfitting."},{"text":"كلا النموذجين يعاني من الـ underfitting لأن أيًّا منهما لا يبلغ 0.9 على بيانات الاختبار.","why":"كثير من المسائل الحقيقية يبلغ سقفها ما هو أدنى من 0.9 بكثير. ويُحكم على الـ underfitting بأن تكون نتيجة التدريب ضعيفة أيضًا، وهذا لا ينطبق على النموذج المعقّد."}],"answer":1},{"q":"<p>ما الأعمدة التي ينتجها <code dir=\"ltr\">PolynomialFeatures(degree=2, include_bias=False)</code> من عمودين <code dir=\"ltr\">a</code> و<code dir=\"ltr\">b</code>؟</p>","options":[{"text":"<code dir=\"ltr\">a</code> و<code dir=\"ltr\">b</code> و<code dir=\"ltr\">a^2</code> و<code dir=\"ltr\">a b</code> و<code dir=\"ltr\">b^2</code>","why":"صحيح. الدرجة 2 تضيف كل مربّع وكل حاصل ضرب بين زوج من الأعمدة، أي حدّ التفاعل."},{"text":"<code dir=\"ltr\">a^2</code> و<code dir=\"ltr\">b^2</code>","why":"تُحفظ الأعمدة الأصلية، ويُضاف حدّ التفاعل <code dir=\"ltr\">a b</code> أيضًا."},{"text":"<code dir=\"ltr\">1</code> و<code dir=\"ltr\">a</code> و<code dir=\"ltr\">b</code> و<code dir=\"ltr\">a^2</code> و<code dir=\"ltr\">b^2</code>","why":"<code dir=\"ltr\">include_bias=False</code> يحذف العمود الثابت، وحدّ التفاعل <code dir=\"ltr\">a b</code> غائب عن هذه القائمة."}],"answer":0},{"q":"<p>كيف يجب أن تختار درجة كثير الحدود؟</p>","options":[{"text":"اختر الدرجة صاحبة أعلى نتيجة تدريب.","why":"نتيجة التدريب تواصل الارتفاع مع الدرجة، فهذه الطريقة تختار دائمًا النموذج الأكثر overfitting."},{"text":"اختر الدرجة صاحبة أعلى نتيجة اختبار، ثم انشر تلك النتيجة.","why":"هذا يستخدم بيانات الاختبار لاتخاذ قرار، فتكون النتيجة المنشورة متفائلة."},{"text":"اقتطع جزء تحقق من بيانات التدريب، واختر الدرجة التي تحقق أفضل نتيجة عليه، ثم قِس مرة واحدة على بيانات الاختبار.","why":"صحيح. جزء التحقق يمتص عملية الاختيار؛ وتبقى بيانات الاختبار فحصًا نهائيًا غير منحاز."}],"answer":2},{"q":"<p>أيّ تغيير هو الأقل احتمالًا أن يقلّل الـ overfitting؟</p>","options":[{"text":"جمع صفوف تدريب أكثر.","why":"البيانات الأكثر تجعل حفظ الضجيج أصعب، فهي تساعد عادةً."},{"text":"إضافة درجات أعلى لكثير الحدود كي يلائم النموذج البيانات بدقة أكبر.","why":"صحيح. المرونة الإضافية هي سبب الـ overfitting أصلًا."},{"text":"خفض الدرجة أو حذف الـ features الضعيفة.","why":"النموذج الأبسط قدرته على الحفظ أقل، فهذا علاج مباشر."},{"text":"إضافة عقوبة على المعاملات الكبيرة.","why":"هذا هو الـ regularization، موضوع الدرس القادم، وهو علاج معياري."}],"answer":1}],"exercise":{"kind":"python","starter":"from sklearn.datasets import load_diabetes\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import PolynomialFeatures\n\nX, y = load_diabetes(return_X_y=True, as_frame=True)\nX = X[[\"bmi\", \"bp\", \"s5\", \"s3\"]]\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)\nX_fit, X_val, y_fit, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=0)\n\n# 1. val_scores: {degree: validation R2} for degrees 1 to 6.\n#    Fit each model on X_fit / y_fit, score it on X_val / y_val.\nval_scores = {}\n\n# 2. The degree with the best validation score\nbest_degree = None\n\n# 3. Refit that degree on ALL the training data, then score once on the test set\ntest_r2 = None\n","solution":"from sklearn.datasets import load_diabetes\nfrom sklearn.linear_model import LinearRegression\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import PolynomialFeatures\n\nX, y = load_diabetes(return_X_y=True, as_frame=True)\nX = X[[\"bmi\", \"bp\", \"s5\", \"s3\"]]\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)\nX_fit, X_val, y_fit, y_val = train_test_split(X_train, y_train, test_size=0.25, random_state=0)\n\ndef poly_model(degree):\n    return make_pipeline(PolynomialFeatures(degree=degree, include_bias=False), LinearRegression())\n\nval_scores = {d: poly_model(d).fit(X_fit, y_fit).score(X_val, y_val) for d in range(1, 7)}\nbest_degree = max(val_scores, key=val_scores.get)\ntest_r2 = poly_model(best_degree).fit(X_train, y_train).score(X_test, y_test)\nprint(val_scores, best_degree, test_r2)\n","checks":[{"id":"degrees","test":"sorted(val_scores) == [1, 2, 3, 4, 5, 6]"},{"id":"validation","test":"abs(float(val_scores[2]) - __import__('sklearn.pipeline', fromlist=['make_pipeline']).make_pipeline(__import__('sklearn.preprocessing', fromlist=['PolynomialFeatures']).PolynomialFeatures(degree=2, include_bias=False), __import__('sklearn.linear_model', fromlist=['LinearRegression']).LinearRegression()).fit(X_fit, y_fit).score(X_val, y_val)) < 1e-6"},{"id":"best","test":"best_degree == max(val_scores, key=val_scores.get)"},{"id":"test-score","test":"test_r2 is not None and abs(float(test_r2) - __import__('sklearn.pipeline', fromlist=['make_pipeline']).make_pipeline(__import__('sklearn.preprocessing', fromlist=['PolynomialFeatures']).PolynomialFeatures(degree=best_degree, include_bias=False), __import__('sklearn.linear_model', fromlist=['LinearRegression']).LinearRegression()).fit(X_train, y_train).score(X_test, y_test)) < 1e-6"}],"title":"اختر درجة كثير الحدود دون لمس بيانات الاختبار","prompt":"<p>باستخدام أربعة features من بيانات السكري، اختر درجة كثير الحدود بأمانة.</p>\n<ol>\n<li><code dir=\"ltr\">val_scores</code>: قاموس (dict) يربط كل درجة من 1 إلى 6 بقيمة R² الخاصة بها على جزء التحقق. كل نموذج هو <code dir=\"ltr\">PolynomialFeatures(degree=d, include_bias=False)</code> متبوعًا بـ <code dir=\"ltr\">LinearRegression</code>، مدرَّب على <code dir=\"ltr\">X_fit, y_fit</code> ومقيس على <code dir=\"ltr\">X_val, y_val</code>.</li>\n<li><code dir=\"ltr\">best_degree</code>: الدرجة صاحبة أعلى R² على جزء التحقق.</li>\n<li><code dir=\"ltr\">test_r2</code>: أعد تدريب تلك الدرجة على <code dir=\"ltr\">X_train, y_train</code> كاملة وقِسها مرة واحدة على <code dir=\"ltr\">X_test, y_test</code>.</li>\n</ol>\n","hints":["دالة مساعدة <code dir=\"ltr\">poly_model(degree)</code> تُعيد <code dir=\"ltr\">make_pipeline(PolynomialFeatures(...), LinearRegression())</code> تُبقي الحلقة قصيرة.","يعمل الـ dict comprehension هنا: <code dir=\"ltr\">{d: poly_model(d).fit(X_fit, y_fit).score(X_val, y_val) for d in range(1, 7)}</code>.","تُعيد <code dir=\"ltr\">max(val_scores, key=val_scores.get)</code> المفتاح صاحب أكبر قيمة."],"explanation":"<p>تتراجع نتائج التحقق كلما كبرت الدرجة، وبعض الدرجات العليا تصبح سالبة، فيستقر الإجراء على درجة منخفضة. وإعادة التدريب على <code dir=\"ltr\">X_train</code> كاملة تستخدم كل صفوف التدريب في النموذج النهائي، ونتيجة الاختبار الوحيدة تقدير غير منحاز لأن بيانات الاختبار لم يكن لها أي دور في الاختيار.</p>\n","checkLabels":{"degrees":"يحتوي val_scores على الدرجات من 1 إلى 6","validation":"نتائج التحقق تأتي من نماذج مدرَّبة على X_fit ومقيسة على X_val","best":"best_degree هي صاحبة أعلى نتيجة تحقق","test-score":"test_r2 يأتي من الدرجة المختارة بعد إعادة تدريبها على بيانات التدريب كلها"}},"words":633,"readMinutes":4}