.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/linear_model/plot_tweedie_regression_insurance_claims.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_linear_model_plot_tweedie_regression_insurance_claims.py: ====================================== انحدار تويدي على مطالبات التأمين ====================================== يوضح هذا المثال استخدام الانحدار الشعاعي، جاما وتويدي على `مجموعة بيانات مطالبات المسؤولية المدنية الفرنسية لطرف ثالث `_، مستوحى من درس تعليمي R [1]_. في هذه المجموعة من البيانات، يتوافق كل عينة مع بوليصة تأمين، أي عقد داخل شركة تأمين وفرد (حامل بوليصة التأمين). تتضمن الميزات المتاحة عمر السائق، وعمر السيارة، وقوة السيارة، وما إلى ذلك. بعض التعريفات: *المطالبة* هي الطلب الذي يقدمه حامل بوليصة التأمين إلى شركة التأمين لتعويض الخسارة التي يغطيها التأمين. *مبلغ المطالبة* هو مبلغ المال الذي يجب على شركة التأمين دفعه. *التعرض* هو مدة تغطية التأمين لسياسة معينة، بالسنوات. هنا هدفنا هو التنبؤ بالقيمة المتوقعة، أي المتوسط، لمبلغ المطالبة الإجمالي لكل وحدة تعرض، والتي يشار إليها أيضًا باسم القسط الصافي. هناك عدة إمكانيات للقيام بذلك، اثنان منها هما: 1. نمذجة عدد المطالبات بتوزيع شعاعي، ومتوسط مبلغ المطالبة لكل مطالبة، المعروف أيضًا باسم الشدة، كتوزيع جاما وضرب تنبؤات كل من أجل الحصول على مبلغ المطالبة الإجمالي. 2. نمذجة مبلغ المطالبة الإجمالي لكل تعرض مباشرةً، عادةً بتوزيع تويدي من تويدي بقوة :math:`p \in (1, 2)`. في هذا المثال، سنقوم بتوضيح كلا النهجين. نبدأ بتعريف بعض وظائف المساعدة لتحميل البيانات وتصور النتائج. .. [1] A. Noll, R. Salzmann and M.V. Wuthrich, Case Study: French Motor Third-Party Liability Claims (November 8, 2018). `doi:10.2139/ssrn.3164764 `_ .. GENERATED FROM PYTHON SOURCE LINES 33-36 .. code-block:: Python # المؤلفون: مطوري scikit-learn # معرف SPDX-License: BSD-3-Clause .. GENERATED FROM PYTHON SOURCE LINES 37-197 .. code-block:: Python from functools import partial import matplotlib.pyplot as plt import numpy as np import pandas as pd from sklearn.datasets import fetch_openml from sklearn.metrics import ( mean_absolute_error, mean_squared_error, mean_tweedie_deviance, ) def load_mtpl2(n_samples=None): """تحميل مجموعة بيانات مطالبات المسؤولية المدنية الفرنسية لطرف ثالث. المعلمات ---------- n_samples: int، default=None عدد العينات المراد تحديدها (لتشغيل وقت أسرع). تحتوي مجموعة البيانات الكاملة على 678013 عينة. """ # freMTPL2freq dataset from https://www.openml.org/d/41214 df_freq = fetch_openml(data_id=41214, as_frame=True).data df_freq["IDpol"] = df_freq["IDpol"].astype(int) df_freq.set_index("IDpol", inplace=True) # freMTPL2sev dataset from https://www.openml.org/d/41215 df_sev = fetch_openml(data_id=41215, as_frame=True).data # sum ClaimAmount over identical IDs df_sev = df_sev.groupby("IDpol").sum() df = df_freq.join(df_sev, how="left") df["ClaimAmount"] = df["ClaimAmount"].fillna(0) # unquote string fields for column_name in df.columns[[t is object for t in df.dtypes.values]]: df[column_name] = df[column_name].str.strip("'") return df.iloc[:n_samples] def plot_obs_pred( df, feature, weight, observed, predicted, y_label=None, title=None, ax=None, fill_legend=False, ): """رسم الملاحظ والمتوقع - مجمعة حسب مستوى الميزة. المعلمات ---------- df : DataFrame بيانات الإدخال الميزة: str اسم عمود df لميزة المراد رسمها الوزن : str اسم عمود df بقيم الأوزان أو التعرض الملاحظ : str اسم عمود df مع الهدف الملاحظ المتوقع : DataFrame جدول بيانات، بنفس فهرس df، مع الهدف المتوقع fill_legend : bool، default=False ما إذا كان سيتم عرض fill_between legend """ # تجميع المتغيرات الملاحظة والمتوقعة حسب مستوى الميزة df_ = df.loc[:, [feature, weight]].copy() df_["observed"] = df[observed] * df[weight] df_["predicted"] = predicted * df[weight] df_ = ( df_.groupby([feature])[[weight, "observed", "predicted"]] .sum() .assign(observed=lambda x: x["observed"] / x[weight]) .assign(predicted=lambda x: x["predicted"] / x[weight]) ) ax = df_.loc[:, ["observed", "predicted"]].plot(style=".", ax=ax) y_max = df_.loc[:, ["observed", "predicted"]].values.max() * 0.8 p2 = ax.fill_between( df_.index, 0, y_max * df_[weight] / df_[weight].values.max(), color="g", alpha=0.1, ) if fill_legend: ax.legend([p2], ["{} distribution".format(feature)]) ax.set( ylabel=y_label if y_label is not None else None, title=title if title is not None else "Train: Observed vs Predicted", ) def score_estimator( estimator, X_train, X_test, df_train, df_test, target, weights, tweedie_powers=None, ): """تقييم أداة تقدير على مجموعات التدريب والاختبار بمقاييس مختلفة""" metrics = [ ("D² explained", None), # استخدم scorer الافتراضي إذا كان موجودًا ("mean abs. error", mean_absolute_error), ("mean squared error", mean_squared_error), ] if tweedie_powers: metrics += [ ( "mean Tweedie dev p={:.4f}".format(power), partial(mean_tweedie_deviance, power=power), ) for power in tweedie_powers ] res = [] for subset_label, X, df in [ ("train", X_train, df_train), ("test", X_test, df_test), ]: y, _weights = df[target], df[weights] for score_label, metric in metrics: if isinstance(estimator, tuple) and len(estimator) == 2: # تسجيل نموذج يتكون من ناتج نموذج التردد # والشدة. est_freq, est_sev = estimator y_pred = est_freq.predict(X) * est_sev.predict(X) else: y_pred = estimator.predict(X) if metric is None: if not hasattr(estimator, "score"): continue score = estimator.score(X, y, sample_weight=_weights) else: score = metric(y, y_pred, sample_weight=_weights) res.append({"subset": subset_label, "metric": score_label, "score": score}) res = ( pd.DataFrame(res) .set_index(["metric", "subset"]) .score.unstack(-1) .round(4) .loc[:, ["train", "test"]] ) return res .. GENERATED FROM PYTHON SOURCE LINES 198-205 تحميل مجموعات البيانات، استخراج الميزات الأساسية وتعاريف الهدف ----------------------------------------------------------------- نحن نبني مجموعة بيانات freMTPL2 عن طريق الانضمام إلى جدول freMTPL2freq، تحتوي على عدد المطالبات (``ClaimNb``)، مع جدول freMTPL2sev، تحتوي على مبلغ المطالبة (``ClaimAmount``) لنفس معرفات السياسة (``IDpol``). .. GENERATED FROM PYTHON SOURCE LINES 205-263 .. code-block:: Python from sklearn.compose import ColumnTransformer from sklearn.pipeline import make_pipeline from sklearn.preprocessing import ( FunctionTransformer, KBinsDiscretizer, OneHotEncoder, StandardScaler, ) df = load_mtpl2() # تصحيح الملاحظات غير المعقولة (التي قد تكون خطأ في البيانات) # وبعض مبالغ المطالبات الكبيرة بشكل استثنائي df["ClaimNb"] = df["ClaimNb"].clip(upper=4) df["Exposure"] = df["Exposure"].clip(upper=1) df["ClaimAmount"] = df["ClaimAmount"].clip(upper=200000) # إذا كان مبلغ المطالبة 0، فلا نعتبره مطالبة. دالة الخسارة # المستخدمة بواسطة نموذج الشدة تتطلب مبالغ مطالبات إيجابية صارمة. بهذه الطريقة # التردد والشدة أكثر اتساقًا مع بعضهما البعض. df.loc[(df["ClaimAmount"] == 0) & (df["ClaimNb"] >= 1), "ClaimNb"] = 0 log_scale_transformer = make_pipeline( FunctionTransformer(func=np.log), StandardScaler() ) column_trans = ColumnTransformer( [ ( "binned_numeric", KBinsDiscretizer(n_bins=10, random_state=0), ["VehAge", "DrivAge"], ), ( "onehot_categorical", OneHotEncoder(), ["VehBrand", "VehPower", "VehGas", "Region", "Area"], ), ("passthrough_numeric", "passthrough", ["BonusMalus"]), ("log_scaled_numeric", log_scale_transformer, ["Density"]), ], remainder="drop", ) X = column_trans.fit_transform(df) # شركات التأمين مهتمة بنمذجة القسط الصافي، أي # مبلغ المطالبة الإجمالي المتوقع لكل وحدة من التعرض لكل حامل بوليصة في # محفظتهم: df["PurePremium"] = df["ClaimAmount"] / df["Exposure"] # يمكن تقريب هذا بشكل غير مباشر عن طريق النمذجة ذات الخطوتين: ناتج نموذج التردد # والشدة: df["Frequency"] = df["ClaimNb"] / df["Exposure"] df["AvgClaimAmount"] = df["ClaimAmount"] / np.fmax(df["ClaimNb"], 1) with pd.option_context("display.max_columns", 15): print(df[df.ClaimAmount > 0].head()) .. rst-class:: sphx-glr-script-out .. code-block:: none ClaimNb Exposure Area VehPower VehAge DrivAge BonusMalus VehBrand \ IDpol 139 1 0.75 F 7 1 61 50 B12 190 1 0.14 B 12 5 50 60 B12 414 1 0.14 E 4 0 36 85 B12 424 2 0.62 F 10 0 51 100 B12 463 1 0.31 A 5 0 45 50 B12 VehGas Density Region ClaimAmount PurePremium Frequency \ IDpol 139 'Regular' 27000 R11 303.00 404.000000 1.333333 190 'Diesel' 56 R25 1981.84 14156.000000 7.142857 414 'Regular' 4792 R11 1456.55 10403.928571 7.142857 424 'Regular' 27000 R11 10834.00 17474.193548 3.225806 463 'Regular' 12 R73 3986.67 12860.225806 3.225806 AvgClaimAmount IDpol 139 303.00 190 1981.84 414 1456.55 424 5417.00 463 3986.67 .. GENERATED FROM PYTHON SOURCE LINES 264-273 نموذج التردد - التوزيع الشعاعي --------------------------------------- عدد المطالبات (``ClaimNb``) هو عدد صحيح إيجابي (0 مدرج). وبالتالي، يمكن نمذجة هذا الهدف بتوزيع شعاعي. يفترض بعد ذلك أن يكون عدد الأحداث المنفصلة التي تحدث بمعدل ثابت في فترة زمنية معينة (``Exposure``، بوحدات السنوات). هنا نقوم بنمذجة التردد ``y = ClaimNb / Exposure``، والذي لا يزال (مقياس) توزيع شعاعي، واستخدام ``Exposure`` كـ `sample_weight`. .. GENERATED FROM PYTHON SOURCE LINES 274-279 .. code-block:: Python from sklearn.linear_model import PoissonRegressor from sklearn.model_selection import train_test_split df_train, df_test, X_train, X_test = train_test_split(df, X, random_state=0) .. GENERATED FROM PYTHON SOURCE LINES 280-283 دعنا نضع في اعتبارنا أنه على الرغم من العدد الكبير على ما يبدو من نقاط البيانات في هذه المجموعة من البيانات، فإن عدد نقاط التقييم التي يكون فيها مبلغ المطالبة غير صفري صغير جدًا: .. GENERATED FROM PYTHON SOURCE LINES 284-286 .. code-block:: Python len(df_test) .. rst-class:: sphx-glr-script-out .. code-block:: none 169504 .. GENERATED FROM PYTHON SOURCE LINES 287-289 .. code-block:: Python len(df_test[df_test["ClaimAmount"] > 0]) .. rst-class:: sphx-glr-script-out .. code-block:: none 6237 .. GENERATED FROM PYTHON SOURCE LINES 290-297 ونتيجة لذلك، نتوقع تقلبًا كبيرًا في تقييمنا عند إعادة أخذ العينات العشوائية للاختبار تقسيم. يتم تقدير معلمات النموذج عن طريق تقليل الانحراف الشعاعي على مجموعة التدريب عبر محدد نيوتن. بعض الميزات متوازية (على سبيل المثال لأننا لم نتخلص من أي مستوى فئوي في `OneHotEncoder`)، نستخدم ضعف L2 لتجنب المشكلات العددية. .. GENERATED FROM PYTHON SOURCE LINES 298-313 .. code-block:: Python glm_freq = PoissonRegressor(alpha=1e-4, solver="newton-cholesky") glm_freq.fit(X_train, df_train["Frequency"], sample_weight=df_train["Exposure"]) scores = score_estimator( glm_freq, X_train, X_test, df_train, df_test, target="Frequency", weights="Exposure", ) print("تقييم PoissonRegressor على الهدف Frequency") print(scores) .. rst-class:: sphx-glr-script-out .. code-block:: none تقييم PoissonRegressor على الهدف Frequency subset train test metric D² explained 0.0448 0.0427 mean abs. error 0.1379 0.1378 mean squared error 0.2441 0.2246 .. GENERATED FROM PYTHON SOURCE LINES 314-322 لاحظ أن النتيجة المقاسة على مجموعة الاختبار أفضل بشكل مدهش من على مجموعة التدريب. قد يكون هذا خاصًا بهذا التقسيم العشوائي للاختبار. التدريب. يمكن للتحقق الصحيح من الصحة أن يساعدنا في تقييم تقلب العينات لهذه النتائج. يمكننا مقارنة القيم الملاحظة والمتوقعة بصريًا، مجمعة حسب عمر السائق (``DrivAge``)، عمر السيارة (``VehAge``) و التأمين مكافأة/عقوبة (``BonusMalus``). .. GENERATED FROM PYTHON SOURCE LINES 323-375 .. code-block:: Python fig, ax = plt.subplots(ncols=2, nrows=2, figsize=(16, 8)) fig.subplots_adjust(hspace=0.3, wspace=0.2) plot_obs_pred( df=df_train, feature="DrivAge", weight="Exposure", observed="Frequency", predicted=glm_freq.predict(X_train), y_label="Claim Frequency", title="train data", ax=ax[0, 0], ) plot_obs_pred( df=df_test, feature="DrivAge", weight="Exposure", observed="Frequency", predicted=glm_freq.predict(X_test), y_label="Claim Frequency", title="test data", ax=ax[0, 1], fill_legend=True, ) plot_obs_pred( df=df_test, feature="VehAge", weight="Exposure", observed="Frequency", predicted=glm_freq.predict(X_test), y_label="Claim Frequency", title="test data", ax=ax[1, 0], fill_legend=True, ) plot_obs_pred( df=df_test, feature="BonusMalus", weight="Exposure", observed="Frequency", predicted=glm_freq.predict(X_test), y_label="Claim Frequency", title="test data", ax=ax[1, 1], fill_legend=True, ) .. image-sg:: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_001.png :alt: train data, test data, test data, test data :srcset: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 376-393 وفقًا للبيانات المرصودة، يكون معدل الحوادث أعلى بالنسبة للسائقين الذين تقل أعمارهم عن 30 عامًا، وهو مرتبط بشكل إيجابي بمتغير `BonusMalus`. نموذجنا قادر على نمذجة هذا السلوك بشكل صحيح في الغالب. نموذج الشدة - توزيع جاما ------------------------------------ يمكن إظهار أن متوسط ​​مبلغ المطالبة أو الشدة (`AvgClaimAmount`) يتبع تجريبيًا توزيع جاما تقريبًا. نقوم بملاءمة نموذج GLM للحدة بنفس ميزات نموذج التردد. ملاحظة: - نقوم بتصفية ``ClaimAmount == 0`` حيث أن توزيع جاما مدعوم على :math:`(0, \infty)`، وليس :math:`[0, \infty)`. - نستخدم ``ClaimNb`` كـ `sample_weight` لحساب السياسات التي تحتوي على أكثر من مطالبة واحدة. .. GENERATED FROM PYTHON SOURCE LINES 393-419 .. code-block:: Python from sklearn.linear_model import GammaRegressor mask_train = df_train["ClaimAmount"] > 0 mask_test = df_test["ClaimAmount"] > 0 glm_sev = GammaRegressor(alpha=10.0, solver="newton-cholesky") glm_sev.fit( X_train[mask_train.values], df_train.loc[mask_train, "AvgClaimAmount"], sample_weight=df_train.loc[mask_train, "ClaimNb"], ) scores = score_estimator( glm_sev, X_train[mask_train.values], X_test[mask_test.values], df_train[mask_train], df_test[mask_test], target="AvgClaimAmount", weights="ClaimNb", ) print("تقييم GammaRegressor على الهدف AvgClaimAmount") print(scores) .. rst-class:: sphx-glr-script-out .. code-block:: none تقييم GammaRegressor على الهدف AvgClaimAmount subset train test metric D² explained 3.900000e-03 4.400000e-03 mean abs. error 1.756746e+03 1.744042e+03 mean squared error 5.801770e+07 5.030677e+07 .. GENERATED FROM PYTHON SOURCE LINES 420-424 هذه القيم للمقاييس ليست بالضرورة سهلة التفسير. قد يكون من المفيد مقارنتها بنموذج لا يستخدم أي ميزات إدخال ويتنبأ دائمًا بقيمة ثابتة، أي متوسط ​​مبلغ المطالبة، في نفس الإعداد: .. GENERATED FROM PYTHON SOURCE LINES 425-447 .. code-block:: Python from sklearn.dummy import DummyRegressor dummy_sev = DummyRegressor(strategy="mean") dummy_sev.fit( X_train[mask_train.values], df_train.loc[mask_train, "AvgClaimAmount"], sample_weight=df_train.loc[mask_train, "ClaimNb"], ) scores = score_estimator( dummy_sev, X_train[mask_train.values], X_test[mask_test.values], df_train[mask_train], df_test[mask_test], target="AvgClaimAmount", weights="ClaimNb", ) print("تقييم متنبئ متوسط ​​على الهدف AvgClaimAmount") print(scores) .. rst-class:: sphx-glr-script-out .. code-block:: none تقييم متنبئ متوسط ​​على الهدف AvgClaimAmount subset train test metric D² explained 0.000000e+00 -0.000000e+00 mean abs. error 1.756687e+03 1.744497e+03 mean squared error 5.803882e+07 5.033764e+07 .. GENERATED FROM PYTHON SOURCE LINES 448-457 نستنتج أن مبلغ المطالبة من الصعب جدًا التنبؤ به. ومع ذلك، فإن :class:`~sklearn.linear_model.GammaRegressor` قادر على الاستفادة من بعض المعلومات من ميزات الإدخال لتحسين خط الأساس المتوسط ​​قليلاً من حيث D². لاحظ أن النموذج الناتج هو متوسط ​​مبلغ المطالبة لكل مطالبة. على هذا النحو، فهو مشروط بوجود مطالبة واحدة على الأقل، ولا يمكن استخدامه للتنبؤ بمتوسط ​​مبلغ المطالبة لكل سياسة. لهذا، يجب دمجه مع نموذج لتكرار المطالبات. .. GENERATED FROM PYTHON SOURCE LINES 458-478 .. code-block:: Python print( "متوسط ​​مبلغ AvgClaim لكل سياسة: %.2f " % df_train["AvgClaimAmount"].mean() ) print( "متوسط ​​مبلغ AvgClaim | NbClaim > 0: %.2f" % df_train["AvgClaimAmount"][df_train["AvgClaimAmount"] > 0].mean() ) print( "متوسط ​​مبلغ AvgClaim المتوقع | NbClaim > 0: %.2f" % glm_sev.predict(X_train).mean() ) print( "متوسط ​​مبلغ AvgClaim المتوقع (وهمي) | NbClaim > 0: %.2f" % dummy_sev.predict(X_train).mean() ) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​مبلغ AvgClaim لكل سياسة: 71.78 متوسط ​​مبلغ AvgClaim | NbClaim > 0: 1951.21 متوسط ​​مبلغ AvgClaim المتوقع | NbClaim > 0: 1940.95 متوسط ​​مبلغ AvgClaim المتوقع (وهمي) | NbClaim > 0: 1978.59 .. GENERATED FROM PYTHON SOURCE LINES 479-481 يمكننا مقارنة القيم المرصودة والمتوقعة بصريًا، مجمعة لعمر السائقين (``DrivAge``). .. GENERATED FROM PYTHON SOURCE LINES 481-508 .. code-block:: Python fig, ax = plt.subplots(ncols=1, nrows=2, figsize=(16, 6)) plot_obs_pred( df=df_train.loc[mask_train], feature="DrivAge", weight="Exposure", observed="AvgClaimAmount", predicted=glm_sev.predict(X_train[mask_train.values]), y_label="متوسط ​​حدة المطالبة", title="بيانات التدريب", ax=ax[0], ) plot_obs_pred( df=df_test.loc[mask_test], feature="DrivAge", weight="Exposure", observed="AvgClaimAmount", predicted=glm_sev.predict(X_test[mask_test.values]), y_label="متوسط ​​حدة المطالبة", title="بيانات الاختبار", ax=ax[1], fill_legend=True, ) plt.tight_layout() .. image-sg:: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_002.png :alt: بيانات التدريب, بيانات الاختبار :srcset: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 509-538 بشكل عام، يكون لعمر السائقين (``DrivAge``) تأثير ضعيف على حدة المطالبة، سواء في البيانات المرصودة أو المتوقعة. نمذجة القسط الخالص عبر نموذج المنتج مقابل TweedieRegressor واحد -------------------------------------------------------------------- كما هو مذكور في المقدمة، يمكن نمذجة إجمالي مبلغ المطالبة لكل وحدة تعرض على أنه حاصل ضرب تنبؤ نموذج التردد في تنبؤ نموذج الشدة. بدلاً من ذلك، يمكن للمرء نمذجة الخسارة الإجمالية مباشرة باستخدام نموذج خطي معمم مركب Poisson Gamma فريد (مع دالة ربط لوغاريتمي). هذا النموذج هو حالة خاصة من Tweedie GLM مع معلمة "قوة" :math:`p \in (1, 2)`. هنا، نقوم بتثبيت معلمة `power` لنموذج Tweedie مسبقًا على قيمة عشوائية (1.9) في النطاق الصحيح. من الناحية المثالية، سيختار المرء هذه القيمة عبر البحث الشبكي عن طريق تقليل احتمالية السجل السالب لنموذج Tweedie، لكن لسوء الحظ، لا يسمح التطبيق الحالي بذلك (حتى الآن). سنقارن أداء كلا النهجين. لتحديد أداء كلا النموذجين كميًا، يمكن للمرء حساب متوسط ​​انحراف بيانات التدريب والاختبار بافتراض توزيع مركب Poisson-Gamma لإجمالي مبلغ المطالبة. هذا يعادل توزيع Tweedie مع معلمة `power` بين 1 و 2. تعتمد :func:`sklearn.metrics.mean_tweedie_deviance` على معلمة `power`. نظرًا لأننا لا نعرف القيمة الحقيقية لمعلمة `power`، فإننا هنا نحسب متوسط ​​الانحرافات لشبكة من القيم الممكنة، ونقارن النماذج جنبًا إلى جنب، أي أننا نقارنها بقيم متطابقة لـ `power`. من الناحية المثالية، نأمل أن يكون أحد النماذج أفضل باستمرار من الآخر، بغض النظر عن `power`. .. GENERATED FROM PYTHON SOURCE LINES 538-582 .. code-block:: Python from sklearn.linear_model import TweedieRegressor glm_pure_premium = TweedieRegressor(power=1.9, alpha=0.1, solver="newton-cholesky") glm_pure_premium.fit( X_train, df_train["PurePremium"], sample_weight=df_train["Exposure"] ) tweedie_powers = [1.5, 1.7, 1.8, 1.9, 1.99, 1.999, 1.9999] scores_product_model = score_estimator( (glm_freq, glm_sev), X_train, X_test, df_train, df_test, target="PurePremium", weights="Exposure", tweedie_powers=tweedie_powers, ) scores_glm_pure_premium = score_estimator( glm_pure_premium, X_train, X_test, df_train, df_test, target="PurePremium", weights="Exposure", tweedie_powers=tweedie_powers, ) scores = pd.concat( [scores_product_model, scores_glm_pure_premium], axis=1, sort=True, keys=("نموذج المنتج", "TweedieRegressor"), ) print( "تقييم نموذج المنتج و Tweedie Regressor على الهدف PurePremium" ) with pd.option_context("display.expand_frame_repr", False): print(scores) .. rst-class:: sphx-glr-script-out .. code-block:: none تقييم نموذج المنتج و Tweedie Regressor على الهدف PurePremium نموذج المنتج TweedieRegressor subset train test train test metric D² explained NaN NaN 1.640000e-02 1.370000e-02 mean Tweedie dev p=1.5000 7.669930e+01 7.617050e+01 7.640770e+01 7.640880e+01 mean Tweedie dev p=1.7000 3.695740e+01 3.683980e+01 3.682880e+01 3.692270e+01 mean Tweedie dev p=1.8000 3.046010e+01 3.040530e+01 3.037600e+01 3.045390e+01 mean Tweedie dev p=1.9000 3.387580e+01 3.385000e+01 3.382120e+01 3.387830e+01 mean Tweedie dev p=1.9900 2.015716e+02 2.015414e+02 2.015347e+02 2.015587e+02 mean Tweedie dev p=1.9990 1.914573e+03 1.914370e+03 1.914538e+03 1.914387e+03 mean Tweedie dev p=1.9999 1.904751e+04 1.904556e+04 1.904747e+04 1.904558e+04 mean abs. error 2.730119e+02 2.722128e+02 2.739865e+02 2.731249e+02 mean squared error 3.295040e+07 3.212197e+07 3.295505e+07 3.213056e+07 .. GENERATED FROM PYTHON SOURCE LINES 583-591 في هذا المثال، ينتج عن كلا النهجين للنمذجة مقاييس أداء قابلة للمقارنة. لأسباب تتعلق بالتنفيذ، فإن نسبة التباين الموضحة :math:`D^2` غير متاحة لنموذج المنتج. يمكننا بالإضافة إلى ذلك التحقق من صحة هذه النماذج من خلال مقارنة إجمالي مبلغ المطالبة المرصود والمتوقع على مجموعات بيانات الاختبار والتدريب الفرعية. نرى أنه في المتوسط​​، يميل كلا النموذجين إلى التقليل من شأن إجمالي المطالبة (لكن هذا السلوك يعتمد على مقدار التنظيم). .. GENERATED FROM PYTHON SOURCE LINES 591-613 .. code-block:: Python res = [] for subset_label, X, df in [ ("train", X_train, df_train), ("test", X_test, df_test), ]: exposure = df["Exposure"].values res.append( { "subset": subset_label, "observed": df["ClaimAmount"].values.sum(), "predicted, frequency*severity model": np.sum( exposure * glm_freq.predict(X) * glm_sev.predict(X) ), "predicted, tweedie, power=%.2f" % glm_pure_premium.power: np.sum(exposure * glm_pure_premium.predict(X)), } ) print(pd.DataFrame(res).set_index("subset").T) .. rst-class:: sphx-glr-script-out .. code-block:: none subset train test observed 3.917618e+07 1.299546e+07 predicted, frequency*severity model 3.916555e+07 1.313276e+07 predicted, tweedie, power=1.90 3.951751e+07 1.325198e+07 .. GENERATED FROM PYTHON SOURCE LINES 614-641 أخيرًا، يمكننا مقارنة النموذجين باستخدام مخطط المطالبات التراكمية: لكل نموذج، يتم تصنيف حاملي وثائق التأمين من الأكثر أمانًا إلى الأكثر خطورة بناءً على تنبؤات النموذج ويتم رسم جزء من إجمالي المطالبات التراكمية المرصودة على المحور ص. غالبًا ما يُطلق على هذا الرسم البياني منحنى لورنز المرتب للنموذج. يمكن استخدام معامل جيني (بناءً على المساحة بين المنحنى والقطر) كمقياس لاختيار النموذج لتحديد قدرة النموذج على تصنيف حاملي وثائق التأمين. لاحظ أن هذا المقياس لا يعكس قدرة النماذج على إجراء تنبؤات دقيقة من حيث القيمة المطلقة لإجمالي مبالغ المطالبات ولكن فقط من حيث الكميات النسبية كمقياس تصنيف. يكون معامل جيني محددًا بحد أقصى قدره 1.0 ولكن حتى نموذج أوراكل يصنف حاملي وثائق التأمين حسب مبالغ المطالبات المرصودة لا يمكنه الوصول إلى درجة 1.0. نلاحظ أن كلا النموذجين قادران على تصنيف حاملي وثائق التأمين حسب الخطورة بشكل أفضل بكثير من الصدفة على الرغم من أنهما بعيدان أيضًا عن نموذج أوراكل نظرًا لصعوبة مشكلة التنبؤ الطبيعية من عدد قليل من الميزات: معظم الحوادث لا يمكن التنبؤ بها ويمكن أن تكون ناجمة عن ظروف بيئية غير موصوفة على الإطلاق بواسطة ميزات الإدخال للنماذج. لاحظ أن مؤشر جيني يميز فقط أداء تصنيف النموذج ولكن ليس معايرته: أي تحويل رتيب للتنبؤات يترك مؤشر جيني للنموذج دون تغيير. أخيرًا، ينبغي للمرء أن يؤكد أن نموذج جاما Poisson المركب الذي يتم ملاءمته مباشرة على القسط الخالص هو أبسط من الناحية التشغيلية للتطوير والصيانة لأنه يتكون من مقدر scikit-learn واحد بدلاً من زوج من النماذج، لكل منها مجموعته الخاصة من المعلمات الفائقة. .. GENERATED FROM PYTHON SOURCE LINES 642-693 .. code-block:: Python from sklearn.metrics import auc def lorenz_curve(y_true, y_pred, exposure): y_true, y_pred = np.asarray(y_true), np.asarray(y_pred) exposure = np.asarray(exposure) # ترتيب العينات عن طريق زيادة المخاطر المتوقعة: ranking = np.argsort(y_pred) ranked_exposure = exposure[ranking] ranked_pure_premium = y_true[ranking] cumulated_claim_amount = np.cumsum(ranked_pure_premium * ranked_exposure) cumulated_claim_amount /= cumulated_claim_amount[-1] cumulated_samples = np.linspace(0, 1, len(cumulated_claim_amount)) return cumulated_samples, cumulated_claim_amount fig, ax = plt.subplots(figsize=(8, 8)) y_pred_product = glm_freq.predict(X_test) * glm_sev.predict(X_test) y_pred_total = glm_pure_premium.predict(X_test) for label, y_pred in [ ("نموذج التردد * الشدة", y_pred_product), ("جاما بواسون المركب", y_pred_total), ]: ordered_samples, cum_claims = lorenz_curve( df_test["PurePremium"], y_pred, df_test["Exposure"] ) gini = 1 - 2 * auc(ordered_samples, cum_claims) label += " (مؤشر جيني: {:.3f})".format(gini) ax.plot(ordered_samples, cum_claims, linestyle="-", label=label) # نموذج أوراكل: y_pred == y_test ordered_samples, cum_claims = lorenz_curve( df_test["PurePremium"], df_test["PurePremium"], df_test["Exposure"] ) gini = 1 - 2 * auc(ordered_samples, cum_claims) label = "أوراكل (مؤشر جيني: {:.3f})".format(gini) ax.plot(ordered_samples, cum_claims, linestyle="-.", color="gray", label=label) # خط أساس عشوائي ax.plot([0, 1], [0, 1], linestyle="--", color="black", label="خط أساس عشوائي") ax.set( title="منحنيات لورنز", xlabel="جزء من حاملي وثائق التأمين\n(مرتب حسب النموذج من الأكثر أمانًا إلى الأكثر خطورة)", ylabel="جزء من إجمالي مبلغ المطالبة", ) ax.legend(loc="upper left") plt.plot() .. image-sg:: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_003.png :alt: منحنيات لورنز :srcset: /auto_examples/linear_model/images/sphx_glr_plot_tweedie_regression_insurance_claims_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none [] .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 9.881 seconds) .. _sphx_glr_download_auto_examples_linear_model_plot_tweedie_regression_insurance_claims.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/linear_model/plot_tweedie_regression_insurance_claims.ipynb :alt: Launch binder :width: 150 px .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../lite/lab/index.html?path=auto_examples/linear_model/plot_tweedie_regression_insurance_claims.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_tweedie_regression_insurance_claims.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_tweedie_regression_insurance_claims.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_tweedie_regression_insurance_claims.zip ` .. include:: plot_tweedie_regression_insurance_claims.recommendations .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_