مقارنة ترميز الهدف مع الترميزات الأخرى#

يستخدم TargetEncoder قيمة الهدف لترميز كل ميزة فئة. في هذا المثال، سنقارن بين ثلاثة أساليب مختلفة لمعالجة الميزات الفئوية: TargetEncoder، OrdinalEncoder، OneHotEncoder وإسقاط الفئة.

ملاحظة

fit(X, y).transform(X) لا يساوي fit_transform(X, y) لأن مخطط التثبيت المتقاطع مستخدم في fit_transform للترميز. راجع دليل المستخدم. للحصول على التفاصيل.

# المؤلفون: مطوري scikit-learn
# معرف SPDX-License: BSD-3-Clause

تحميل البيانات من OpenML#

أولاً، نقوم بتحميل مجموعة بيانات مراجعات النبيذ، حيث الهدف هو النقاط المعطاة من قبل المراجع:

from sklearn.datasets import fetch_openml

wine_reviews = fetch_openml(data_id=42074, as_frame=True)

df = wine_reviews.frame
df.head()
country description designation points price province region_1 region_2 variety winery
0 US This tremendous 100% varietal wine hails from ... Martha's Vineyard 96 235.0 California Napa Valley Napa Cabernet Sauvignon Heitz
1 Spain Ripe aromas of fig, blackberry and cassis are ... Carodorum Selección Especial Reserva 96 110.0 Northern Spain Toro NaN Tinta de Toro Bodega Carmen Rodríguez
2 US Mac Watson honors the memory of a wine once ma... Special Selected Late Harvest 96 90.0 California Knights Valley Sonoma Sauvignon Blanc Macauley
3 US This spent 20 months in 30% new French oak, an... Reserve 96 65.0 Oregon Willamette Valley Willamette Valley Pinot Noir Ponzi
4 France This is the top wine from La Bégude, named aft... La Brûlade 95 66.0 Provence Bandol NaN Provence red blend Domaine de la Bégude


لهذا المثال، نستخدم المجموعة الفرعية التالية من الميزات العددية والفئوية الميزات في البيانات. الهدف هي قيم مستمرة من 80 إلى 100:

numerical_features = ["price"]
categorical_features = [
    "country",
    "province",
    "region_1",
    "region_2",
    "variety",
    "winery",
]
target_name = "points"

X = df[numerical_features + categorical_features]
y = df[target_name]

_ = y.hist()
plot target encoder

تدريب وتقييم خطوط الأنابيب مع ترميزات مختلفة#

في هذا القسم، سنقيم خطوط الأنابيب مع HistGradientBoostingRegressor مع استراتيجيات ترميز مختلفة. أولاً، سنقوم بكتابة قائمة بالترميزات التي سنستخدمها لمعالجة مسبقة الميزات الفئوية:

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, OrdinalEncoder, TargetEncoder

categorical_preprocessors = [
    ("drop", "drop"),
    ("ordinal", OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1)),
    (
        "one_hot",
        OneHotEncoder(handle_unknown="ignore", max_categories=20, sparse_output=False),
    ),
    ("target", TargetEncoder(target_type="continuous")),
]

بعد ذلك، نقيم النماذج باستخدام التحقق المتقاطع ونقوم بتسجيل النتائج:

from sklearn.ensemble import HistGradientBoostingRegressor
from sklearn.model_selection import cross_validate
from sklearn.pipeline import make_pipeline

n_cv_folds = 3
max_iter = 20
results = []


def evaluate_model_and_store(name, pipe):
    result = cross_validate(
        pipe,
        X,
        y,
        scoring="neg_root_mean_squared_error",
        cv=n_cv_folds,
        return_train_score=True,
    )
    rmse_test_score = -result["test_score"]
    rmse_train_score = -result["train_score"]
    results.append(
        {
            "preprocessor": name,
            "rmse_test_mean": rmse_test_score.mean(),
            "rmse_test_std": rmse_train_score.std(),
            "rmse_train_mean": rmse_train_score.mean(),
            "rmse_train_std": rmse_train_score.std(),
        }
    )


for name, categorical_preprocessor in categorical_preprocessors:
    preprocessor = ColumnTransformer(
        [
            ("numerical", "passthrough", numerical_features),
            ("categorical", categorical_preprocessor, categorical_features),
        ]
    )
    pipe = make_pipeline(
        preprocessor, HistGradientBoostingRegressor(random_state=0, max_iter=max_iter)
    )
    evaluate_model_and_store(name, pipe)

دعم الميزات الفئوية الأصلي#

في هذا القسم، نقوم ببناء وتقييم خط أنابيب يستخدم الدعم الفئوي الأصلي في HistGradientBoostingRegressor، الذي يدعم ما يصل إلى 255 فئة فريدة فقط. في مجموعة بياناتنا، معظم الميزات الفئوية لديها أكثر من 255 فئة فريدة:

n_unique_categories = df[categorical_features].nunique().sort_values(ascending=False)
n_unique_categories
winery      14810
region_1     1236
variety       632
province      455
country        48
region_2       18
dtype: int64

للتحايل على القيد أعلاه، نقوم بتقسيم الميزات الفئوية إلى ميزات ذات عدد قليل من الفئات وميزات ذات عدد كبير من الفئات. سيتم ترميز الميزات ذات العدد الكبير من الفئات وسيتم استخدام الميزات ذات العدد القليل من الفئات في التدرج الدعم الفئوي الأصلي.

high_cardinality_features = n_unique_categories[n_unique_categories > 255].index
low_cardinality_features = n_unique_categories[n_unique_categories <= 255].index
mixed_encoded_preprocessor = ColumnTransformer(
    [
        ("numerical", "passthrough", numerical_features),
        (
            "high_cardinality",
            TargetEncoder(target_type="continuous"),
            high_cardinality_features,
        ),
        (
            "low_cardinality",
            OrdinalEncoder(handle_unknown="use_encoded_value", unknown_value=-1),
            low_cardinality_features,
        ),
    ],
    verbose_feature_names_out=False,
)

# يجب تعيين إخراج المعالج المسبق إلى pandas بحيث يمكن
# نموذج التدرج الكشف عن الميزات ذات العدد القليل من الفئات.
mixed_encoded_preprocessor.set_output(transform="pandas")
mixed_pipe = make_pipeline(
    mixed_encoded_preprocessor,
    HistGradientBoostingRegressor(
        random_state=0, max_iter=max_iter, categorical_features=low_cardinality_features
    ),
)
mixed_pipe
Pipeline(steps=[('columntransformer',
                 ColumnTransformer(transformers=[('numerical', 'passthrough',
                                                  ['price']),
                                                 ('high_cardinality',
                                                  TargetEncoder(target_type='continuous'),
                                                  Index(['winery', 'region_1', 'variety', 'province'], dtype='object')),
                                                 ('low_cardinality',
                                                  OrdinalEncoder(handle_unknown='use_encoded_value',
                                                                 unknown_value=-1),
                                                  Index(['country', 'region_2'], dtype='object'))],
                                   verbose_feature_names_out=False)),
                ('histgradientboostingregressor',
                 HistGradientBoostingRegressor(categorical_features=Index(['country', 'region_2'], dtype='object'),
                                               max_iter=20, random_state=0))])
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.


أخيرًا، نقوم بتقييم خط الأنابيب باستخدام التحقق المتقاطع وتسجيل النتائج:

evaluate_model_and_store("mixed_target", mixed_pipe)

رسم النتائج#

في هذا القسم، نقوم بعرض النتائج عن طريق رسم درجات الاختبار والتدريب:

import matplotlib.pyplot as plt
import pandas as pd

results_df = (
    pd.DataFrame(results).set_index("preprocessor").sort_values("rmse_test_mean")
)

fig, (ax1, ax2) = plt.subplots(
    1, 2, figsize=(12, 8), sharey=True, constrained_layout=True
)
xticks = range(len(results_df))
name_to_color = dict(
    zip((r["preprocessor"] for r in results), ["C0", "C1", "C2", "C3", "C4"])
)

for subset, ax in zip(["test", "train"], [ax1, ax2]):
    mean, std = f"rmse_{subset}_mean", f"rmse_{subset}_std"
    data = results_df[[mean, std]].sort_values(mean)
    ax.bar(
        x=xticks,
        height=data[mean],
        yerr=data[std],
        width=0.9,
        color=[name_to_color[name] for name in data.index],
    )
    ax.set(
        title=f"RMSE ({subset.title()})",
        xlabel="Encoding Scheme",
        xticks=xticks,
        xticklabels=data.index,
    )
RMSE (Test), RMSE (Train)

عند تقييم الأداء التنبؤي على مجموعة الاختبار، يؤدي إسقاط الفئات تؤدي إلى أسوأ أداء، ويؤدي ترميز الهدف إلى أفضل أداء. يمكن تفسير هذا على النحو التالي:

  • يؤدي إسقاط الميزات الفئوية إلى جعل خط الأنابيب أقل تعبيرًا وتحت التلائم

نتيجة لذلك؛ - نظرًا لارتفاع عدد الفئات ولتقليل وقت التدريب، يستخدم مخطط الترميز أحادي الساخن max_categories=20 الذي يمنع الميزات من التوسع كثيرًا، والذي يمكن أن يؤدي إلى نقص التلائم. - إذا لم نقم بتعيين max_categories=20، فمن المحتمل أن يؤدي مخطط الترميز أحادي الساخن إلى جعل خط الأنابيب مفرط التلائم حيث ينفجر عدد الميزات مع حدوث فئات نادرة التي ترتبط بالهدف عن طريق الصدفة (على مجموعة التدريب فقط)؛ - يفرض الترميز الترتيبي ترتيبًا تعسفيًا على الميزات التي يتم معاملتها بعد ذلك كقيم عددية بواسطة HistGradientBoostingRegressor. نظرًا لأن هذا النموذج يجمع الميزات العددية في 256 صنفًا لكل ميزة، يمكن تجميع العديد من الفئات غير ذات الصلة معًا ونتيجة لذلك يمكن أن يؤدي خط الأنابيب العام إلى نقص التلائم؛ - عند استخدام ترميز الهدف، يحدث نفس التجميع، ولكن نظرًا لأن القيم المشفرة يتم ترتيبها إحصائيًا بالارتباط الهامشي مع متغير الهدف، التجميع الذي يستخدمه HistGradientBoostingRegressor منطقي ويؤدي إلى نتائج جيدة: يعمل مزيج الترميز المستهدف المملس والتجميع كاستراتيجية تنظيم جيدة ضد الإفراط في التلائم مع عدم الحد من تعبيرية خط الأنابيب كثيرًا.

Total running time of the script: (0 minutes 25.366 seconds)

Related examples

دعم الميزات التصنيفية في التدرج التعزيزي

دعم الميزات التصنيفية في التدرج التعزيزي

الترميز الداخلي للهدف عبر الملاءمة

الترميز الداخلي للهدف عبر الملاءمة

محول الأعمدة مع الأنواع المختلطة

محول الأعمدة مع الأنواع المختلطة

عرض خطوط الأنابيب

عرض خطوط الأنابيب

Gallery generated by Sphinx-Gallery