{"id":"l-ml-4-3","courseId":"ml-crash-course","lang":"ar","kind":"lesson","summary":"اضبط الـ hyperparameters باستخدام GridSearchCV وRandomizedSearchCV مع أسماء خطوات الـ pipeline، واقرأ cv_results_، وحافظ على أمانة نتيجة الاختبار النهائية بعد البحث.","html":"<p>كل نموذج حتى الآن كانت له إعدادات اخترتها يدويًا أو تركتها على قيمها الافتراضية: <code dir=\"ltr\">C=1.0</code> و<code dir=\"ltr\">max_depth=3</code> و<code dir=\"ltr\">min_samples_leaf=5</code>. بعض هذه الخيارات مهم جدًا، وبعضها لا يكاد يهم، والطريقة الوحيدة لمعرفة ذلك هي التجربة. والتجربة يدويًا تعني حلقات تكرار ومسك دفاتر وإغراءً باختلاس النظر إلى بيانات الاختبار. أدوات البحث في scikit-learn تفعل ذلك كما ينبغي، مع تحقق متقاطع مدمج.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">البحث الشبكي</h2>\n<p>يأخذ <code dir=\"ltr\">GridSearchCV</code> estimator وقاموسًا من قيم المعاملات ومخطط تحقق متقاطع. ويطبّق التحقق المتقاطع على كل تركيبة، ويختار صاحبة أفضل متوسط، ويعيد تدريبها على بيانات التدريب كلها. وبعد ذلك يتصرّف كالنموذج الفائز.</p>\n<p>يُشار إلى المعاملات داخل الـ pipeline باسم الخطوة، ثم شرطتين سفليتين، ثم اسم المعامل. ولهذا تؤتي تسميةُ خطواتك ثمارها.</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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</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\"> GridSearchCV, StratifiedKFold, 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\"> 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\">churn </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churn.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">features </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"tenure_days\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total_spent\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"avg_order_value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">            \"days_since_last_order\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"used_coupon\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"support_tickets\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile_share\"</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(</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    churn[features], churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </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:#953800;--shiki-dark:#FFA657\">    stratify</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> StratifiedKFold(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">n_splits</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">shuffle</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\">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:#1F2328;--shiki-dark:#E6EDF3\">pipe </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Pipeline([(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"scale\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, StandardScaler()), (</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"model\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, LogisticRegression())])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">search </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> GridSearchCV(pipe, {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"model__C\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.01</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.03</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\">0.3</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\">3</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>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">                      cv</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">scoring</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"roc_auc\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">search.fit(X_train, y_train)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">results </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.DataFrame(search.cv_results_)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(results[[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"param_model__C\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mean_test_score\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"std_test_score\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]].round(</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:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"best:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, search.best_params_, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"CV AUC\"</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\">(search.best_score_, </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>يحمل <code dir=\"ltr\">cv_results_</code> نتائج الطيّات لكل تركيبة؛ وتصفّحه سهل حين يكون DataFrame. وهنا التصفّح نفسه هو الاستنتاج: من <code dir=\"ltr\">C=0.03</code> إلى <code dir=\"ltr\">C=10</code> يتحرك متوسط الـ AUC بأقل من نصف نقطة، وهذا أصغر بكثير من التشتّت بين الطيّات. ثمانية features حسنة السلوك لا تترك للانحدار اللوجستي مجالًا للـ overfitting، فلا تكاد عقوبته تهم. الضبط لا يستطيع إنقاذ نموذج بلغ سقفه أصلًا؛ أما features أفضل أو عائلة نماذج مختلفة فقد تستطيع.</p>\n<p>لاحظ أن القيم متباعدة بعوامل تقارب الثلاثة. في المعاملات التي تعمل بشكل ضربي (<code dir=\"ltr\">C</code> و<code dir=\"ltr\">alpha</code> ومعدّلات التعلّم)، ابحث على مقياس لوغاريتمي؛ فالقيم 0.01 و0.1 و1 و10 تغطي مساحة أكبر بكثير من 1 و2 و3 و4.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">شبكة حيث يهمّ الأمر</h2>\n<p>الأشجار قصة أخرى. العمق والحدّ الأدنى لحجم الورقة يتحكمان في مقدار ما تستطيع الشجرة حفظه، والقيم الصحيحة تعتمد على البيانات.</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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</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\"> GridSearchCV, StratifiedKFold, 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.tree </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> DecisionTreeClassifier</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">churn </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churn.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">features </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"tenure_days\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total_spent\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"avg_order_value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">            \"days_since_last_order\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"used_coupon\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"support_tickets\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile_share\"</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(</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    churn[features], churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </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:#953800;--shiki-dark:#FFA657\">    stratify</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> StratifiedKFold(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">n_splits</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">shuffle</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\">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:#1F2328;--shiki-dark:#E6EDF3\">grid </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"max_depth\"</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 style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</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 style=\"color:#0550AE;--shiki-dark:#79C0FF\">None</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"min_samples_leaf\"</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\">5</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\">20</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">40</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]}</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">search </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> GridSearchCV(DecisionTreeClassifier(</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\">), grid, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">cv</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">scoring</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"roc_auc\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">search.fit(X_train, y_train)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">top </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.DataFrame(search.cv_results_).sort_values(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rank_test_score\"</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\">(top[[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"param_max_depth\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"param_min_samples_leaf\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mean_test_score\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]].head(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).round(</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:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"worst:\"</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\">(top[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mean_test_score\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].min(), </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:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"best:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, search.best_params_, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"| test AUC\"</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\">(search.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=\"1\" hidden></div></div>\n<p>25 تركيبة × 5 طيّات = 125 عملية تدريب، إضافة إلى إعادة تدريب نهائية واحدة. والتشتّت واسع: أسوأ الأشجار (بعمق غير محدود وأوراق من عميل واحد) تحقق نتائج أدنى بكثير من الأفضل. تستخدم <code dir=\"ltr\">search.score</code> مقياس <code dir=\"ltr\">scoring</code> نفسه المستخدم في البحث، فهي تُبلغ هنا عن الـ ROC AUC على بيانات الاختبار.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">البحث العشوائي</h2>\n<p>تكبر الشبكات بشكل ضربي. أربعة معاملات بستّ قيم لكلٍّ منها تعني 1,296 تركيبة، مضروبة في خمس طيّات. أما <strong><code dir=\"ltr\">RandomizedSearchCV</code></strong> فيسحب بدلًا من ذلك عددًا ثابتًا من التركيبات (<code dir=\"ltr\">n_iter</code>)، ويقبل التوزيعات إلى جانب القوائم.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 270\" role=\"img\" aria-labelledby=\"l-ml-4-3-t1\"><defs><marker id=\"arrow-l-ml-4-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-4-3-t1\">مربّعان، المعامل المهم على المحور الأفقي وغير المهم على العمودي. تضع الشبكة تسع نقاط في شبكة 3 في 3، فلا تختبر إلا ثلاث قيم مختلفة للمعامل المهم. أما البحث العشوائي فينثر تسع نقاط، فيختبر تسع قيم مختلفة.</title>\n  <rect class=\"d-box\" x=\"40\" y=\"20\" width=\"240\" height=\"200\" rx=\"6\"/>\n  <rect class=\"d-box\" x=\"400\" y=\"20\" width=\"240\" height=\"200\" rx=\"6\"/>\n  <circle class=\"d-dot\" cx=\"80\" cy=\"60\" r=\"7\"/><circle class=\"d-dot\" cx=\"160\" cy=\"60\" r=\"7\"/><circle class=\"d-dot\" cx=\"240\" cy=\"60\" r=\"7\"/>\n  <circle class=\"d-dot\" cx=\"80\" cy=\"120\" r=\"7\"/><circle class=\"d-dot\" cx=\"160\" cy=\"120\" r=\"7\"/><circle class=\"d-dot\" cx=\"240\" cy=\"120\" r=\"7\"/>\n  <circle class=\"d-dot\" cx=\"80\" cy=\"180\" r=\"7\"/><circle class=\"d-dot\" cx=\"160\" cy=\"180\" r=\"7\"/><circle class=\"d-dot\" cx=\"240\" cy=\"180\" r=\"7\"/>\n  <circle class=\"d-dot\" cx=\"425\" cy=\"150\" r=\"7\"/><circle class=\"d-dot\" cx=\"452\" cy=\"70\" r=\"7\"/><circle class=\"d-dot\" cx=\"478\" cy=\"195\" r=\"7\"/>\n  <circle class=\"d-dot\" cx=\"505\" cy=\"105\" r=\"7\"/><circle class=\"d-dot\" cx=\"532\" cy=\"45\" r=\"7\"/><circle class=\"d-dot\" cx=\"560\" cy=\"170\" r=\"7\"/>\n  <circle class=\"d-dot\" cx=\"585\" cy=\"125\" r=\"7\"/><circle class=\"d-dot\" cx=\"608\" cy=\"60\" r=\"7\"/><circle class=\"d-dot\" cx=\"628\" cy=\"200\" r=\"7\"/>\n  <text class=\"d-label-strong\" x=\"160\" y=\"245\" text-anchor=\"middle\">الشبكة: 3 قيم مُجرَّبة</text>\n  <text class=\"d-label-strong\" x=\"520\" y=\"245\" text-anchor=\"middle\">العشوائي: 9 قيم مُجرَّبة</text>\n  <text class=\"d-label-muted\" x=\"340\" y=\"125\" text-anchor=\"middle\">المهم →</text>\n</svg><figcaption>البحث الشبكي مقابل البحث العشوائي بالمحاولات التسع نفسها</figcaption></figure>\n<p>حين لا يهمّ حقًا إلا معامل أو اثنان، وهي الحالة المعتادة، يستكشف البحث العشوائي قيمًا مختلفة لهما أكثر بكثير بالميزانية نفسها.</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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> scipy.stats </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> randint</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> sklearn.ensemble </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> RandomForestClassifier</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\"> RandomizedSearchCV, StratifiedKFold, train_test_split</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">churn </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churn.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">features </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"tenure_days\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total_spent\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"avg_order_value\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">,</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">            \"days_since_last_order\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"used_coupon\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"support_tickets\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile_share\"</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(</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    churn[features], churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </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:#953800;--shiki-dark:#FFA657\">    stratify</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">churn[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"churned\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> StratifiedKFold(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">n_splits</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">shuffle</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\">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:#1F2328;--shiki-dark:#E6EDF3\">space </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"max_features\"</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 style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sqrt\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"min_samples_leaf\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: randint(</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\">30</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)}</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">search </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> RandomizedSearchCV(RandomForestClassifier(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">n_estimators</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">60</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\">), space,</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">                            n_iter</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">8</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">cv</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cv, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">scoring</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"roc_auc\"</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\">search.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\">\"best:\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, search.best_params_)</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\">\"CV AUC\"</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\">(search.best_score_, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"| test AUC\"</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\">(search.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>تسحب <code dir=\"ltr\">randint(1, 30)</code> من SciPy أعدادًا صحيحة من 1 إلى 29؛ و<code dir=\"ltr\">loguniform(0.01, 10)</code> هو الخيار المعتاد لـ <code dir=\"ltr\">C</code> أو معدّلات التعلّم. اضبط <code dir=\"ltr\">random_state</code> على البحث كي يسحب المرشّحين أنفسهم في كل تشغيل.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">البحث في ما هو أبعد من إعدادات النموذج</h2>\n<p>لأن البحث يضبط الـ pipeline كله، فخيارات المعالجة المسبقة مشمولة أيضًا. إدخال في الشبكة مثل <code dir=\"ltr\">&quot;prep__sat__simpleimputer__strategy&quot;: [&quot;mean&quot;, &quot;median&quot;]</code> يقارن استراتيجيات الملء بالطيّات الأمينة نفسها. بل يمكنك تمرير قائمة من الشبكات، واحدة لكل عائلة نماذج، وترك البحث يبدّل الخطوة الأخيرة: <code dir=\"ltr\">[{&quot;model&quot;: [LogisticRegression()], &quot;model__C&quot;: [0.1, 1]}, {&quot;model&quot;: [RandomForestClassifier()], &quot;model__min_samples_leaf&quot;: [5, 20]}]</code>. هذا أنيق، لكنه يضاعف عمليات التدريب بسرعة، ويُخفي جدول المقارنة الذي تريد أن تعرضه على زميل. ولحفنة من النماذج المرشّحة، كثيرًا ما تكون حلقة بسيطة من استدعاءات <code dir=\"ltr\">cross_validate</code> بالـ splitter نفسه أوضح.</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>تصديق best_score_</span></p>\n<p>يُبلغ البحث عن الأفضل من بين نتائج تحقق متقاطع كثيرة. وجزء من هذا “الأفضل” حظ: فبين عدد كافٍ من المرشّحين المليئين بالضجيج، سيبدو أحدهم جيدًا بالمصادفة. توقّع أن تأتي نتيجة الاختبار أقل قليلًا، كما يحدث هنا، وانشر نتيجة الاختبار. وإذا احتجت إلى تقدير غير منحاز دون بيانات اختبار، فالتحقق المتقاطع المتداخل (nested cross-validation، أي بحث داخل كل طيّة خارجية) يعطيك واحدًا، بكلفة أعلى بكثير.</p>\n</aside>\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>ابدأ بشكل خشن وعلى مقياس لوغاريتمي، وانظر في <code dir=\"ltr\">cv_results_</code>، ثم ضيّق حول المنطقة الأفضل. اضبط المعاملين أو الثلاثة التي تتحكم في التعقيد (العمق، وحجم الورقة، و<code dir=\"ltr\">C</code>، ومعدّل التعلّم) واترك البقية على قيمها الافتراضية. وإذا كانت أفضل عشرة إعدادات أو نحوها ضمن انحراف معياري واحد من بعضها، فتوقّف: أنت تضبط الضجيج.</p>\n</aside>\n<p>عمليات البحث تضاعف عدد النماذج التي تدرّبها، ومعها عدد الفرص لتسرّب المعلومات من بيانات التحقق إلى التدريب. الدرس القادم دليل ميداني لتسرّب البيانات: كيف يحدث، وكيف تكتشفه، ولماذا ينتج أفضل النتائج التي ستراها في حياتك.</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":["يجرّب <code dir=\"ltr\">GridSearchCV</code> كل تركيبة في الشبكة مع تحقق متقاطع لكلٍّ منها؛ ويسحب <code dir=\"ltr\">RandomizedSearchCV</code> عددًا ثابتًا من التركيبات من قوائم أو توزيعات.","داخل الـ pipeline، يُشار إلى المعاملات بالصيغة <code dir=\"ltr\">step__parameter</code>، مثل <code dir=\"ltr\">model__C</code>.","بعد البحث، يحمل <code dir=\"ltr\">best_params_</code> الفائز، و<code dir=\"ltr\">best_estimator_</code> هو ذلك النموذج بعد إعادة تدريبه على بيانات التدريب كلها.","قيمة <code dir=\"ltr\">best_score_</code> متفائلة قليلًا لأنها الأفضل من بين محاولات كثيرة؛ وبيانات الاختبار تعطي الرقم غير المنحاز.","ابحث على مقياس لوغاريتمي في معاملات مثل <code dir=\"ltr\">C</code> و<code dir=\"ltr\">alpha</code> و<code dir=\"ltr\">learning_rate</code>، وتوقّع أن يضيف الضبط نقاطًا، لا معجزات."],"further":[{"title":"Tuning the hyper-parameters of an estimator","url":"https://scikit-learn.org/stable/modules/grid_search.html"},{"title":"GridSearchCV","url":"https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html"},{"title":"RandomizedSearchCV","url":"https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.RandomizedSearchCV.html"}],"quiz":[{"q":"<p>الـ pipeline لديك هو <code dir=\"ltr\">Pipeline([(&quot;prep&quot;, preprocess), (&quot;clf&quot;, LogisticRegression())])</code>. أيّ شبكة تضبط قوة الـ regularization؟</p>","options":[{"text":"<code dir=\"ltr\">{&quot;C&quot;: [0.1, 1, 10]}</code>","why":"لا يوجد في الـ pipeline معامل اسمه <code dir=\"ltr\">C</code>؛ وسيرفع البحث خطأ معامل غير صالح."},{"text":"<code dir=\"ltr\">{&quot;LogisticRegression__C&quot;: [0.1, 1, 10]}</code>","why":"البادئة هي اسم الخطوة، لا اسم الصنف."},{"text":"<code dir=\"ltr\">{&quot;clf.C&quot;: [0.1, 1, 10]}</code>","why":"يستخدم scikit-learn شرطتين سفليتين، لا نقطة، للوصول إلى داخل الخطوات."},{"text":"<code dir=\"ltr\">{&quot;clf__C&quot;: [0.1, 1, 10]}</code>","why":"صحيح. اسم الخطوة، ثم شرطتان سفليتان، ثم اسم المعامل."}],"answer":3},{"q":"<p>في شبكة 5 قيم لـ <code dir=\"ltr\">max_depth</code> و5 قيم لـ <code dir=\"ltr\">min_samples_leaf</code>، مع <code dir=\"ltr\">cv=5</code>. كم نموذجًا يُدرَّب، بما في ذلك إعادة التدريب النهائية؟</p>","options":[{"text":"126: أي 25 تركيبة × 5 طيّات، إضافة إلى إعادة تدريب واحدة على بيانات التدريب كلها.","why":"صحيح. مع القيمة الافتراضية <code dir=\"ltr\">refit=True</code> يُعاد تدريب الفائز مرة أخرى في النهاية."},{"text":"25: واحد لكل تركيبة.","why":"كل تركيبة تخضع للتحقق المتقاطع، فتُدرَّب مرة لكل طيّة."},{"text":"10: خمس قيم زائد خمس قيم.","why":"تجرّب الشبكة كل تركيبة، لا كل قيمة على حدة."}],"answer":0},{"q":"<p>لماذا قد يتفوّق <code dir=\"ltr\">RandomizedSearchCV</code> بعشرين تكرارًا على شبكة من 400 تركيبة بالميزانية الزمنية نفسها؟</p>","options":[{"text":"لأن البحث العشوائي يستخدم مُحسِّنًا أذكى يتعلّم من المحاولات السابقة.","why":"البحث العشوائي العادي لا يتعلّم بين المحاولات؛ فكل عيّنة مستقلة."},{"text":"لأن البحث العشوائي يجد دائمًا القيمة المثلى الحقيقية.","why":"إنه يسحب عيّنات، فقد يفوّت القيمة المثلى؛ والغاية الكفاءة، لا الضمانات."},{"text":"لأنه حين لا يهمّ إلا عدد قليل من المعاملات، يجرّب السحب العشوائي قيمًا مختلفة لتلك المعاملات أكثر بكثير مما تجرّبه الشبكة.","why":"صحيح. تهدر الشبكة المحاولات في تكرار قيم المعامل المهم نفسها بينما تنوّع المعاملات غير المهمة."}],"answer":2},{"q":"<p>يُبلغ البحث عن <code dir=\"ltr\">best_score_ = 0.813</code>، ويحقق النموذج المُعاد تدريبه 0.805 على بيانات الاختبار. ما الذي يحدث؟</p>","options":[{"text":"لا بد أن بيانات الاختبار تتسرّب، فالنتائج يجب أن تتطابق تمامًا.","why":"النتائج تختلف على بيانات مختلفة؛ والتسرّب كان سيرفع نتيجة الاختبار، لا أن يخفضها."},{"text":"أفضل نتيجة من بين نتائج تحقق متقاطع كثيرة متفائلة قليلًا؛ ونتيجة الاختبار هي التقدير الأمين.","why":"صحيح. اختيار الحدّ الأقصى من نتائج مليئة بالضجيج يحابي الإعدادات المحظوظة، وهي “لعنة الفائز”."},{"text":"إعادة التدريب على بيانات التدريب كلها جعلت النموذج أسوأ.","why":"نادرًا ما تضرّ بيانات التدريب الإضافية؛ والفجوة تأتي من طريقة اختيار الفائز."}],"answer":1}],"exercise":{"kind":"python","files":["churn.csv"],"starter":"import pandas as pd\nfrom sklearn.model_selection import GridSearchCV, StratifiedKFold, train_test_split\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.preprocessing import StandardScaler\n\nchurn = pd.read_csv(\"churn.csv\")\nfeatures = [\"tenure_days\", \"orders\", \"total_spent\", \"avg_order_value\",\n            \"days_since_last_order\", \"used_coupon\", \"support_tickets\", \"mobile_share\"]\nX_train, X_test, y_train, y_test = train_test_split(\n    churn[features], churn[\"churned\"], test_size=0.25, random_state=42,\n    stratify=churn[\"churned\"])\ncv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\npipe = Pipeline([(\"scale\", StandardScaler()), (\"knn\", KNeighborsClassifier())])\n\n# 1. Grid: n_neighbors in [5, 15, 25, 35, 51] and weights in [\"uniform\", \"distance\"]\ngrid = {\"n_neighbors\": [5, 15, 25, 35, 51], \"weights\": [\"uniform\", \"distance\"]}\n\n# 2. Search with the provided cv, scoring ROC AUC, fitted on the training data\nsearch = None\n\n# 3. Results\nbest_params = None\nbest_cv_auc = None\ntest_auc = None   # ROC AUC of the refit best model on the test set\n","solution":"import pandas as pd\nfrom sklearn.model_selection import GridSearchCV, StratifiedKFold, train_test_split\nfrom sklearn.neighbors import KNeighborsClassifier\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.preprocessing import StandardScaler\n\nchurn = pd.read_csv(\"churn.csv\")\nfeatures = [\"tenure_days\", \"orders\", \"total_spent\", \"avg_order_value\",\n            \"days_since_last_order\", \"used_coupon\", \"support_tickets\", \"mobile_share\"]\nX_train, X_test, y_train, y_test = train_test_split(\n    churn[features], churn[\"churned\"], test_size=0.25, random_state=42,\n    stratify=churn[\"churned\"])\ncv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)\n\npipe = Pipeline([(\"scale\", StandardScaler()), (\"knn\", KNeighborsClassifier())])\n\ngrid = {\"knn__n_neighbors\": [5, 15, 25, 35, 51], \"knn__weights\": [\"uniform\", \"distance\"]}\n\nsearch = GridSearchCV(pipe, grid, cv=cv, scoring=\"roc_auc\")\nsearch.fit(X_train, y_train)\n\nbest_params = search.best_params_\nbest_cv_auc = search.best_score_\ntest_auc = search.score(X_test, y_test)\nprint(best_params, round(best_cv_auc, 3), round(test_auc, 3))\n","checks":[{"id":"grid-names","test":"set(grid) == {'knn__n_neighbors', 'knn__weights'}"},{"id":"searched","test":"search is not None and len(search.cv_results_['params']) == 10 and search.scoring == 'roc_auc' and search.cv is cv and hasattr(search, 'best_estimator_')"},{"id":"best","test":"best_params is not None and best_params == search.best_params_ and best_params['knn__n_neighbors'] in [15, 25, 35, 51] and abs(float(best_cv_auc) - float(search.best_score_)) < 1e-9 and 0.77 < float(best_cv_auc) < 0.82"},{"id":"test-auc","test":"test_auc is not None and abs(float(test_auc) - float(search.score(X_test, y_test))) < 1e-9 and 0.75 < float(test_auc) < 0.82"}],"title":"اضبط أقرب k جيران","prompt":"<p>جد أفضل عدد من الجيران لـ pipeline من k-NN بعد توحيد المقاييس.</p>\n<ol>\n<li>أصلح <code dir=\"ltr\">grid</code> بحيث تشير مفاتيحه إلى الخطوة <code dir=\"ltr\">knn</code> في الـ pipeline (مفاتيح الكود المبدئي سترفع خطأ معامل غير صالح).</li>\n<li><code dir=\"ltr\">search</code>: نموذج <code dir=\"ltr\">GridSearchCV</code> على <code dir=\"ltr\">pipe</code> مع <code dir=\"ltr\">cv</code> المعطى و<code dir=\"ltr\">scoring=&quot;roc_auc&quot;</code>، مدرَّبًا على بيانات التدريب.</li>\n<li><code dir=\"ltr\">best_params</code> و<code dir=\"ltr\">best_cv_auc</code>: الإعدادات الفائزة ومتوسط الـ AUC الخاص بها بالتحقق المتقاطع. و<code dir=\"ltr\">test_auc</code>: قيمة الـ ROC AUC للفائز بعد إعادة تدريبه، على بيانات الاختبار.</li>\n</ol>\n","hints":["معاملات الـ pipeline صيغتها <code dir=\"ltr\">&lt;اسم الخطوة&gt;__&lt;المعامل&gt;</code>: وهنا <code dir=\"ltr\">knn__n_neighbors</code> و<code dir=\"ltr\">knn__weights</code>.","<code dir=\"ltr\">GridSearchCV(pipe, grid, cv=cv, scoring=&quot;roc_auc&quot;).fit(X_train, y_train)</code>","<code dir=\"ltr\">search.best_params_</code> و<code dir=\"ltr\">search.best_score_</code> و<code dir=\"ltr\">search.score(X_test, y_test)</code> (التي تستخدم مقياس البحث نفسه)."],"explanation":"<p>خمسة جيران عدد قليل جدًا: فكل تنبؤ يرتكز على حفنة من العملاء، والـ AUC نحو 0.75. وعند 25–35 جارًا يتحسّن الترتيب إلى نحو 0.79، ولا يكاد يختلف مخططا الترجيح. يحقق الفائز (35، uniform) قيمة 0.795 بالتحقق المتقاطع و0.785 على بيانات الاختبار: أقل قليلًا، كما هو متوقع من الأفضل بين عشر محاولات. وما زال متأخرًا بشيء يسير عن الانحدار اللوجستي، فيحتفظ النموذج الأبسط بمكانه.</p>\n","checkLabels":{"grid-names":"مفاتيح grid تستخدم البادئة knn__","searched":"جرّب search التركيبات العشر كلها مع ROC AUC","best":"best_params وbest_cv_auc مأخوذان من البحث","test-auc":"test_auc هي قيمة ROC AUC للفائز المُعاد تدريبه على بيانات الاختبار"}},"words":639,"readMinutes":4}