.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/model_selection/plot_likelihood_ratios.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. or to run this example in your browser via JupyterLite or Binder .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_model_selection_plot_likelihood_ratios.py: ============================================================= نسب الاحتمال الطبقي لقياس أداء التصنيف ============================================================= هذا المثال يوضح الدالة :func:`~sklearn.metrics.class_likelihood_ratios` والتي تقوم بحساب نسب الاحتمال الطبقي الإيجابية والسلبية (`LR+`, `LR-`) لتقييم القوة التنبؤية لمصنف ثنائي. كما سنرى، هذه المقاييس مستقلة عن نسبة التوازن بين الفئات في مجموعة الاختبار، مما يجعلها مفيدة للغاية عندما تختلف نسبة التوازن بين الفئات في البيانات المتاحة للدراسة عن نسبة التوازن في التطبيق المستهدف. الاستخدام النموذجي هو دراسة الحالة-المراقبة في الطب، والتي لديها توازن تقريبًا بين الفئات بينما يوجد اختلال كبير في التوازن بين الفئات في السكان بشكل عام. في مثل هذه التطبيقات، يمكن اختيار احتمالية ما قبل الاختبار لوجود حالة معينة لدى فرد ما لتكون هي نسبة الانتشار، أي نسبة السكان الذين يعانون من حالة طبية معينة. تمثل احتمالية ما بعد الاختبار عندئذٍ احتمالية وجود الحالة بالفعل نظرًا لنتيجة الاختبار الإيجابية. في هذا المثال، نناقش أولاً العلاقة بين احتمالية ما قبل الاختبار واحتمالية ما بعد الاختبار والتي تعطى بواسطة :ref:`class_likelihood_ratios`. ثم نقيم سلوكها في بعض السيناريوهات الخاضعة للتحكم. في القسم الأخير، نرسمها كدالة لنسبة انتشار الفئة الإيجابية. .. GENERATED FROM PYTHON SOURCE LINES 24-28 .. code-block:: Python # المؤلفون: مطوري scikit-learn # معرف الترخيص: BSD-3-Clause .. GENERATED FROM PYTHON SOURCE LINES 29-36 تحليل ما قبل الاختبار مقابل ما بعد الاختبار =============================== لنفترض أن لدينا مجموعة من السكان مع قياسات فيزيولوجية `X` والتي يمكن أن تكون مؤشرات حيوية غير مباشرة للمرض ومؤشرات حقيقية للمرض `y` (الحقيقة الأرضية). معظم الناس في السكان لا يحملون المرض ولكن أقلية (في هذه الحالة حوالي 10٪) تفعل ذلك: .. GENERATED FROM PYTHON SOURCE LINES 36-42 .. code-block:: Python from sklearn.datasets import make_classification X, y = make_classification(n_samples=10_000, weights=[0.9, 0.1], random_state=0) print(f"نسبة الأشخاص الذين يحملون المرض: {100*y.mean():.2f}%") .. rst-class:: sphx-glr-script-out .. code-block:: none نسبة الأشخاص الذين يحملون المرض: 10.37% .. GENERATED FROM PYTHON SOURCE LINES 43-46 يتم بناء نموذج تعلم آلي لتشخيص ما إذا كان الشخص مع بعض القياسات الفيزيولوجية من المرجح أن يحمل المرض محل الاهتمام. لتقييم النموذج، نحتاج إلى تقييم أدائه على مجموعة اختبار محجوزة: .. GENERATED FROM PYTHON SOURCE LINES 46-51 .. code-block:: Python from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) .. GENERATED FROM PYTHON SOURCE LINES 52-54 بعد ذلك يمكننا ملاءمة نموذج التشخيص لدينا وحساب نسبة الاحتمال الطبقي الإيجابية لتقييم فائدة هذا المصنف كأداة لتشخيص المرض: .. GENERATED FROM PYTHON SOURCE LINES 54-63 .. code-block:: Python from sklearn.linear_model import LogisticRegression from sklearn.metrics import class_likelihood_ratios estimator = LogisticRegression().fit(X_train, y_train) y_pred = estimator.predict(X_test) pos_LR, neg_LR = class_likelihood_ratios(y_test, y_pred) print(f"LR+: {pos_LR:.3f}") .. rst-class:: sphx-glr-script-out .. code-block:: none LR+: 12.617 .. GENERATED FROM PYTHON SOURCE LINES 64-73 بما أن نسبة الاحتمال الطبقي الإيجابية أكبر بكثير من 1.0، فهذا يعني أن أداة التشخيص القائمة على التعلم الآلي مفيدة: احتمالية ما بعد الاختبار أن الحالة موجودة بالفعل نظرًا لنتيجة الاختبار الإيجابية أكبر من 12 مرة من احتمالية ما قبل الاختبار. التحقق المتقاطع لنسب الاحتمال الطبقي ===================================== نقيم تباين القياسات لنسب الاحتمال الطبقي في بعض الحالات الخاصة. .. GENERATED FROM PYTHON SOURCE LINES 73-93 .. code-block:: Python import pandas as pd def scoring(estimator, X, y): y_pred = estimator.predict(X) pos_lr, neg_lr = class_likelihood_ratios(y, y_pred, raise_warning=False) return {"positive_likelihood_ratio": pos_lr, "negative_likelihood_ratio": neg_lr} def extract_score(cv_results): lr = pd.DataFrame( { "positive": cv_results["test_positive_likelihood_ratio"], "negative": cv_results["test_negative_likelihood_ratio"], } ) return lr.aggregate(["mean", "std"]) .. GENERATED FROM PYTHON SOURCE LINES 94-96 نقوم أولاً بالتحقق من نموذج :class:`~sklearn.linear_model.LogisticRegression` مع معاملات افتراضية كما هو مستخدم في القسم السابق. .. GENERATED FROM PYTHON SOURCE LINES 96-102 .. code-block:: Python from sklearn.model_selection import cross_validate estimator = LogisticRegression() extract_score(cross_validate(estimator, X, y, scoring=scoring, cv=10)) .. raw:: html
positive negative
mean 16.661086 0.724702
std 4.383973 0.054045


.. GENERATED FROM PYTHON SOURCE LINES 103-109 نؤكد أن النموذج مفيد: احتمالية ما بعد الاختبار أكبر من 12 إلى 20 مرة من احتمالية ما قبل الاختبار. على العكس، لنفترض نموذجًا وهميًا سيخرج تنبؤات عشوائية مع احتمالات مماثلة لمتوسط انتشار المرض في مجموعة التدريب: .. GENERATED FROM PYTHON SOURCE LINES 109-115 .. code-block:: Python from sklearn.dummy import DummyClassifier estimator = DummyClassifier(strategy="stratified", random_state=1234) extract_score(cross_validate(estimator, X, y, scoring=scoring, cv=10)) .. raw:: html
positive negative
mean 1.108843 0.986989
std 0.268147 0.034278


.. GENERATED FROM PYTHON SOURCE LINES 116-121 هنا كلتا نسبتي الاحتمال الطبقي متوافقتان مع 1.0 مما يجعل هذا المصنف عديم الفائدة كأداة تشخيصية لتحسين اكتشاف المرض. خيار آخر للنموذج الوهمي هو التنبؤ دائمًا بالفئة الأكثر تكرارًا، والتي في هذه الحالة هي "عدم وجود مرض". .. GENERATED FROM PYTHON SOURCE LINES 121-125 .. code-block:: Python estimator = DummyClassifier(strategy="most_frequent") extract_score(cross_validate(estimator, X, y, scoring=scoring, cv=10)) .. raw:: html
positive negative
mean NaN 1.0
std NaN 0.0


.. GENERATED FROM PYTHON SOURCE LINES 126-141 عدم وجود تنبؤات إيجابية يعني أنه لن يكون هناك تنبؤات صحيحة ولا تنبؤات خاطئة، مما يؤدي إلى نسبة احتمالية طبقية إيجابية غير محددة `LR+` والتي لا ينبغي بأي حال تفسيرها كنسبة احتمالية طبقية إيجابية لا نهائية (المصنف يحدد الحالات الإيجابية بشكل مثالي). في مثل هذه الحالة، تقوم الدالة :func:`~sklearn.metrics.class_likelihood_ratios` بإرجاع `nan` وإظهار تحذير بشكل افتراضي. في الواقع، تساعدنا قيمة `LR-` على استبعاد هذا النموذج. قد ينشأ سيناريو مشابه عند التحقق المتقاطع لبيانات غير متوازنة للغاية مع عدد قليل من العينات: بعض الطيات لن يكون لديها عينات مع المرض وبالتالي لن تخرج تنبؤات صحيحة ولا تنبؤات خاطئة عند استخدامها للاختبار. رياضيًا، هذا يؤدي إلى نسبة احتمالية طبقية إيجابية لا نهائية، والتي لا ينبغي أيضًا تفسيرها على أنها النموذج الذي يحدد الحالات الإيجابية بشكل مثالي. مثل هذا الحدث يؤدي إلى تباين أعلى لنسب الاحتمال الطبقي المقدرة، ولكن يمكن تفسيرها على أنها زيادة في احتمالية ما بعد الاختبار لوجود الحالة. .. GENERATED FROM PYTHON SOURCE LINES 141-146 .. code-block:: Python estimator = LogisticRegression() X, y = make_classification(n_samples=300, weights=[0.9, 0.1], random_state=0) extract_score(cross_validate(estimator, X, y, scoring=scoring, cv=10)) .. raw:: html
positive negative
mean 17.8000 0.373333
std 8.5557 0.235430


.. GENERATED FROM PYTHON SOURCE LINES 147-164 الثبات فيما يتعلق بالانتشار ===================================== نسب الاحتمال الطبقي مستقلة عن انتشار المرض ويمكن استقراؤها بين السكان بغض النظر عن أي اختلال في التوازن بين الفئات، **طالما يتم تطبيق نفس النموذج على جميع السكان**. لاحظ أنه في الرسوم البيانية أدناه **حدود القرار ثابتة** (انظر :ref:`sphx_glr_auto_examples_svm_plot_separating_hyperplane_unbalanced.py` لدراسة حدود القرار للتوازن غير المتوازن بين الفئات). هنا نقوم بتدريب نموذج :class:`~sklearn.linear_model.LogisticRegression` أساسي على دراسة حالة-مراقبة مع انتشار 50٪. ثم يتم تقييمه على السكان مع انتشار متغير. نستخدم الدالة :func:`~sklearn.datasets.make_classification` لضمان أن عملية توليد البيانات هي نفسها كما هو موضح في الرسوم البيانية أدناه. التسمية `1` تقابل الفئة الإيجابية "المرض"، في حين أن التسمية `0` تقف على "عدم وجود مرض". .. GENERATED FROM PYTHON SOURCE LINES 164-190 .. code-block:: Python from collections import defaultdict import matplotlib.pyplot as plt import numpy as np from sklearn.inspection import DecisionBoundaryDisplay populations = defaultdict(list) common_params = { "n_samples": 10_000, "n_features": 2, "n_informative": 2, "n_redundant": 0, "random_state": 0, } weights = np.linspace(0.1, 0.8, 6) weights = weights[::-1] # ملاءمة وتقييم النموذج الأساسي على فئات متوازنة X, y = make_classification(**common_params, weights=[0.5, 0.5]) estimator = LogisticRegression().fit(X, y) lr_base = extract_score(cross_validate(estimator, X, y, scoring=scoring, cv=10)) pos_lr_base, pos_lr_base_std = lr_base["positive"].values neg_lr_base, neg_lr_base_std = lr_base["negative"].values .. GENERATED FROM PYTHON SOURCE LINES 191-194 سنعرض الآن حدود القرار لكل مستوى من مستويات الانتشار. لاحظ أننا نرسم فقط جزءًا من البيانات الأصلية لتقييم حدود القرار للنموذج الخطي بشكل أفضل. .. GENERATED FROM PYTHON SOURCE LINES 194-224 .. code-block:: Python fig, axs = plt.subplots(nrows=3, ncols=2, figsize=(15, 12)) for ax, (n, weight) in zip(axs.ravel(), enumerate(weights)): X, y = make_classification( **common_params, weights=[weight, 1 - weight], ) prevalence = y.mean() populations["prevalence"].append(prevalence) populations["X"].append(X) populations["y"].append(y) # تقليل العينات للرسم rng = np.random.RandomState(1) plot_indices = rng.choice(np.arange(X.shape[0]), size=500, replace=True) X_plot, y_plot = X[plot_indices], y[plot_indices] # رسم حدود القرار الثابتة للنموذج الأساسي مع انتشار متغير disp = DecisionBoundaryDisplay.from_estimator( estimator, X_plot, response_method="predict", alpha=0.5, ax=ax, ) scatter = disp.ax_.scatter(X_plot[:, 0], X_plot[:, 1], c=y_plot, edgecolor="k") disp.ax_.set_title(f"prevalence = {y_plot.mean():.2f}") disp.ax_.legend(*scatter.legend_elements()) .. image-sg:: /auto_examples/model_selection/images/sphx_glr_plot_likelihood_ratios_001.png :alt: prevalence = 0.22, prevalence = 0.34, prevalence = 0.45, prevalence = 0.60, prevalence = 0.76, prevalence = 0.88 :srcset: /auto_examples/model_selection/images/sphx_glr_plot_likelihood_ratios_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 225-226 نحدد دالة للتمهيد. .. GENERATED FROM PYTHON SOURCE LINES 226-241 .. code-block:: Python def scoring_on_bootstrap(estimator, X, y, rng, n_bootstrap=100): results_for_prevalence = defaultdict(list) for _ in range(n_bootstrap): bootstrap_indices = rng.choice( np.arange(X.shape[0]), size=X.shape[0], replace=True ) for key, value in scoring( estimator, X[bootstrap_indices], y[bootstrap_indices] ).items(): results_for_prevalence[key].append(value) return pd.DataFrame(results_for_prevalence) .. GENERATED FROM PYTHON SOURCE LINES 242-243 نقوم بتسجيل نقاط النموذج الأساسي لكل انتشار باستخدام التمهيد. .. GENERATED FROM PYTHON SOURCE LINES 243-263 .. code-block:: Python results = defaultdict(list) n_bootstrap = 100 rng = np.random.default_rng(seed=0) for prevalence, X, y in zip( populations["prevalence"], populations["X"], populations["y"] ): results_for_prevalence = scoring_on_bootstrap( estimator, X, y, rng, n_bootstrap=n_bootstrap ) results["prevalence"].append(prevalence) results["metrics"].append( results_for_prevalence.aggregate(["mean", "std"]).unstack() ) results = pd.DataFrame(results["metrics"], index=results["prevalence"]) results.index.name = "prevalence" results .. raw:: html
positive_likelihood_ratio negative_likelihood_ratio
mean std mean std
prevalence
0.2039 4.507943 0.113516 0.207667 0.009778
0.3419 4.443238 0.125140 0.198766 0.008915
0.4809 4.421087 0.123828 0.192913 0.006360
0.6196 4.409717 0.164009 0.193949 0.005861
0.7578 4.334795 0.175298 0.189267 0.005840
0.8963 4.197666 0.238955 0.185654 0.005027


.. GENERATED FROM PYTHON SOURCE LINES 264-266 في الرسوم البيانية أدناه، نلاحظ أن نسب الاحتمال الطبقي المعاد حسابها مع انتشار مختلف ثابتة ضمن انحراف معياري واحد من تلك المحسوبة على فئات متوازنة. .. GENERATED FROM PYTHON SOURCE LINES 266-320 .. code-block:: Python fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(15, 6)) results["positive_likelihood_ratio"]["mean"].plot( ax=ax1, color="r", label="extrapolation through populations" ) ax1.axhline(y=pos_lr_base + pos_lr_base_std, color="r", linestyle="--") ax1.axhline( y=pos_lr_base - pos_lr_base_std, color="r", linestyle="--", label="base model confidence band", ) ax1.fill_between( results.index, results["positive_likelihood_ratio"]["mean"] - results["positive_likelihood_ratio"]["std"], results["positive_likelihood_ratio"]["mean"] + results["positive_likelihood_ratio"]["std"], color="r", alpha=0.3, ) ax1.set( title="Positive likelihood ratio", ylabel="LR+", ylim=[0, 5], ) ax1.legend(loc="lower right") ax2 = results["negative_likelihood_ratio"]["mean"].plot( ax=ax2, color="b", label="extrapolation through populations" ) ax2.axhline(y=neg_lr_base + neg_lr_base_std, color="b", linestyle="--") ax2.axhline( y=neg_lr_base - neg_lr_base_std, color="b", linestyle="--", label="base model confidence band", ) ax2.fill_between( results.index, results["negative_likelihood_ratio"]["mean"] - results["negative_likelihood_ratio"]["std"], results["negative_likelihood_ratio"]["mean"] + results["negative_likelihood_ratio"]["std"], color="b", alpha=0.3, ) ax2.set( title="Negative likelihood ratio", ylabel="LR-", ylim=[0, 0.5], ) ax2.legend(loc="lower right") plt.show() .. image-sg:: /auto_examples/model_selection/images/sphx_glr_plot_likelihood_ratios_002.png :alt: Positive likelihood ratio, Negative likelihood ratio :srcset: /auto_examples/model_selection/images/sphx_glr_plot_likelihood_ratios_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.040 seconds) .. _sphx_glr_download_auto_examples_model_selection_plot_likelihood_ratios.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: binder-badge .. image:: images/binder_badge_logo.svg :target: https://mybinder.org/v2/gh/scikit-learn/scikit-learn/main?urlpath=lab/tree/notebooks/auto_examples/model_selection/plot_likelihood_ratios.ipynb :alt: Launch binder :width: 150 px .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../lite/lab/index.html?path=auto_examples/model_selection/plot_likelihood_ratios.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_likelihood_ratios.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_likelihood_ratios.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_likelihood_ratios.zip ` .. include:: plot_likelihood_ratios.recommendations .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_