.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/applications/plot_cyclical_feature_engineering.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_applications_plot_cyclical_feature_engineering.py: ================================ هندسة الميزات ذات الصلة بالوقت ================================ يُقدم هذا الدفتر طرقًا مختلفة للاستفادة من الميزات ذات الصلة بالوقت لمهمة انحدار طلب مشاركة الدراجات التي تعتمد بشكل كبير على دورات العمل (الأيام، والأسابيع، والشهور) ودورات المواسم السنوية. في هذه العملية، نُقدم كيفية إجراء هندسة الميزات الدورية باستخدام فئة :class:`sklearn.preprocessing.SplineTransformer` وخيار `extrapolation="periodic"` الخاص بها. .. GENERATED FROM PYTHON SOURCE LINES 15-19 .. code-block:: Python # المؤلفون: مطورو scikit-learn # مُعرِّف ترخيص SPDX: BSD-3-Clause .. GENERATED FROM PYTHON SOURCE LINES 20-24 استكشاف البيانات على مجموعة بيانات طلب مشاركة الدراجات --------------------------------------------------- نبدأ بتحميل البيانات من مستودع OpenML. .. GENERATED FROM PYTHON SOURCE LINES 24-44 .. code-block:: Python from sklearn.kernel_approximation import Nystroem from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import FeatureUnion from sklearn.preprocessing import SplineTransformer import pandas as pd from sklearn.preprocessing import FunctionTransformer from sklearn.preprocessing import MinMaxScaler, OneHotEncoder from sklearn.linear_model import RidgeCV import numpy as np from sklearn.pipeline import make_pipeline from sklearn.model_selection import cross_validate from sklearn.ensemble import HistGradientBoostingRegressor from sklearn.compose import ColumnTransformer from sklearn.model_selection import TimeSeriesSplit import matplotlib.pyplot as plt from sklearn.datasets import fetch_openml bike_sharing = fetch_openml("Bike_Sharing_Demand", version=2, as_frame=True) df = bike_sharing.frame .. GENERATED FROM PYTHON SOURCE LINES 45-52 للحصول على فهم سريع للأنماط الدورية للبيانات، دعونا نلقي نظرة على متوسط ​​الطلب في الساعة خلال الأسبوع. لاحظ أن الأسبوع يبدأ يوم الأحد، خلال عطلة نهاية الأسبوع. يمكننا بوضوح تمييز أنماط التنقل في الصباح والمساء من أيام العمل واستخدام الدراجات الترفيهي في عطلات نهاية الأسبوع مع ذروة طلب أكثر انتشارًا في منتصف الأيام: .. GENERATED FROM PYTHON SOURCE LINES 52-65 .. code-block:: Python fig, ax = plt.subplots(figsize=(12, 4)) average_week_demand = df.groupby(["weekday", "hour"])["count"].mean() average_week_demand.plot(ax=ax) _ = ax.set( title="متوسط ​​طلب الدراجات بالساعة خلال الأسبوع", xticks=[i * 24 for i in range(7)], xticklabels=["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"], xlabel="وقت الأسبوع", ylabel="عدد تأجيرات الدراجات", ) .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_001.png :alt: متوسط ​​طلب الدراجات بالساعة خلال الأسبوع :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 66-68 هدف مشكلة التنبؤ هو العدد المطلق لتأجيرات الدراجات على أساس كل ساعة: .. GENERATED FROM PYTHON SOURCE LINES 69-71 .. code-block:: Python df["count"].max() .. rst-class:: sphx-glr-script-out .. code-block:: none 977 .. GENERATED FROM PYTHON SOURCE LINES 72-87 دعونا نعيد قياس متغير الهدف (عدد تأجيرات الدراجات بالساعة) للتنبؤ بطلب نسبي بحيث يكون من السهل تفسير متوسط ​​الخطأ المطلق كجزء بسيط من الحد الأقصى للطلب. .. note:: يقلل أسلوب الملاءمة للنماذج المستخدمة في هذا الدفتر جميعًا من متوسط ​​الخطأ التربيعي لتقدير المتوسط ​​الشرطي. ومع ذلك، سيُقدِّر الخطأ المطلق الوسيط الشرطي. ومع ذلك، عند الإبلاغ عن مقاييس الأداء على مجموعة الاختبار في المناقشة، نختار التركيز على متوسط ​​الخطأ المطلق بدلاً من متوسط ​​الخطأ التربيعي (الجذر) لأنه من الأسهل تفسيرها. لاحظ، مع ذلك، أنه في هذه الدراسة، فإن أفضل النماذج لمقياس واحد هي أيضًا الأفضل من حيث المقياس الآخر. .. GENERATED FROM PYTHON SOURCE LINES 88-91 .. code-block:: Python y = df["count"] / df["count"].max() .. GENERATED FROM PYTHON SOURCE LINES 92-100 .. code-block:: Python fig, ax = plt.subplots(figsize=(12, 4)) y.hist(bins=30, ax=ax) _ = ax.set( xlabel="جزء بسيط من طلب أسطول التأجير", ylabel="عدد الساعات", ) .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_002.png :alt: plot cyclical feature engineering :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 101-106 إطار بيانات ميزة الإدخال هو سجل كل ساعة بعلامات زمنية للمتغيرات التي تصف أحوال الطقس. يتضمن كلاً من المتغيرات الرقمية والفئوية. لاحظ أنه قد تم بالفعل توسيع معلومات الوقت إلى عدة أعمدة تكميلية. .. GENERATED FROM PYTHON SOURCE LINES 106-109 .. code-block:: Python X = df.drop("count", axis="columns") X .. raw:: html
season year month hour holiday weekday workingday weather temp feel_temp humidity windspeed
0 spring 0 1 0 False 6 False clear 9.84 14.395 0.81 0.0000
1 spring 0 1 1 False 6 False clear 9.02 13.635 0.80 0.0000
2 spring 0 1 2 False 6 False clear 9.02 13.635 0.80 0.0000
3 spring 0 1 3 False 6 False clear 9.84 14.395 0.75 0.0000
4 spring 0 1 4 False 6 False clear 9.84 14.395 0.75 0.0000
... ... ... ... ... ... ... ... ... ... ... ... ...
17374 spring 1 12 19 False 1 True misty 10.66 12.880 0.60 11.0014
17375 spring 1 12 20 False 1 True misty 10.66 12.880 0.60 11.0014
17376 spring 1 12 21 False 1 True clear 10.66 12.880 0.60 11.0014
17377 spring 1 12 22 False 1 True clear 10.66 13.635 0.56 8.9981
17378 spring 1 12 23 False 1 True clear 10.66 13.635 0.65 8.9981

17379 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 110-120 .. note:: إذا كانت معلومات الوقت موجودة فقط كعمود تاريخ أو عمود تاريخ ووقت، فكان من الممكن توسيعها إلى ساعة في اليوم، ويوم في الأسبوع، ويوم في الشهر، وشهر في السنة باستخدام pandas: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#time-date-components نستعرض الآن توزيع المتغيرات الفئوية، بدءًا من `"weather"`: .. GENERATED FROM PYTHON SOURCE LINES 120-123 .. code-block:: Python X["weather"].value_counts() .. rst-class:: sphx-glr-script-out .. code-block:: none weather clear 11413 misty 4544 rain 1419 heavy_rain 3 Name: count, dtype: int64 .. GENERATED FROM PYTHON SOURCE LINES 124-128 نظرًا لوجود 3 أحداث `"heavy_rain"` فقط، لا يمكننا استخدام هذه الفئة لـ تدريب نماذج التعلم الآلي مع التحقق المتبادل. بدلاً من ذلك، نبسط التمثيل عن طريق دمجها في فئة `"rain"`. .. GENERATED FROM PYTHON SOURCE LINES 128-135 .. code-block:: Python X["weather"] = ( X["weather"] .astype(object) .replace(to_replace="heavy_rain", value="rain") .astype("category") ) .. GENERATED FROM PYTHON SOURCE LINES 136-139 .. code-block:: Python X["weather"].value_counts() .. rst-class:: sphx-glr-script-out .. code-block:: none weather clear 11413 misty 4544 rain 1422 Name: count, dtype: int64 .. GENERATED FROM PYTHON SOURCE LINES 140-142 كما هو متوقع، فإن متغير `"season"` متوازن جيدًا: .. GENERATED FROM PYTHON SOURCE LINES 142-144 .. code-block:: Python X["season"].value_counts() .. rst-class:: sphx-glr-script-out .. code-block:: none season fall 4496 summer 4409 spring 4242 winter 4232 Name: count, dtype: int64 .. GENERATED FROM PYTHON SOURCE LINES 145-157 التحقق المتبادل على أساس الوقت --------------------------- نظرًا لأن مجموعة البيانات هي سجل أحداث مرتب زمنيًا (طلب كل ساعة)، فسنستخدم مُقسِّمًا للتحقق المتبادل حساسًا للوقت لتقييم نموذج التنبؤ بالطلب الخاص بنا بأكبر قدر ممكن من الواقعية. نستخدم فجوة لمدة يومين بين جانب التدريب وجانب الاختبار من عمليات التقسيم. نقوم أيضًا بتحديد حجم مجموعة التدريب لجعل أداء طيات التحقق المتبادل أكثر استقرارًا. يجب أن تكون 1000 نقطة بيانات اختبار كافية لتحديد أداء النموذج. يُمثل هذا أقل بقليل من شهر ونصف من بيانات الاختبار المتجاورة: .. GENERATED FROM PYTHON SOURCE LINES 157-166 .. code-block:: Python ts_cv = TimeSeriesSplit( n_splits=5, gap=48, max_train_size=10000, test_size=1000, ) .. GENERATED FROM PYTHON SOURCE LINES 167-169 دعونا نفحص يدويًا التقسيمات المختلفة للتحقق من أن `TimeSeriesSplit` يعمل كما نتوقع، بدءًا من التقسيم الأول: .. GENERATED FROM PYTHON SOURCE LINES 169-172 .. code-block:: Python all_splits = list(ts_cv.split(X, y)) train_0, test_0 = all_splits[0] .. GENERATED FROM PYTHON SOURCE LINES 173-175 .. code-block:: Python X.iloc[test_0] .. raw:: html
season year month hour holiday weekday workingday weather temp feel_temp humidity windspeed
12379 summer 1 6 0 False 2 True clear 22.14 25.760 0.68 27.9993
12380 summer 1 6 1 False 2 True misty 21.32 25.000 0.77 22.0028
12381 summer 1 6 2 False 2 True rain 21.32 25.000 0.72 19.9995
12382 summer 1 6 3 False 2 True rain 20.50 24.240 0.82 12.9980
12383 summer 1 6 4 False 2 True rain 20.50 24.240 0.82 12.9980
... ... ... ... ... ... ... ... ... ... ... ... ...
13374 fall 1 7 11 False 1 True clear 34.44 40.150 0.53 15.0013
13375 fall 1 7 12 False 1 True clear 34.44 39.395 0.49 8.9981
13376 fall 1 7 13 False 1 True clear 34.44 39.395 0.49 19.0012
13377 fall 1 7 14 False 1 True clear 36.08 40.910 0.42 7.0015
13378 fall 1 7 15 False 1 True clear 35.26 40.150 0.47 16.9979

1000 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 176-178 .. code-block:: Python X.iloc[train_0] .. raw:: html
season year month hour holiday weekday workingday weather temp feel_temp humidity windspeed
2331 summer 0 4 1 False 2 True misty 25.42 31.060 0.50 6.0032
2332 summer 0 4 2 False 2 True misty 24.60 31.060 0.53 8.9981
2333 summer 0 4 3 False 2 True misty 23.78 27.275 0.56 8.9981
2334 summer 0 4 4 False 2 True misty 22.96 26.515 0.64 8.9981
2335 summer 0 4 5 False 2 True misty 22.14 25.760 0.68 8.9981
... ... ... ... ... ... ... ... ... ... ... ... ...
12326 summer 1 6 19 False 6 False clear 26.24 31.060 0.36 11.0014
12327 summer 1 6 20 False 6 False clear 25.42 31.060 0.35 19.0012
12328 summer 1 6 21 False 6 False clear 24.60 31.060 0.40 7.0015
12329 summer 1 6 22 False 6 False clear 23.78 27.275 0.46 8.9981
12330 summer 1 6 23 False 6 False clear 22.96 26.515 0.52 7.0015

10000 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 179-180 نفحص الآن التقسيم الأخير: .. GENERATED FROM PYTHON SOURCE LINES 180-182 .. code-block:: Python train_4, test_4 = all_splits[4] .. GENERATED FROM PYTHON SOURCE LINES 183-186 .. code-block:: Python X.iloc[test_4] .. raw:: html
season year month hour holiday weekday workingday weather temp feel_temp humidity windspeed
16379 winter 1 11 5 False 2 True misty 13.94 16.665 0.66 8.9981
16380 winter 1 11 6 False 2 True misty 13.94 16.665 0.71 11.0014
16381 winter 1 11 7 False 2 True clear 13.12 16.665 0.76 6.0032
16382 winter 1 11 8 False 2 True clear 13.94 16.665 0.71 8.9981
16383 winter 1 11 9 False 2 True misty 14.76 18.940 0.71 0.0000
... ... ... ... ... ... ... ... ... ... ... ... ...
17374 spring 1 12 19 False 1 True misty 10.66 12.880 0.60 11.0014
17375 spring 1 12 20 False 1 True misty 10.66 12.880 0.60 11.0014
17376 spring 1 12 21 False 1 True clear 10.66 12.880 0.60 11.0014
17377 spring 1 12 22 False 1 True clear 10.66 13.635 0.56 8.9981
17378 spring 1 12 23 False 1 True clear 10.66 13.635 0.65 8.9981

1000 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 187-189 .. code-block:: Python X.iloc[train_4] .. raw:: html
season year month hour holiday weekday workingday weather temp feel_temp humidity windspeed
6331 winter 0 9 9 False 1 True misty 26.24 28.790 0.89 12.9980
6332 winter 0 9 10 False 1 True misty 26.24 28.790 0.89 12.9980
6333 winter 0 9 11 False 1 True clear 27.88 31.820 0.79 15.0013
6334 winter 0 9 12 False 1 True misty 27.88 31.820 0.79 11.0014
6335 winter 0 9 13 False 1 True misty 28.70 33.335 0.74 11.0014
... ... ... ... ... ... ... ... ... ... ... ... ...
16326 winter 1 11 0 False 0 False misty 12.30 15.150 0.70 11.0014
16327 winter 1 11 1 False 0 False clear 12.30 14.395 0.70 12.9980
16328 winter 1 11 2 False 0 False clear 11.48 14.395 0.81 7.0015
16329 winter 1 11 3 False 0 False misty 12.30 15.150 0.81 11.0014
16330 winter 1 11 4 False 0 False misty 12.30 14.395 0.81 12.9980

10000 rows × 12 columns



.. GENERATED FROM PYTHON SOURCE LINES 190-208 كل شيء على ما يرام. نحن الآن جاهزون لإجراء بعض النمذجة التنبؤية! تعزيز التدرج ----------------- غالبًا ما يكون انحدار تعزيز التدرج مع أشجار القرار مرنًا بما يكفي لـ معالجة البيانات الجدولية غير المتجانسة بكفاءة مع مزيج من الميزات الفئوية و الرقمية طالما أن عدد العينات كبير بما يكفي. هنا، نستخدم :class:`~sklearn.ensemble.HistGradientBoostingRegressor` الحديث مع دعم أصلي للميزات الفئوية. لذلك، نحتاج فقط إلى تعيين `categorical_features="from_dtype"` بحيث تُعتبر الميزات ذات نوع البيانات الفئوية ميزات فئوية. كمرجع، نستخرج الميزات الفئوية من إطار البيانات بناءً على نوع البيانات. تستخدم الأشجار الداخلية قاعدة تقسيم شجرة مخصصة لهذه الميزات. لا تحتاج المتغيرات الرقمية إلى معالجة مسبقة، ومن أجل البساطة، نجرب فقط المعلمات الفائقة الافتراضية لهذا النموذج: .. GENERATED FROM PYTHON SOURCE LINES 208-215 .. code-block:: Python gbrt = HistGradientBoostingRegressor( categorical_features="from_dtype", random_state=42) categorical_columns = X.columns[X.dtypes == "category"] print("الميزات الفئوية:", categorical_columns.tolist()) .. rst-class:: sphx-glr-script-out .. code-block:: none الميزات الفئوية: ['season', 'holiday', 'workingday', 'weather'] .. GENERATED FROM PYTHON SOURCE LINES 216-218 دعونا نُقيِّم نموذج تعزيز التدرج الخاص بنا باستخدام متوسط ​​الخطأ المطلق للطلب النسبي في المتوسط ​​عبر 5 تقسيمات للتحقق المتبادل على أساس الوقت: .. GENERATED FROM PYTHON SOURCE LINES 219-248 .. code-block:: Python def evaluate(model, X, y, cv, model_prop=None, model_step=None): cv_results = cross_validate( model, X, y, cv=cv, scoring=["neg_mean_absolute_error", "neg_root_mean_squared_error"], return_estimator=model_prop is not None, ) if model_prop is not None: if model_step is not None: values = [ getattr(m[model_step], model_prop) for m in cv_results["estimator"] ] else: values = [getattr(m, model_prop) for m in cv_results["estimator"]] print(f"متوسط model.{model_prop} = {np.mean(values)}") mae = -cv_results["test_neg_mean_absolute_error"] rmse = -cv_results["test_neg_root_mean_squared_error"] print( f"متوسط ​​الخطأ المطلق: {mae.mean():.3f} +/- {mae.std():.3f}\n" f"جذر متوسط ​​الخطأ التربيعي: {rmse.mean():.3f} +/- {rmse.std():.3f}" ) evaluate(gbrt, X, y, cv=ts_cv, model_prop="n_iter_") .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط model.n_iter_ = 100.0 متوسط ​​الخطأ المطلق: 0.044 +/- 0.003 جذر متوسط ​​الخطأ التربيعي: 0.068 +/- 0.005 .. GENERATED FROM PYTHON SOURCE LINES 249-268 نرى أننا قمنا بتعيين `max_iter` كبيرة بما يكفي بحيث يتم الإيقاف المبكر. يبلغ متوسط ​​خطأ هذا النموذج حوالي 4 إلى 5٪ من الحد الأقصى للطلب. هذا جيد جدًا للمحاولة الأولى بدون أي ضبط للمعلمات الفائقة! كان علينا فقط توضيح المتغيرات الفئوية. لاحظ أنه يتم تمرير الميزات ذات الصلة بالوقت كما هي، أي بدون معالجتها. لكن هذه ليست مشكلة كبيرة للنماذج المستندة إلى الشجرة لأنها تستطيع تعلم علاقة غير رتيبة بين ميزات الإدخال الترتيبية والهدف. هذا ليس هو الحال بالنسبة لنماذج الانحدار الخطي كما سنرى في ما يلي. الانحدار الخطي الساذج ----------------------- كالمعتاد بالنسبة للنماذج الخطية، يجب ترميز المتغيرات الفئوية بشكل أحادي الاتجاه. من أجل الاتساق، نقوم بقياس الميزات الرقمية على نفس النطاق 0-1 باستخدام :class:`~sklearn.preprocessing.MinMaxScaler`، على الرغم من أن هذا لا يؤثر على النتائج كثيرًا في هذه الحالة لأنها بالفعل على مقاييس قابلة للمقارنة: .. GENERATED FROM PYTHON SOURCE LINES 268-288 .. code-block:: Python one_hot_encoder = OneHotEncoder(handle_unknown="ignore", sparse_output=False) alphas = np.logspace(-6, 6, 25) naive_linear_pipeline = make_pipeline( ColumnTransformer( transformers=[ ("categorical", one_hot_encoder, categorical_columns), ], remainder=MinMaxScaler(), ), RidgeCV(alphas=alphas), ) evaluate( naive_linear_pipeline, X, y, cv=ts_cv, model_prop="alpha_", model_step="ridgecv" ) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط model.alpha_ = 2.7298221281347037 متوسط ​​الخطأ المطلق: 0.142 +/- 0.014 جذر متوسط ​​الخطأ التربيعي: 0.184 +/- 0.020 .. GENERATED FROM PYTHON SOURCE LINES 289-317 من المؤكد أن `alpha_` المحددة موجودة في نطاقنا المحدد. الأداء ليس جيدًا: متوسط ​​الخطأ حوالي 14٪ من الحد الأقصى للطلب. هذا أعلى بثلاث مرات من متوسط ​​خطأ نموذج تعزيز التدرج. يمكننا أن نشك في أن الترميز الأصلي الساذج (تم قياسه ببساطة من الحد الأدنى إلى الحد الأقصى) للميزات الدورية ذات الصلة بالوقت قد يمنع نموذج الانحدار الخطي من الاستفادة بشكل صحيح من معلومات الوقت: لا يُنمذج الانحدار الخطي تلقائيًا العلاقات غير الرتيبة بين ميزات الإدخال والهدف. يجب هندسة المصطلحات غير الخطية في الإدخال. على سبيل المثال، يمنع الترميز الرقمي الأولي لميزة `"hour"` النموذج الخطي من التعرف على أن زيادة الساعة في الصباح من 6 إلى 8 يجب أن يكون لها تأثير إيجابي قوي على عدد تأجيرات الدراجات بينما يجب أن يكون للزيادة ذات الحجم المماثل في المساء من 18 إلى 20 تأثير سلبي قوي على العدد المتوقع لتأجيرات الدراجات. الخطوات الزمنية كفئات ------------------------ نظرًا لأن ميزات الوقت مُرمَّزة بطريقة منفصلة باستخدام أعداد صحيحة (24 قيمة فريدة في ميزة "hours")، يمكننا أن نقرر التعامل مع هذه كمتغيرات فئوية باستخدام ترميز أحادي الاتجاه وبالتالي تجاهل أي افتراض ضمني بترتيب قيم الساعة. يمنح استخدام الترميز الأحادي الاتجاه لميزات الوقت النموذج الخطي مرونة أكبر بكثير حيث نُقدم ميزة إضافية واحدة لكل مستوى زمني منفصل. .. GENERATED FROM PYTHON SOURCE LINES 317-330 .. code-block:: Python one_hot_linear_pipeline = make_pipeline( ColumnTransformer( transformers=[ ("categorical", one_hot_encoder, categorical_columns), ("one_hot_time", one_hot_encoder, ["hour", "weekday", "month"]), ], remainder=MinMaxScaler(), ), RidgeCV(alphas=alphas), ) evaluate(one_hot_linear_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.099 +/- 0.011 جذر متوسط ​​الخطأ التربيعي: 0.131 +/- 0.011 .. GENERATED FROM PYTHON SOURCE LINES 331-359 يبلغ متوسط ​​معدل الخطأ لهذا النموذج 10٪ وهو أفضل بكثير من استخدام الترميز الأصلي (الترتيبي) لميزة الوقت، مما يؤكد حدسنا بأن نموذج الانحدار الخطي يستفيد من المرونة المضافة لعدم معالجة تقدم الوقت بطريقة رتيبة. ومع ذلك، يُسبب هذا عددًا كبيرًا جدًا من الميزات الجديدة. إذا تم تمثيل وقت اليوم بالدقائق منذ بداية اليوم بدلاً من الساعات، لكان الترميز الأحادي الاتجاه قد أدخل 1440 ميزة بدلاً من 24. قد يُسبب هذا بعض التكيف الزائد الكبير. لتجنب ذلك، يمكننا استخدام :func:`sklearn.preprocessing.KBinsDiscretizer` بدلاً من ذلك لإعادة تصنيف عدد مستويات المتغيرات الترتيبية أو الرقمية الدقيقة مع الاستمرار في الاستفادة من مزايا التعبير غير الرتيب للترميز الأحادي الاتجاه. أخيرًا، نلاحظ أيضًا أن الترميز الأحادي الاتجاه يتجاهل تمامًا ترتيب مستويات الساعة بينما قد يكون هذا تحيزًا استقرائيًا مثيرًا للاهتمام للحفاظ عليه إلى حد ما. في ما يلي، نحاول استكشاف ترميز سلس وغير رتيب يحافظ محليًا على الترتيب النسبي لميزات الوقت. الميزات المثلثية ---------------------- كمحاولة أولى، يمكننا محاولة ترميز كل من هذه الميزات الدورية باستخدام تحويل الجيب وجيب التمام مع الفترة المقابلة. يتم تحويل كل ميزة زمنية ترتيبية إلى ميزتين تُرمِّزان معًا معلومات مكافئة بطريقة غير رتيبة، والأهم من ذلك بدون أي قفزة بين القيمة الأولى والأخيرة للنطاق الدوري. .. GENERATED FROM PYTHON SOURCE LINES 359-369 .. code-block:: Python def sin_transformer(period): return FunctionTransformer(lambda x: np.sin(x / period * 2 * np.pi)) def cos_transformer(period): return FunctionTransformer(lambda x: np.cos(x / period * 2 * np.pi)) .. GENERATED FROM PYTHON SOURCE LINES 370-372 دعونا نتصور تأثير توسيع الميزة هذا على بعض بيانات الساعة التركيبية مع القليل من الاستقراء بعد الساعة = 23: .. GENERATED FROM PYTHON SOURCE LINES 373-383 .. code-block:: Python hour_df = pd.DataFrame( np.arange(26).reshape(-1, 1), columns=["hour"], ) hour_df["hour_sin"] = sin_transformer(24).fit_transform(hour_df)["hour"] hour_df["hour_cos"] = cos_transformer(24).fit_transform(hour_df)["hour"] hour_df.plot(x="hour") _ = plt.title("الترميز المثلثي لميزة 'hour'") .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_003.png :alt: الترميز المثلثي لميزة 'hour' :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 384-389 دعونا نستخدم مخطط تشتت ثنائي الأبعاد مع الساعات المُرمَّزة كألوان لنرى بشكل أفضل كيف يُعيِّن هذا التمثيل ساعات اليوم الأربع والعشرين إلى مساحة ثنائية الأبعاد، تُشبه نوعًا من إصدار ساعة تناظرية لمدة 24 ساعة. لاحظ أن الساعة "الخامسة والعشرين" يتم تعيينها مرة أخرى إلى الساعة الأولى بسبب الطبيعة الدورية لتمثيل الجيب/جيب التمام. .. GENERATED FROM PYTHON SOURCE LINES 390-398 .. code-block:: Python fig, ax = plt.subplots(figsize=(7, 5)) sp = ax.scatter(hour_df["hour_sin"], hour_df["hour_cos"], c=hour_df["hour"]) ax.set( xlabel="sin(hour)", ylabel="cos(hour)", ) _ = fig.colorbar(sp) .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_004.png :alt: plot cyclical feature engineering :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 399-400 يمكننا الآن بناء خط أنابيب لاستخراج الميزات باستخدام هذه الاستراتيجية: .. GENERATED FROM PYTHON SOURCE LINES 401-421 .. code-block:: Python cyclic_cossin_transformer = ColumnTransformer( transformers=[ ("categorical", one_hot_encoder, categorical_columns), ("month_sin", sin_transformer(12), ["month"]), ("month_cos", cos_transformer(12), ["month"]), ("weekday_sin", sin_transformer(7), ["weekday"]), ("weekday_cos", cos_transformer(7), ["weekday"]), ("hour_sin", sin_transformer(24), ["hour"]), ("hour_cos", cos_transformer(24), ["hour"]), ], remainder=MinMaxScaler(), ) cyclic_cossin_linear_pipeline = make_pipeline( cyclic_cossin_transformer, RidgeCV(alphas=alphas), ) evaluate(cyclic_cossin_linear_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.125 +/- 0.014 جذر متوسط ​​الخطأ التربيعي: 0.166 +/- 0.020 .. GENERATED FROM PYTHON SOURCE LINES 422-433 أداء نموذج الانحدار الخطي الخاص بنا مع هندسة الميزات البسيطة هذه أفضل قليلاً من استخدام ميزات الوقت الترتيبية الأصلية ولكنه أسوأ من استخدام ميزات الوقت المُرمَّزة بشكل أحادي الاتجاه. سنُحلل المزيد من الأسباب المحتملة لهذه النتيجة المخيبة للآمال في نهاية هذا الدفتر. ميزات сплаين الدورية ------------------------ يمكننا تجربة ترميز بديل لميزات الوقت الدورية ذات الصلة باستخدام تحويلات сплаين مع عدد كبير بما يكفي من сплаين، ونتيجة لذلك، عدد أكبر من الميزات الموسعة مقارنة بتحويل الجيب/جيب التمام: .. GENERATED FROM PYTHON SOURCE LINES 434-449 .. code-block:: Python def periodic_spline_transformer(period, n_splines=None, degree=3): if n_splines is None: n_splines = period n_knots = n_splines + 1 # دوري و include_bias هو True return SplineTransformer( degree=degree, n_knots=n_knots, knots=np.linspace(0, period, n_knots).reshape(n_knots, 1), extrapolation="periodic", include_bias=True, ) .. GENERATED FROM PYTHON SOURCE LINES 450-452 مرة أخرى، دعونا نتصور تأثير توسيع الميزة هذا على بعض بيانات الساعة التركيبية مع القليل من الاستقراء بعد الساعة = 23: .. GENERATED FROM PYTHON SOURCE LINES 453-467 .. code-block:: Python hour_df = pd.DataFrame( np.linspace(0, 26, 1000).reshape(-1, 1), columns=["hour"], ) splines = periodic_spline_transformer(24, n_splines=12).fit_transform(hour_df) splines_df = pd.DataFrame( splines, columns=[f"spline_{i}" for i in range(splines.shape[1])], ) pd.concat([hour_df, splines_df], axis="columns").plot( x="hour", cmap=plt.cm.tab20b) _ = plt.title("ترميز قائم على сплаين الدوري لميزة 'hour'") .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_005.png :alt: ترميز قائم على сплаين الدوري لميزة 'hour' :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_005.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 468-477 بفضل استخدام معلمة `extrapolation="periodic"`، نلاحظ أن ترميز الميزة يظل سلسًا عند الاستقراء إلى ما بعد منتصف الليل. يمكننا الآن بناء خط أنابيب تنبؤي باستخدام استراتيجية هندسة الميزات الدورية البديلة هذه. من الممكن استخدام عدد أقل من сплаين من المستويات المنفصلة لهذه القيم الترتيبية. هذا يجعل الترميز القائم على сплаين أكثر كفاءة من الترميز الأحادي الاتجاه مع الحفاظ على معظم التعبيرية: .. GENERATED FROM PYTHON SOURCE LINES 477-497 .. code-block:: Python cyclic_spline_transformer = ColumnTransformer( transformers=[ ("categorical", one_hot_encoder, categorical_columns), ("cyclic_month", periodic_spline_transformer( 12, n_splines=6), ["month"]), ("cyclic_weekday", periodic_spline_transformer( 7, n_splines=3), ["weekday"]), ("cyclic_hour", periodic_spline_transformer( 24, n_splines=12), ["hour"]), ], remainder=MinMaxScaler(), ) cyclic_spline_linear_pipeline = make_pipeline( cyclic_spline_transformer, RidgeCV(alphas=alphas), ) evaluate(cyclic_spline_linear_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.097 +/- 0.011 جذر متوسط ​​الخطأ التربيعي: 0.132 +/- 0.013 .. GENERATED FROM PYTHON SOURCE LINES 498-511 تُمكِّن ميزات сплаين النموذج الخطي من الاستفادة بنجاح من الميزات الدورية ذات الصلة بالوقت وتقليل الخطأ من ~ 14٪ إلى ~ 10٪ من الحد الأقصى للطلب، وهو ما يُشبه ما لاحظناه مع الميزات المُرمَّزة بشكل أحادي الاتجاه. التحليل النوعي لتأثير الميزات على تنبؤات النموذج الخطي -------------------------------------------------------------------------- هنا، نريد تصور تأثير اختيارات هندسة الميزات على الشكل المتعلق بالوقت للتنبؤات. للقيام بذلك، نعتبر تقسيمًا عشوائيًا قائمًا على الوقت لمقارنة التنبؤات على مجموعة من نقاط البيانات المحتفظ بها. .. GENERATED FROM PYTHON SOURCE LINES 511-525 .. code-block:: Python naive_linear_pipeline.fit(X.iloc[train_0], y.iloc[train_0]) naive_linear_predictions = naive_linear_pipeline.predict(X.iloc[test_0]) one_hot_linear_pipeline.fit(X.iloc[train_0], y.iloc[train_0]) one_hot_linear_predictions = one_hot_linear_pipeline.predict(X.iloc[test_0]) cyclic_cossin_linear_pipeline.fit(X.iloc[train_0], y.iloc[train_0]) cyclic_cossin_linear_predictions = cyclic_cossin_linear_pipeline.predict( X.iloc[test_0]) cyclic_spline_linear_pipeline.fit(X.iloc[train_0], y.iloc[train_0]) cyclic_spline_linear_predictions = cyclic_spline_linear_pipeline.predict( X.iloc[test_0]) .. GENERATED FROM PYTHON SOURCE LINES 526-528 نقوم بتصور هذه التنبؤات عن طريق التكبير على آخر 96 ساعة (4 أيام) من مجموعة الاختبار للحصول على بعض الأفكار النوعية: .. GENERATED FROM PYTHON SOURCE LINES 528-558 .. code-block:: Python last_hours = slice(-96, None) fig, ax = plt.subplots(figsize=(12, 4)) fig.suptitle("التنبؤات بواسطة النماذج الخطية") ax.plot( y.iloc[test_0].values[last_hours], "x-", alpha=0.2, label="الطلب الفعلي", color="black", ) ax.plot(naive_linear_predictions[last_hours], "x-", label="ميزات الوقت الترتيبي") ax.plot( cyclic_cossin_linear_predictions[last_hours], "x-", label="ميزات الوقت المثلثية", ) ax.plot( cyclic_spline_linear_predictions[last_hours], "x-", label="ميزات الوقت القائمة على сплаين", ) ax.plot( one_hot_linear_predictions[last_hours], "x-", label="ميزات الوقت أحادية الاتجاه", ) _ = ax.legend() .. image-sg:: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_006.png :alt: التنبؤات بواسطة النماذج الخطية :srcset: /auto_examples/applications/images/sphx_glr_plot_cyclical_feature_engineering_006.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 559-584 يمكننا استخلاص الاستنتاجات التالية من الرسم البياني أعلاه: - **ميزات الوقت الترتيبية الأولية** مشكلة لأنها لا تلتقط الدورية الطبيعية: نلاحظ قفزة كبيرة في التنبؤات في نهاية كل يوم عندما تنتقل ميزات الساعة من 23 إلى 0. يمكننا توقع قطع أثرية مماثلة في نهاية كل أسبوع أو كل عام. - كما هو متوقع، **الميزات المثلثية** (الجيب وجيب التمام) ليس لديها هذه الانقطاعات في منتصف الليل، لكن نموذج الانحدار الخطي يفشل في الاستفادة من هذه الميزات لنمذجة التغيرات داخل اليوم بشكل صحيح. يمكن أن يؤدي استخدام الميزات المثلثية للتوافقيات الأعلى أو الميزات المثلثية الإضافية للفترة الطبيعية ذات المراحل المختلفة إلى إصلاح هذه المشكلة. - تُصلح **الميزات الدورية القائمة على сплаين** هاتين المشكلتين في وقت واحد: فهي تمنح النموذج الخطي مزيدًا من التعبيرية من خلال تمكينه من التركيز على ساعات محددة بفضل استخدام 12 сплаين. علاوة على ذلك، يفرض خيار `extrapolation="periodic"` تمثيلًا سلسًا بين `hour=23` و `hour=0`. - تتصرف **الميزات المُرمَّزة بشكل أحادي الاتجاه** بشكل مشابه للميزات الدورية القائمة على сплаين ولكنها أكثر حدة: على سبيل المثال، يمكنها نمذجة ذروة الصباح خلال أيام الأسبوع بشكل أفضل نظرًا لأن هذه الذروة تستمر أقل من ساعة. ومع ذلك، سنرى في ما يلي أن ما يمكن أن يكون ميزة للنماذج الخطية ليس بالضرورة للنماذج الأكثر تعبيرية. .. GENERATED FROM PYTHON SOURCE LINES 587-589 يمكننا أيضًا مقارنة عدد الميزات التي استخرجها كل خط أنابيب لهندسة الميزات: .. GENERATED FROM PYTHON SOURCE LINES 589-591 .. code-block:: Python naive_linear_pipeline[:-1].transform(X).shape .. rst-class:: sphx-glr-script-out .. code-block:: none (17379, 19) .. GENERATED FROM PYTHON SOURCE LINES 592-594 .. code-block:: Python one_hot_linear_pipeline[:-1].transform(X).shape .. rst-class:: sphx-glr-script-out .. code-block:: none (17379, 59) .. GENERATED FROM PYTHON SOURCE LINES 595-598 .. code-block:: Python cyclic_cossin_linear_pipeline[:-1].transform(X).shape .. rst-class:: sphx-glr-script-out .. code-block:: none (17379, 22) .. GENERATED FROM PYTHON SOURCE LINES 599-602 .. code-block:: Python cyclic_spline_linear_pipeline[:-1].transform(X).shape .. rst-class:: sphx-glr-script-out .. code-block:: none (17379, 37) .. GENERATED FROM PYTHON SOURCE LINES 603-619 يؤكد هذا أن استراتيجيات الترميز الأحادي الاتجاه والترميز القائم على сплаين تُنشئ ميزات أكثر بكثير لتمثيل الوقت من البدائل، مما يمنح بدوره النموذج الخطي في المراحل النهائية مزيدًا من المرونة (درجات الحرية) لتجنب نقص الملاءمة. أخيرًا، نلاحظ أنه لا يمكن لأي من النماذج الخطية تقريب الطلب الحقيقي على تأجير الدراجات، خاصة بالنسبة للقمم التي يمكن أن تكون حادة جدًا في ساعات الذروة خلال أيام العمل ولكنها أكثر تسطحًا خلال عطلات نهاية الأسبوع: أكثر النماذج الخطية دقة بناءً على сплаين أو الترميز الأحادي الاتجاه تميل إلى التنبؤ بقمم تأجير الدراجات المتعلقة بالتنقل حتى في عطلات نهاية الأسبوع و التقليل من تقدير الأحداث المتعلقة بالتنقل خلال أيام العمل. تكشف أخطاء التنبؤ المنهجية هذه عن شكل من أشكال نقص الملاءمة ويمكن تفسيرها من خلال عدم وجود مصطلحات تفاعل بين الميزات، على سبيل المثال "workingday" والميزات المشتقة من "hours". سيتم معالجة هذه المشكلة في القسم التالي. .. GENERATED FROM PYTHON SOURCE LINES 622-633 نمذجة التفاعلات الزوجية مع ميزات сплаين ومتعددة الحدود ------------------------------------------------------------------- لا تلتقط النماذج الخطية تلقائيًا تأثيرات التفاعل بين ميزات الإدخال. لا يساعد ذلك في أن بعض الميزات غير خطية بشكل هامشي كما هو الحال مع الميزات التي تم إنشاؤها بواسطة `SplineTransformer` (أو الترميز الأحادي الاتجاه أو التصنيف). ومع ذلك، من الممكن استخدام فئة `PolynomialFeatures` على ساعات مُرمَّزة بـ сплаين خشنة الحبيبات لنمذجة تفاعل "workingday"/"hours" صراحةً بدون إدخال عدد كبير جدًا من المتغيرات الجديدة: .. GENERATED FROM PYTHON SOURCE LINES 633-647 .. code-block:: Python hour_workday_interaction = make_pipeline( ColumnTransformer( [ ("cyclic_hour", periodic_spline_transformer( 24, n_splines=8), ["hour"]), ("workingday", FunctionTransformer( lambda x: x == "True"), ["workingday"]), ] ), PolynomialFeatures(degree=2, interaction_only=True, include_bias=False), ) .. GENERATED FROM PYTHON SOURCE LINES 648-651 ثم يتم دمج هذه الميزات مع تلك المحسوبة بالفعل في خط أنابيب сплаين السابق. يمكننا ملاحظة تحسن كبير في الأداء عن طريق نمذجة هذا التفاعل الزوجي صراحةً: .. GENERATED FROM PYTHON SOURCE LINES 651-663 .. code-block:: Python cyclic_spline_interactions_pipeline = make_pipeline( FeatureUnion( [ ("marginal", cyclic_spline_transformer), ("interactions", hour_workday_interaction), ] ), RidgeCV(alphas=alphas), ) evaluate(cyclic_spline_interactions_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.078 +/- 0.009 جذر متوسط ​​الخطأ التربيعي: 0.104 +/- 0.009 .. GENERATED FROM PYTHON SOURCE LINES 664-680 نمذجة تفاعلات الميزات غير الخطية باستخدام النوى ----------------------------------------------------- سلَّط التحليل السابق الضوء على الحاجة إلى نمذجة التفاعلات بين `"workingday"` و `"hours"`. مثال آخر على مثل هذا التفاعل غير الخطي الذي نود نمذجته هو تأثير المطر الذي قد لا يكون هو نفسه خلال أيام العمل وعطلات نهاية الأسبوع والأعياد على سبيل المثال. لنمذجة كل هذه التفاعلات، يمكننا إما استخدام توسيع متعدد الحدود على جميع الميزات الهامشية مرة واحدة، بعد توسيعها القائم على сплаين. ومع ذلك، سيُنشئ هذا عددًا تربيعيًا من الميزات التي يمكن أن تُسبب مشكلات في التكيف الزائد وقابلية التتبع الحسابي. بدلاً من ذلك، يمكننا استخدام طريقة Nyström لحساب توسيع نواة متعدد الحدود تقريبي. دعونا نجرب هذا الأخير: .. GENERATED FROM PYTHON SOURCE LINES 680-689 .. code-block:: Python cyclic_spline_poly_pipeline = make_pipeline( cyclic_spline_transformer, Nystroem(kernel="poly", degree=2, n_components=300, random_state=0), RidgeCV(alphas=alphas), ) evaluate(cyclic_spline_poly_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.053 +/- 0.002 جذر متوسط ​​الخطأ التربيعي: 0.076 +/- 0.004 .. GENERATED FROM PYTHON SOURCE LINES 690-700 نلاحظ أن هذا النموذج يمكن أن ينافس تقريبًا أداء أشجار التعزيز المتدرج بمتوسط ​​خطأ حوالي 5٪ من الحد الأقصى للطلب. لاحظ أنه على الرغم من أن الخطوة الأخيرة من خط الأنابيب هذا هي نموذج انحدار خطي، فإن الخطوات الوسيطة مثل استخراج ميزة сплаين وتقريب نواة Nyström غير خطية للغاية. نتيجة لذلك، يكون خط الأنابيب المركب أكثر تعبيرية من نموذج الانحدار الخطي البسيط ذي الميزات الأولية. من أجل الاكتمال، نقوم أيضًا بتقييم مزيج من الترميز الأحادي الاتجاه وتقريب النواة: .. GENERATED FROM PYTHON SOURCE LINES 701-716 .. code-block:: Python one_hot_poly_pipeline = make_pipeline( ColumnTransformer( transformers=[ ("categorical", one_hot_encoder, categorical_columns), ("one_hot_time", one_hot_encoder, ["hour", "weekday", "month"]), ], remainder="passthrough", ), Nystroem(kernel="poly", degree=2, n_components=300, random_state=0), RidgeCV(alphas=alphas), ) evaluate(one_hot_poly_pipeline, X, y, cv=ts_cv) .. rst-class:: sphx-glr-script-out .. code-block:: none متوسط ​​الخطأ المطلق: 0.082 +/- 0.006 جذر متوسط ​​الخطأ التربيعي: 0.111 +/- 0.011 .. GENERATED FROM PYTHON SOURCE LINES 717-720 بينما كانت الميزات المُرمَّزة بشكل أحادي الاتجاه تنافسية مع الميزات القائمة على сплаين عند استخدام نماذج خطية، لم يعد هذا هو الحال عند استخدام تقريب منخفض الرتبة لنواة غير خطية: يمكن تفسير ذلك من خلال حقيقة أن ميزات сплаين أكثر سلاسة وتسمح لتقريب النواة بالعثور عل .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 16.698 seconds) .. _sphx_glr_download_auto_examples_applications_plot_cyclical_feature_engineering.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/applications/plot_cyclical_feature_engineering.ipynb :alt: Launch binder :width: 150 px .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../lite/lab/index.html?path=auto_examples/applications/plot_cyclical_feature_engineering.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_cyclical_feature_engineering.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_cyclical_feature_engineering.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_cyclical_feature_engineering.zip ` .. include:: plot_cyclical_feature_engineering.recommendations .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_