{"id":"l-ml-2-4","courseId":"ml-crash-course","lang":"ar","kind":"lesson","summary":"تحكّم في الـ overfitting بمعاقبة المعاملات الكبيرة باستخدام Ridge وLasso، ووحّد مقاييس الـ features لتكون العقوبة عادلة، واستخدم أصفار Lasso اختيارًا تلقائيًا للـ features.","html":"<p>في الدرس السابق، أعطت الـ polynomial features من الدرجة 2 نموذجَ السكري 65 عمودًا، فانخفضت نتيجة الاختبار من 0.49 إلى 0.42. كان بإمكانك التخلّص من الأعمدة الإضافية. لكن الـ regularization (التنظيم) يقدّم ما هو أفضل: احتفظ بها كلها، لكن اجعل النموذج يدفع ثمن كل وحدة من المعاملات يستخدمها. الأعمدة التي تستحق مكانها تنال وزنًا؛ والبقية تتقلّص.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">عقوبة تُضاف إلى دالة الخسارة</h2>\n<p>تصغّر المربعات الصغرى العادية الخطأ المربّع ولا شيء غيره. أما الانحدار المنظَّم فيصغّر الخطأ المربّع <strong>مضافًا إليه</strong> عقوبةٌ تكبر مع حجم المعاملات:</p>\n<ul>\n<li><strong>Ridge</strong> يضيف <code dir=\"ltr\">alpha * sum(coef ** 2)</code>، وهي عقوبة L2.</li>\n<li><strong>Lasso</strong> يضيف <code dir=\"ltr\">alpha * sum(abs(coef))</code>، وهي عقوبة L1 (كما أن scikit-learn يعاير حدّ الخطأ بطريقة مختلفة قليلًا، ولهذا تختلف قيم <code dir=\"ltr\">alpha</code> الجيدة بين النموذجين).</li>\n</ul>\n<p>يحدّد <code dir=\"ltr\">alpha</code> سعر الصرف. عند 0 تعود إلى المربعات الصغرى. ومع ازدياده، يجب على المعامل الكبير أن يشتري خفضًا كبيرًا في الخطأ كي يستحق وجوده. والمعاملات التي لا تلائم إلا الضجيج لا تستطيع ذلك، فتتقلّص. القيم المربّعة تجعل Ridge يقلّص كل شيء بسلاسة؛ والقيم المطلقة تجعل Lasso يدفع المعاملات الضعيفة حتى الصفر.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">وحّد المقاييس أولًا، ثم عاقِب</h2>\n<p>تجمع العقوبة المعاملات كما لو كانت قابلة للمقارنة. وهي ليست كذلك إلا إذا اشتركت الـ features في مقياس واحد. قِس الإنفاق بالسنتات بدل الدولارات وسيصغر معامله مئة مرة، فلا تكاد العقوبة تلحظه. ضع دائمًا <code dir=\"ltr\">StandardScaler</code> قبل أي نموذج معاقَب.</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.linear_model </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> LinearRegression, Ridge, Lasso</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, 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_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\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> degree2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(model):</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:#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\">), StandardScaler(), model)</span></span>\n<span class=\"line\"></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\">\"no penalty:\"</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\">(degree2(LinearRegression()).fit(X_train, y_train).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 style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> alpha </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\">10</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1000</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    m </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> degree2(Ridge(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">alpha</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">alpha)).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\">\"Ridge alpha=</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">alpha</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:&#x3C;5}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> train </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">m.score(X_train, y_train)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:.3f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">  test </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">m.score(X_test, y_test)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:.3f}</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=\"0\" hidden></div></div>\n<p>مع ارتفاع <code dir=\"ltr\">alpha</code> تنخفض نتيجة التدريب باطّراد (إذ يُمنح النموذج حرية أقل)، بينما تصعد نتيجة الاختبار من 0.42 إلى 0.50 عند <code dir=\"ltr\">alpha=100</code>، وهذا أفضل من النموذج العادي ذي الـ features العشرة. ادفعها إلى 1,000 فتنخفض النتيجتان معًا: صار النموذج الآن في الـ underfitting. يحوّل الـ regularization المفاضلةَ بين الـ overfitting والـ underfitting إلى مقبض تديره.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">Lasso يختار الـ features نيابةً عنك</h2>\n<p>أجرِ التجربة نفسها مع Lasso وعُدّ المعاملات التي تنتهي إلى الصفر بالضبط.</p>\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\"> Lasso</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, 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_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\"> alpha </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.1</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\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    m </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:#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\">), StandardScaler(),</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">                      Lasso(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">alpha</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">alpha)).fit(X_train, y_train)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    zeros </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (m[</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\">].coef_ </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\">).sum()</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\">\"Lasso alpha=</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">alpha</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:&#x3C;4}</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\">m.score(X_test, y_test)</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:.3f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">  zero coefficients: </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">zeros</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> of 65\"</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\">names </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> m[</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].get_feature_names_out()</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">kept </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\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> n, c </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> zip</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(names, m[</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\">].coef_) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> c </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 style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"kept at alpha=5:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, kept)</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>عند <code dir=\"ltr\">alpha=2</code> يبلغ Lasso قيمة R² على الاختبار تساوي 0.53، وهي أفضل نتيجة انحدار في هذا القسم، مع تجاهله 39 عمودًا من أصل 65. وعند <code dir=\"ltr\">alpha=5</code> يحتفظ بـ 11 عمودًا: مؤشر كتلة الجسم وضغط الدم و<code dir=\"ltr\">s5</code> من النماذج السابقة، إضافة إلى بضعة تفاعلات مثل <code dir=\"ltr\">bmi bp</code>. يصل <code dir=\"ltr\">m[-1]</code> إلى آخر خطوة في الـ pipeline، ويُعطي <code dir=\"ltr\">m[0].get_feature_names_out()</code> أسماء الأعمدة المولّدة.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">ترويض المعاملات المترابطة</h2>\n<p>أتذكر <code dir=\"ltr\">s1</code> عند -918 و<code dir=\"ltr\">s2</code> عند +508 في الانحدار العادي، قياسَي دم مترابطَين يشدّ أحدهما عكس الآخر؟ مع الـ features الموحّدة المقاييس تظهر القصة نفسها على نطاق أصغر، والعقوبة تحسمها.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 660 230\" role=\"img\" aria-labelledby=\"l-ml-2-4-t1\"><defs><marker id=\"arrow-l-ml-2-4-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-4-t1\">معاملا s1 وs2 على features موحّدة المقاييس. المربعات الصغرى: s1 سالب 44، وs2 موجب 25. Ridge مع alpha تساوي 10: s1 سالب 13، وs2 قرب الصفر. Lasso مع alpha تساوي 1: s1 سالب 8، وs2 صفر بالضبط.</title>\n  <line class=\"d-line\" x1=\"330\" y1=\"20\" x2=\"330\" y2=\"200\"/>\n  <text class=\"d-label-muted\" x=\"330\" y=\"220\" text-anchor=\"middle\">0</text>\n  <text class=\"d-label\" x=\"20\" y=\"48\">المربعات الصغرى</text>\n  <rect class=\"d-box-warn\" x=\"198\" y=\"30\" width=\"132\" height=\"22\" rx=\"3\"/><text class=\"d-code\" x=\"190\" y=\"46\" text-anchor=\"end\">s1 −44</text>\n  <rect class=\"d-box-accent\" x=\"330\" y=\"56\" width=\"74\" height=\"22\" rx=\"3\"/><text class=\"d-code\" x=\"412\" y=\"72\">s2 +25</text>\n  <text class=\"d-label\" x=\"20\" y=\"113\">Ridge, alpha=10</text>\n  <rect class=\"d-box-warn\" x=\"291\" y=\"95\" width=\"39\" height=\"22\" rx=\"3\"/><text class=\"d-code\" x=\"283\" y=\"111\" text-anchor=\"end\">s1 −13</text>\n  <rect class=\"d-box-accent\" x=\"330\" y=\"121\" width=\"2\" height=\"22\" rx=\"1\"/><text class=\"d-code\" x=\"340\" y=\"137\">s2 +0.5</text>\n  <text class=\"d-label\" x=\"20\" y=\"178\">Lasso, alpha=1</text>\n  <rect class=\"d-box-warn\" x=\"305\" y=\"160\" width=\"25\" height=\"22\" rx=\"3\"/><text class=\"d-code\" x=\"297\" y=\"176\" text-anchor=\"end\">s1 −8</text>\n  <text class=\"d-code\" x=\"340\" y=\"198\">s2 0 (محذوف)</text>\n</svg><figcaption>ما الذي يحدث لمعاملين مترابطين</figcaption></figure>\n<p>يوزّع Ridge الوزن بين الـ features المترابطة بشكل معقول بدل أن يتركها يلغي بعضها بعضًا؛ بينما يميل Lasso إلى الاحتفاظ بأحدها وحذف الآخر. وفي الحالتين تصبح المعاملات مستقرة بما يكفي كي لا ينقلب اتجاهها مع تغيير صغير في بيانات التدريب.</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>ضبط alpha على بيانات الاختبار</span></p>\n<p><code dir=\"ltr\">alpha</code> hyperparameter مثل درجة كثير الحدود. فالمرور على قيمها ونشر أفضل نتيجة اختبار، كما تفعل الأمثلة أعلاه لتبيّن شكل المنحنى، يعطي رقمًا متفائلًا. في المشروع الحقيقي تختار <code dir=\"ltr\">alpha</code> على بيانات تحقق. يفعل <code dir=\"ltr\">RidgeCV</code> و<code dir=\"ltr\">LassoCV</code> ذلك بتحقق متقاطع مدمج، ويفعله <code dir=\"ltr\">GridSearchCV</code> في القسم 4 مع أي نموذج.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">Ridge أم Lasso؟</h2>\n<p>كلاهما يعالج الداء نفسه، فالاختيار يرجع إلى ما تريده من النموذج النهائي. يفوز Ridge عادةً حين تحمل features كثيرة شيئًا قليلًا من الإشارة لكلٍّ منها، وهذا شائع مع القياسات المتداخلة، مثل قراءات الدم الست هنا. ويفوز Lasso حين تهمّ features قليلة والبقية ضجيج، ويسلّمك قائمة مشتريات أقصر من المدخلات، وهذا مهم حين يجب جمع كل feature وتنظيفه ومراقبته في بيئة الإنتاج. وحين تأتي الـ features في مجموعات مترابطة، قد تكون عادة Lasso في الاحتفاظ بعضو واحد، باعتباطية إلى حدّ ما، غير مستقرة من تدريب إلى آخر. ويمزج <code dir=\"ltr\">ElasticNet</code> العقوبتين لهذه الحالة بالضبط. وعلى مجموعة بيانات بهذا الحجم، الإجابة الأمينة هي أن تجرّب الاثنين على بيانات تحقق وتحتفظ بالفائز، ثم تفضّل الأبسط حين يتعادلان.</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>لنموذج خطي على أكثر من حفنة من الـ features، ابدأ بـ <code dir=\"ltr\">Ridge</code> داخل pipeline مع <code dir=\"ltr\">StandardScaler</code>، وعامِل <code dir=\"ltr\">LinearRegression</code> العادي على أنه الاستثناء. والجأ إلى <code dir=\"ltr\">Lasso</code> حين تريد features أقل في النموذج النهائي.</p>\n</aside>\n<p>بهذا يُختتم الانحدار. وفكرة العقوبة نفسها تعود مباشرة في القسم القادم: <code dir=\"ltr\">LogisticRegression</code> منظَّم افتراضيًا، بمعامل <code dir=\"ltr\">C</code> يعمل كمقلوب <code dir=\"ltr\">alpha</code>. يعيد القسم 3 الهدفَ إلى انقطاع العملاء، نعم أو لا.</p>\n","toc":[{"id":"sec-1","text":"عقوبة تُضاف إلى دالة الخسارة","level":2},{"id":"sec-2","text":"وحّد المقاييس أولًا، ثم عاقِب","level":2},{"id":"sec-3","text":"Lasso يختار الـ features نيابةً عنك","level":2},{"id":"sec-4","text":"ترويض المعاملات المترابطة","level":2},{"id":"sec-5","text":"Ridge أم Lasso؟","level":2}],"takeaways":["يضيف الـ regularization إلى دالة الخسارة عقوبةً على حجم المعاملات، فيتنازل النموذج عن قليل من التوافق مع التدريب مقابل معاملات أبسط وأكثر استقرارًا.","يعاقب Ridge مربعات المعاملات فيقلّصها جميعًا؛ ويعاقب Lasso قيمها المطلقة فيجعل بعضها صفرًا بالضبط.","<code dir=\"ltr\">alpha</code> هو قوة العقوبة: 0 يعني المربعات الصغرى العادية، والقيم الكبيرة جدًا تسطّح النموذج حتى الـ underfitting.","وحّد مقاييس الـ features قبل النموذج المعاقَب، وإلا عاقبت العقوبةُ الـ features على وحداتها لا على فائدتها.","اختر <code dir=\"ltr\">alpha</code> على بيانات تحقق أو بالتحقق المتقاطع، بالطريقة نفسها التي تختار بها أي hyperparameter."],"further":[{"title":"Ridge regression and classification","url":"https://scikit-learn.org/stable/modules/linear_model.html#ridge-regression-and-classification"},{"title":"Lasso","url":"https://scikit-learn.org/stable/modules/linear_model.html#lasso"},{"title":"Ridge","url":"https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html"}],"quiz":[{"q":"<p>رفعت قيمة <code dir=\"ltr\">alpha</code> في Ridge من 1 إلى 100,000. ماذا يحدث للنموذج؟</p>","options":[{"text":"تتقلّص المعاملات نحو الصفر وتقترب التنبؤات من متوسط الهدف؛ فيقع النموذج في الـ underfitting.","why":"صحيح. العقوبة الهائلة تجعل أي معامل غير صفري باهظ الكلفة، فيرتدّ النموذج إلى ما يقارب الـ intercept وحده."},{"text":"تكبر المعاملات ليلائم النموذج بيانات التدريب بدقة أكبر.","why":"قيمة <code dir=\"ltr\">alpha</code> الأكبر تجعل المعاملات الكبيرة أغلى، لا أرخص."},{"text":"تصبح معظم المعاملات صفرًا بالضبط، ولا يبقى إلا قليل من الـ features.","why":"هذا سلوك Lasso. أما Ridge فيقلّص المعاملات بسلاسة، لكنه لا يكاد يوصلها إلى الصفر بالضبط أبدًا."}],"answer":0},{"q":"<p>لماذا نضع <code dir=\"ltr\">StandardScaler</code> قبل <code dir=\"ltr\">Lasso</code> في الـ pipeline؟</p>","options":[{"text":"لأن Lasso لا يتعامل مع الأرقام السالبة دون توحيد المقاييس.","why":"يعمل Lasso على أي أعداد حقيقية. المشكلة في عدالة العقوبة."},{"text":"لأن العقوبة تعامل كل المعاملات بالطريقة نفسها، فيجب أن تشترك الـ features في مقياس واحد كي تحكم عليها بفائدتها لا بوحداتها.","why":"صحيح. الـ feature المقيس بوحدات كبيرة يحتاج إلى معامل ضئيل فيفلت من العقوبة؛ والمقيس بوحدات صغيرة يُعاقَب."},{"text":"لأن توحيد المقاييس يجعل Lasso يتقارب إلى الإجابة نفسها التي تعطيها المربعات الصغرى العادية.","why":"توحيد المقاييس لا يزيل العقوبة؛ فمع <code dir=\"ltr\">alpha &gt; 0</code> يبقى Lasso مختلفًا عن المربعات الصغرى."}],"answer":1},{"q":"<p>تحتاج إلى نموذج انقطاع يستخدم أقل عدد ممكن من 60 feature مرشّحًا. ما الخيار الأول الطبيعي؟</p>","options":[{"text":"Ridge، لأنه يقلّص المعاملات الستين كلها.","why":"يحتفظ Ridge بكل feature بوزن صغير، فستظل بحاجة إلى المدخلات الستين كلها وقت التنبؤ."},{"text":"الانحدار الخطي العادي، ثم حذف الـ features ذات أصغر المعاملات.","why":"المعاملات غير المعاقَبة للـ features المترابطة غير مستقرة، فـ “الأصغر” معيار غير موثوق."},{"text":"عقوبة L1 (على طريقة Lasso)، لأنها تدفع المعاملات عديمة الفائدة إلى الصفر بالضبط.","why":"صحيح. هذه الأصفار اختيار مدمج للـ features؛ ويمكنك بعدها فحص الـ features التي نجت."}],"answer":2}],"exercise":{"kind":"python","starter":"from sklearn.datasets import load_diabetes\nfrom sklearn.linear_model import Lasso, Ridge\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import PolynomialFeatures, StandardScaler\n\nX, y = load_diabetes(return_X_y=True, as_frame=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)\n\n# 1. Pipeline: degree-2 PolynomialFeatures (include_bias=False) -> StandardScaler -> Lasso(alpha=1)\nlasso_model = make_pipeline(PolynomialFeatures(degree=2, include_bias=False), Lasso(alpha=1))\nlasso_model.fit(X_train, y_train)\n\n# 2. Test R2 and the number of coefficients that are exactly zero\nlasso_r2 = None\nn_zero = None\n\n# 3. Names of the generated columns Lasso kept (non-zero coefficient), as a list of strings\nkept = None\n","solution":"from sklearn.datasets import load_diabetes\nfrom sklearn.linear_model import Lasso, Ridge\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.pipeline import make_pipeline\nfrom sklearn.preprocessing import PolynomialFeatures, StandardScaler\n\nX, y = load_diabetes(return_X_y=True, as_frame=True)\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)\n\nlasso_model = make_pipeline(PolynomialFeatures(degree=2, include_bias=False), StandardScaler(), Lasso(alpha=1))\nlasso_model.fit(X_train, y_train)\n\nlasso_r2 = lasso_model.score(X_test, y_test)\ncoefs = lasso_model[-1].coef_\nn_zero = int((coefs == 0).sum())\n\nnames = lasso_model[0].get_feature_names_out()\nkept = [name for name, c in zip(names, coefs) if c != 0]\nprint(round(lasso_r2, 3), n_zero, len(kept))\n","checks":[{"id":"scaled","test":"[type(s).__name__ for s in lasso_model] == ['PolynomialFeatures', 'StandardScaler', 'Lasso'] and lasso_model[-1].alpha == 1"},{"id":"r2","test":"lasso_r2 is not None and abs(float(lasso_r2) - 0.515) < 0.005"},{"id":"zeros","test":"n_zero is not None and int(n_zero) == int((lasso_model[-1].coef_ == 0).sum()) == 30"},{"id":"kept","test":"kept is not None and len(kept) == 35 and 'bmi' in list(kept) and all(isinstance(k, str) for k in kept)"}],"title":"دع Lasso يختار الـ features","prompt":"<p>الـ pipeline في الكود المبدئي ينسى شيئًا مهمًا. أصلحه، ثم افحص ما فعله Lasso.</p>\n<ol>\n<li><code dir=\"ltr\">lasso_model</code>: <code dir=\"ltr\">PolynomialFeatures(include_bias=False)</code> من الدرجة 2، ثم <code dir=\"ltr\">StandardScaler</code>، ثم <code dir=\"ltr\">Lasso(alpha=1)</code>، مدرَّبًا على بيانات التدريب.</li>\n<li><code dir=\"ltr\">lasso_r2</code>: قيمة R² على بيانات الاختبار. و<code dir=\"ltr\">n_zero</code>: عدد معاملاته الـ 65 التي تساوي صفرًا بالضبط.</li>\n<li><code dir=\"ltr\">kept</code>: قائمة بأسماء الأعمدة المولّدة التي معاملها ليس صفرًا.</li>\n</ol>\n","hints":["بلا scaler تحكم العقوبة على الـ features بحسب وحداتها. أضف <code dir=\"ltr\">StandardScaler()</code> بين الخطوتين الموجودتين.","يعطيك <code dir=\"ltr\">lasso_model[-1].coef_</code> معاملات Lasso؛ و<code dir=\"ltr\">(coef == 0).sum()</code> يعدّ الأصفار.","يسرد <code dir=\"ltr\">lasso_model[0].get_feature_names_out()</code> أسماء الأعمدة المولّدة الـ 65 بترتيب المعاملات نفسه."],"explanation":"<p>مع وجود توحيد المقاييس، يبلغ Lasso عند <code dir=\"ltr\">alpha=1</code> قيمة R² على الاختبار بنحو 0.515 ويجعل 30 من 65 معاملًا أصفارًا، محتفظًا بـ 35 عمودًا. وبدون الـ scaler، يعني المقياس الضئيل لـ features بيانات السكري أن العقوبة تسحق معظم المعاملات للسبب الخاطئ: وحداتها، لا فائدتها. وربط الأسماء بالمعاملات هو الطريقة التي تُبلغ بها عن المدخلات التي يحتاجها النموذج النهائي فعلًا.</p>\n","checkLabels":{"scaled":"الـ pipeline هو PolynomialFeatures ← StandardScaler ← Lasso(alpha=1)","r2":"lasso_r2 هو قيمة R² على بيانات الاختبار","zeros":"n_zero يعدّ المعاملات الصفرية","kept":"kept يسرد أسماء الأعمدة غير الصفرية"}},"words":663,"readMinutes":4}