التعامل مع المتغيرات الفئوية : بناء نموذج

تحدثنا في المقال السابق عن معظم المشاكل التي قد تواجهنا أثنا تعاملنا مع المتغيرات الفئوئية ، في هذا المقال سنقوم ببناء نموذج لتصنيف مجموعة البيانات  cat-in-the-dat II ونحاول تحسين أدائه بطريقة تدريجية. قبل القيام بناء النماذج ، من الضروري الاهتمام بالتحقق المتقاطع.

التحقق المتقاطع 

 لقد رأينا بالفعل توزيع المسميات / الهدف ، ونعلم أنها مشكلة تصنيف ثنائية مع أهداف منحرفة. وبالتالي ، سوف نستخدم StratifiedKFold لتقسيم البيانات هنا.

import pandas as pd
from sklearn import model_selection

if __name__ == '__main__':

    # قراءة ملفات التدريب
    df = pd.read_csv("../input/cat_train.csv")

    # -1 و نمله بـ kfold ننشأ عامود جديد نسميه 
    df["kfold"] = -1

    # الخطوة التاليه هي عشوائية صفوف البيانات 
    df = df.sample(frac=1).reset_index(drop=True)

    # الحصول على المسيات
    y = df.target.values

    #  model_selection من  kfold تهيئة كلاس 
    kf = model_selection.StratifiedKFold(n_splits=5)

    # kfold ملء عامود 

    for f , (t_, v_) in enumerate(kf.split(X=df, y=y)):
        df.loc[v_, 'kfold'] = f

    # حفظ ملف الجديد مع عامود الطيات
    df.to_csv("../input/cat_train_folds.csv", index=False)

يمكننا الآن التحقق من طيات csv الجديدة لمعرفة عدد العينات في كل طية:

In [X]: import pandas as pd
In [X]: df = pd.read_csv("../input/cat_train_folds.csv")
In [X]: df.kfold.value_counts()
Out[X]:
4 120000
3 120000
2 120000
1 120000
0 120000
Name: kfold, dtype: int64

تحتوي جميع الطيات على 120000 عينة. هذا متوقع لأن بيانات التدريب تحتوي على 600000 عينة ، وقمنا بعمل خمسة طيات . حتى الان جيد جدا.

 الآن ، يمكننا أيضًا التحقق من التوزيع المستهدف لكل طيه.

In [X]: df[df.kfold==0].target.value_counts()
Out[X]:
0 97536
1 22464
Name: target, dtype: int64
In [X]: df[df.kfold==1].target.value_counts()
Out[X]:
0 97536
1 22464
Name: target, dtype: int64
In [X]: df[df.kfold==2].target.value_counts()
Out[X]:
0 97535
1 22465
Name: target, dtype: int64
In [X]: df[df.kfold==3].target.value_counts()
Out[X]:
0 97535
1 22465
Name: target, dtype: int64
In [X]: df[df.kfold==4].target.value_counts()
Out[X]:
0 97535
1 22465
Name: target, dtype: int64

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

بناء النماذج 

خط الترميز الأحادي و الإنحدار اللوجستي 

 أحد أبسط النماذج التي يمكننا بناءها هو بإستخدام خط الترميز الأحادي لجميع البيانات  واستخدام الانحدار اللوجستي (logistic regression) 

import pandas as pd
from sklearn import linear_model
from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/cat_train_folds.csv")

    # target , id, kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("id" , "target", "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # الحصول على بيانات التدريب بإستخدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)

    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # تهيئة خط الترميز الأحادي
    ohe = preprocessing.OneHotEncoder()

    # مناسبت خط الترميز الأحادي على سمات التدريب و التحقق
    full_data = pd.concat(
        [df_train[features], df_valid[features]],axis=0
    )

    ohe.fit (full_data[features])

    #  تحويل بيانات التدريب 
    x_train = ohe.transform(df_train[features])
    # تحويل بيانات التحقق
    x_valid = ohe.transform(df_valid[features])

    # تهئية النموذج الإنحدار اللولجيستي 
    model = linear_model.LogisticRegression()

    # تناسب النموذج على بيانات التدريب 
    model.fit(x_train, df_train.target.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.target.values, valid_preds)

    # auc طباعة 
    print(auc)

if __name__ == "__main__":
    run(0)

بالتالي ماذا حدث؟ أنشأ دالة تقسم البيانات إلى تدريب والتحقق ، بالنسبة لعدد الطيات المعطى ، وتعالج قيم NaN ، وتطبق خط الترميو الأحادي على جميع البيانات وتدرب نموذج الانحدار اللوجستي البسيط.

 عندما نقوم بتشغيل هذا الجزء الكود  ، فإنه ينتج مخرجات مثل هذا:

C:\Users\.....\anaconda3\lib\site-packages\sklearn\linear_model\_logistic.py:762: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  n_iter_i = _check_optimize_result(
0.7864687530013026

هناك بعض التحذيرات. يبدو أن الانحدار اللوجستي لم يتقارب مع الحد الأقصى لعدد التكرارات. لم نغير في المعايير ، لذلك لا بأس بذلك. نرى أن AUC هو ~ 0.786. 

دعنا نطبع هذا لجميع الطيات الآن بتغيير بسيط في الكود.

import pandas as pd
from sklearn import linear_model
from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/cat_train_folds.csv")

    # target , id, kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("id" , "target", "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # الحصول على بيانات التدريب بإستخدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)

    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # تهيئة خط الترميز الأحادي
    ohe = preprocessing.OneHotEncoder()

    # مناسبت خط الترميز الأحادي على سمات التدريب و التحقق
    full_data = pd.concat(
        [df_train[features], df_valid[features]],axis=0
    )

    ohe.fit (full_data[features])

    #  تحويل بيانات التدريب 
    x_train = ohe.transform(df_train[features])
    # تحويل بيانات التحقق
    x_valid = ohe.transform(df_valid[features])

    # تهئية النموذج الإنحدار اللولجيستي 
    model = linear_model.LogisticRegression()

    # تناسب النموذج على بيانات التدريب 
    model.fit(x_train, df_train.target.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.target.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




يرجى ملاحظة أننا لا نجري الكثير من التغييرات ، و هذا يعطي:

❯ python -W ignore ohe_logres.py
Fold = 0, AUC = 0.7847865042255127
Fold = 1, AUC = 0.7853553605899214
Fold = 2, AUC = 0.7879321942914885
Fold = 3, AUC = 0.7870315929550808
Fold = 4, AUC = 0.7864668243125608

لاحظ أنني أستخدم “-W ignore” لتجاهل جميع التحذيرات. نرى أن AUC مستقرة تمامًا في جميع الجوانب. متوسط ​​AUC هو 0.78631449527. جيد جدًا لنوذجنا الأول!

نموذج الغابة العشوائية 

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

import pandas as pd
from sklearn import ensemble
from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/cat_train_folds.csv")

    # target , id, kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("id" , "target", "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 

        # لكل عامود سمة  LabelEncoder تهيئة 
        lbl = preprocessing.LabelEncoder()

        #مناسبة ترميز السميات مع كل البيانات 
        lbl.fit(df[col])

        #تحويل جميع البيانات 
        df.loc[:, col] = lbl.transform(df[col])

     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # تهيئة نموذج الغابة العشوائية 
    model = ensemble.RandomForestClassifier(n_jobs=-1)

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.target.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.target.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




نحن نستخدم Random Forest من scikit-Learn وقمنا بالتخلص من خط الترميز الأحادي. و إستخدمنا  ترميز التسمية. النتائج هي كما يلي:

❯ python lbl_rf.py
Fold = 0, AUC = 0.7167390828113697
Fold = 1, AUC = 0.7165459672958506
Fold = 2, AUC = 0.7159709909587376
Fold = 3, AUC = 0.7161589664189556
Fold = 4, AUC = 0.7156020216155978

فرق كبير! نموذج الغابة العشوائية ، بدون أي ضبط للمعايير ، يؤدي أداءً أسوأ بكثير من الانحدار اللوجستي البسيط. 

وهذا سبب يجعلنا نبدأ دائمًا بالنماذج البسيطة أولاً. سيبدأ أحد محبي الغابة العشوائية بها هنا وسيتجاهل نموذج الانحدار اللوجستي معتقدًا أنه نموذج بسيط للغاية لا يمكنه تحقيق أي قيمة أفضل من الغابة العشوائية. هذا النوع من الأشخاص سيرتكب خطأ فادحًا. 

في تنفيذنا للغابة العشوائية ، تستغرق الطيات وقتًا أطول بكثير لإكمالها مقارنةً بالإنحدار اللوجستي. لذا ، فنحن لا نخسر فقط AUCولكننا نأخذ وقتًا أطول لإكمال التدريب. يرجى ملاحظة أن الاستدلال يستغرق أيضًا وقتًا طويلاً في الغابة العشوائية كما أنه يأخذ مساحة أكبر بكثير. 

إذا أردنا ، يمكننا أيضًا محاولة إستخدام الغابة العشوائية على بيانات متناثره مرمزه بإستخدام خط التنرميز الأحادي  ، ولكن هذا سيستغرق الكثير من الوقت. يمكننا أيضًا محاولة تقليل المصفوفات المرمزه لخط الترميز الأحادي  باستخدام تحلل القيمة المفرد (singular value decomposition) . هذه طريقة شائعة جدًا لاستخراج الموضوعات في معالجة اللغة الطبيعية.

import pandas as pd
from scipy import sparse
from sklearn import decomposition
from sklearn import ensemble
from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/cat_train_folds.csv")

    # target , id, kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("id" , "target", "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    
    # تهيئة خط الترميز الأحادي
    ohe = preprocessing.OneHotEncoder()

    # مناسبت خط الترميز الأحادي على سمات التدريب و التحقق
    full_data = pd.concat(
        [df_train[features], df_valid[features]],axis=0
    )

    ohe.fit (full_data[features])
    
    #  تحويل بيانات التدريب 
    x_train = ohe.transform(df_train[features])
    # تحويل بيانات التحقق
    x_valid = ohe.transform(df_valid[features])

    # SVD تهيئة 
    # نقوم بتقليل حجم البيانات إلى 120 عنصر
    svd = decomposition.TruncatedSVD(n_components=120)

    #مع مجموعة البيانات المتناثرة SVD مناسبة 
    full_sparse = sparse.vstack((x_train, x_valid))
    svd.fit(full_sparse)

    # تحويل بيانات  التدريب المتناثرة 
    x_train = svd.transform(x_train)

    #تحويل بيانات التحقق المتناثرة 
    x_valid = svd.transform(x_valid)

    # تهيئة نموذج الغابة العشوائية 
    model = ensemble.RandomForestClassifier(n_jobs=-1)

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.target.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.target.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




نقوم بترميز البيانات الكاملة بإستخدم خط الترميز الأحادي ثم نلائم TruncatedSVD من scikit-Learn على مصفوفة المتناثرة مع بيانات التدريب + التحقق. بهذه الطريقة ، نقوم بتقليل المصفوفة المتناثرة عالية الأبعاد إلى 120 سمة ثم نلائم مصنف الغابة العشوائي.

وهذه هي  ناتج هذا النموذج:

❯ python ohe_svd_rf.py
Fold = 0, AUC = 0.7064863038754249
Fold = 1, AUC = 0.706050102937374
Fold = 2, AUC = 0.7086069243167242
Fold = 3, AUC = 0.7066819080085971
Fold = 4, AUC = 0.7058154015055585

نرى أن الأمر أسوأ. يبدو أن أفضل طريقة لهذه المشكلة هي  بإستخدم خط الترميز الأحادي مع الانحدار اللوجستي. يبدو أن الغابة العشوائية تستغرق الكثير من الوقت. ربما يمكننا تجربة XGBoost.

نموذج XGBoost

 في حالة عدم معرفتك بـ XGBoost ، فهي واحدة من أشهر خوارزميات تعزيز الإشتقاق (gradient boosting ) . نظرًا لأنها خوارزمية مبنية على  الشجرة ، فسنستخدم ترميز التسمية على البيانات.

import pandas as pd
import xgboost as xgb

from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/cat_train_folds.csv")

    # target , id, kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("id" , "target", "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 

        # لكل عامود سمة  LabelEncoder تهيئة 
        lbl = preprocessing.LabelEncoder()

        #مناسبة ترميز السميات مع كل البيانات 
        lbl.fit(df[col])

        #تحويل جميع البيانات 
        df.loc[:, col] = lbl.transform(df[col])

     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
        max_depth=7,
        n_estimators=200
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.target.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.target.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




وتجدر الإشارة إلى أنه في هذا الكود ، قمت بتعديل عدة معايير لـ xgboost. إفتراضياً max_depth لـ xgboost هي 3 ، وقمت بتغييرها إلى 7 ، وقمت أيضًا بتغيير عدد المقدرات (n_estimators) من 100 إلى 200. 

الطيات الخمسة من هذا النموذج هي كما يلي:

 python lbl_xgb.py
Fold = 0, AUC = 0.7656768851999011
Fold = 1, AUC = 0.7633006564148015
Fold = 2, AUC = 0.7654277821434345
Fold = 3, AUC = 0.7663609758878182
Fold = 4, AUC = 0.764914671468069

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

مجموعة بيانات جديدة 

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

تحتوي مجموعة البيانات هذه على الأعمدة التالية:

• age

• workclass

• fnlwgt

• education

• education.num

• marital.status

• occupation

• relationship

• race

• sex

• capital.gain

• capital.loss

• hours.per.week

• native.country

• income

فلنبدأ ببناء النموذج نرى أن عمود الدخل عبارة عن سلسلة. فلنقم بحساب قيمة في هذا العمود.

In [X]: import pandas as pd
In [X]: df = pd.read_csv("../input/adult.csv")
In [X]: df.income.value_counts()
Out[X]:
<=50K 24720
>50K 7841

نرى أن هناك 7841 حالة بدخل أكبر من 50 ألف دولار أمريكي. يمثل هذا حوالي 24٪ من إجمالي عدد العينات. وبالتالي ، سنستخدم نفس التقييم المستخدم مع  مجموعة بيانات cat-in-the-dat ، أي AUC. 

قبل أن نبدأ في النمذجة ، من أجل التبسيط ، سنقوم بإسقاط بعض الأعمدة ، وهي عددية ، وهي:

• fnlwgt

• age

• capital.gain

• capital.loss

• hours.per.week

 نموذج الانحدار اللوجستي

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

import pandas as pd
from sklearn import linear_model
from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/adult_folds.csv")

    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]

    # إسقاط الأعمدة العددية
    df = df.drop(num_cols,axis=1)

    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50k": 0,
        ">50k" : 1
    }

    df.loc[:, "income"] = df.income.map(target_mapping)


    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]

    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # الحصول على بيانات التدريب بإستخدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)

    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # تهيئة خط الترميز الأحادي
    ohe = preprocessing.OneHotEncoder()

    # مناسبت خط الترميز الأحادي على سمات التدريب و التحقق
    full_data = pd.concat(
        [df_train[features], df_valid[features]],axis=0
    )

    ohe.fit (full_data[features])

    #  تحويل بيانات التدريب 
    x_train = ohe.transform(df_train[features])
    # تحويل بيانات التحقق
    x_valid = ohe.transform(df_valid[features])

    # تهئية النموذج الإنحدار اللولجيستي 
    model = linear_model.LogisticRegression()

    # تناسب النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




وعندما نقوم بتشغيل هذا  الكود ، نحصل على:

❯ python -W ignore ohe_logres.py
Fold = 0, AUC = 0.8794809708119079
Fold = 1, AUC = 0.8875785068274882
Fold = 2, AUC = 0.8852609687685753
Fold = 3, AUC = 0.8681236223251438
Fold = 4, AUC = 0.8728581541840037

هذا AUC جيد جدًا بالنسبة لنموذج بهذه البساطة!

نموذج xgboost

 لنجرب إستخدام ترميز التسمية مع  xgboost بدون ضبط أي من المعايير.

import pandas as pd
import xgboost as xgb

from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/adult_folds.csv")

   
    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]

    # إسقاط الأعمدة العددية
    df = df.drop(num_cols, axis=1)

    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50K": 0,
        ">50K" : 1
    }
    df.loc[:, "income"] = df.income.map(target_mapping)


    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]
    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 

        # لكل عامود سمة  LabelEncoder تهيئة 
        lbl = preprocessing.LabelEncoder()

        #مناسبة ترميز السميات مع كل البيانات 
        lbl.fit(df[col])

        #تحويل جميع البيانات 
        df.loc[:, col] = lbl.transform(df[col])

     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




و عند تشغيل هذا 

❯ python lbl_xgb.py
Fold = 0, AUC = 0.8800810634234078
Fold = 1, AUC = 0.886811884948154
Fold = 2, AUC = 0.8854421433318472
Fold = 3, AUC = 0.8676319549361007
Fold = 4, AUC = 0.8714450054900602

هذا يبدو جيدا بالفعل دعونا نرى النتائج عندما نزيد max_depth إلى 7 و n_estimators إلى 200.

❯ python lbl_xgb.py
Fold = 0, AUC = 0.8764108944332032
Fold = 1, AUC = 0.8840708537662638
Fold = 2, AUC = 0.8816601162613102
Fold = 3, AUC = 0.8662335762581732
Fold = 4, AUC = 0.8698983461709926

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

import pandas as pd
import xgboost as xgb

from sklearn import  metrics
from sklearn import  preprocessing

def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/adult_folds.csv")

   
    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]


    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50K": 0,
        ">50K" : 1
    }
    df.loc[:, "income"] = df.income.map(target_mapping)


    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]
    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        # لا نقوم بترميز الأعمدة العددية 
        if col not in num_cols:
            df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 

        # لكل عامود سمة  LabelEncoder تهيئة 
        lbl = preprocessing.LabelEncoder()

        #مناسبة ترميز السميات مع كل البيانات 
        lbl.fit(df[col])

        #تحويل جميع البيانات 
        df.loc[:, col] = lbl.transform(df[col])

     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)

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

يرجى ملاحظة أننا لا نحتاج إلى تسوية البيانات عندما نستخدم النماذج القائمة على الأشجار. ومع ذلك ، يعد هذا أمرًا ضروريا يجب القيام به عندما نستخدم نماذج خطية مثل الانحدار اللوجستي. 

دعونا نشغل هذا الكود !

 python lbl_xgb_num.py
Fold = 0, AUC = 0.9209790185449889
Fold = 1, AUC = 0.9247157449144706
Fold = 2, AUC = 0.9269329887598243
Fold = 3, AUC = 0.9119349082169275
Fold = 4, AUC = 0.9166408030141667

هذه نتيجة ممتازة!

الآن ، يمكننا محاولة إضافة بعض السمات. سنأخذ جميع الأعمدة الفئوية وننشئ مجموعات من  الدرجة الثانية. ألق نظرة على feature_engineering في المقتطف أدناه لمعرفة كيفية القيام بذلك.

import itertools
import pandas as pd
import xgboost as xgb

from sklearn import  metrics
from sklearn import  preprocessing

def feature_enginnering(df, cat_cols):
    
  """
  تُستخدم هذه الوظيفة في هندسة السمات
  : param df: إطار بيانات الباندا مع بيانات التدريب / الاختبار
  : param cat_cols: قائمة الأعمدة الفئوية
  : return: إطار البيانات مع سمات جديدة
  """
  # سيؤدي هذا إلى إنشاء  مجموعتين من القيم
  # في هذه القائمة
  # فمثلا:
  # سترجع list(itertools.combinations([1,2,3], 2)) 
  # [(1, 2), (1, 3), (2, 3)]
  combi = list(itertools.combinations(cat_cols,2))
  return
  for c1, c2 in combi:
      df.loc[
          :,
          c1 + "_" + c2
      ]  = df[c1].astype(str) + "_" + df[c2].astype(str)
  return df  


def run(fold):

    # تحميل بيانات التدريب مع الطيات 
    df = pd.read_csv("../input/adult_folds.csv")

   
    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]


    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50K": 0,
        ">50K" : 1
    }
    df.loc[:, "income"] = df.income.map(target_mapping)

    # قائمة بالإعمدة الفئوية في هندسة السمات 
    cat_cols = [
        c for c in df.columns if c not in num_cols
        and c not in ("kfold", "income")
    ]

    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]
    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        # لا نقوم بترميز الأعمدة العددية 
        if col not in num_cols:
            df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 
        if col not in num_cols:

            # لكل عامود سمة  LabelEncoder تهيئة 
            lbl = preprocessing.LabelEncoder()

            #مناسبة ترميز السميات مع كل البيانات 
            lbl.fit(df[col])

            #تحويل جميع البيانات 
            df.loc[:, col] = lbl.transform(df[col])

     # الحصول على بيانات التدريب بإستحدام الطيات
    df_train = df[df.kfold != fold].reset_index(drop = True)
    # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    for fold_ in range(5):
        run(fold_)




هذه طريقة بليده جدًا لإنشاء سمات من أعمدة فئوية. ينبغي للمرء أن يلقي نظرة على البيانات ومعرفة أي خليط أكثر منطقية. إذا كنت تستخدم هذه الطريقة ، فقد ينتهي بك الأمر إلى إنشاء الكثير من السمات ، وفي هذه الحالة ، ستحتاج إلى استخدام نوع من تحديد السمات لتحديد أفضل السمات .

دعونا نرى النتائج الآن.

 python lbl_xgb_num_feat.py
Fold = 0, AUC = 0.9211483465031423
Fold = 1, AUC = 0.9251499446866125
Fold = 2, AUC = 0.9262344766486692
Fold = 3, AUC = 0.9114264068794995
Fold = 4, AUC = 0.9177914453099201

يبدو أنه حتى بدون تغيير أي معايير وفقط عن طريق إضافة مجموعة من السمات ، يمكننا تحسين نتائجنا قليلاً. دعونا نرى ما إذا كانت زيادة max_depth إلى 7 مفيدة.

❯ python lbl_xgb_num_feat.py
Fold = 0, AUC = 0.9286668430204137
Fold = 1, AUC = 0.9329340656165378
Fold = 2, AUC = 0.9319817543218744
Fold = 3, AUC = 0.919046187194538
Fold = 4, AUC = 0.9245692057162671

ومرة أخرى ، تمكنا من تحسين نموذجنا. لاحظ أننا لم نستخدم بعد قيمًا نادرة ، أو سمات ثنائية ، أومجموعة من  السمات المرمزه بإستخدام خط الترميز الأحادي أو ترميز المسميات ….إلخ.

ترميز الهدف (target encoding)

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

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

هذا يعني أن أول شيء تفعله هو إنشاء الطيات ، ثم استخدام تلك الطيات لإنشاء سمات ترميز مستهدفة للأعمدة المختلفة في البيانات بنفس الطريقة التي تناسب فيها (fit) توقع النموذج مع الطيات. 

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

 يمكن اشتقاق الترميز المستهدف لبيانات الاختبار الي لم يتدرب عليها النموذج  من بيانات التدريب الكاملة أو يمكن أن يكون متوسط ​​جميع الطيات الخمسة. 

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

import copy
import pandas as pd

from sklearn import  metrics
from sklearn import  preprocessing
import xgboost as xgb

def mean_target_encoding(data):

    # عمل نسخة من إطار البيانات 
    df = copy.deepcopy(data)

    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]


    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50K": 0,
        ">50K" : 1
    }
    df.loc[:, "income"] = df.income.map(target_mapping)

   # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in num_cols
        and f not in ("kfold", "income")
    ]

    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]
    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        # لا نقوم بترميز الأعمدة العددية 
        if col not in num_cols:
            df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 
        if col not in num_cols:

            # لكل عامود سمة  LabelEncoder تهيئة 
            lbl = preprocessing.LabelEncoder()

            #مناسبة ترميز السميات مع كل البيانات 
            lbl.fit(df[col])

            #تحويل جميع البيانات 
            df.loc[:, col] = lbl.transform(df[col])
    encoded_dfs = []

    #إنشاء حلقة على كل الطيات
    for fold in range(5):
        # الحصول على بيانات التدريب و التحقق 
        df_train = df[df.kfold != fold].reset_index(drop = True)
        df_valid = df[df.kfold == fold].reset_index(drop = True)

        # لكل أعمدة السمات 
        for column in features :
            # إنشاء قاموس
            mapping_dict = dict(
                df_train.groupby(column)["income"].mean()
            )

            # هو العمود الجديد الذي لدينا مع متوسط الترميز column_enc
            df_valid.loc[
                :, column + "_enc"
            ] = df_valid[column].map(mapping_dict)
        # إضافة إلى القائمة إطار بيانات التحقق المرمبز
        encoded_dfs.append(df_valid)
    # إنشاء إطار بيانات كامل 
    encoded_dfs = pd.concat(encoded_dfs, axis=0)
    return encoded_dfs


def run(fold):

    # الحصول على البيانات في الطيات 
    df_train = df[df.kfold != fold].reset_index(drop=True)
     # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
        max_depth=7
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    # قراءة البيانات
    df = pd.read_csv("../input/adult_folds.csv")
    # إنشاء  متوسط ترميز الهدف للفئات 
    df = mean_target_encoding(df)
    
    # بدأ التدريب و التحقق في 5 طيات
    for fold_ in range(5):
        run(fold_)




وتجدر الإشارة إلى أنه في المقتطف أعلاه ، لم أتخلص من  الأعمدة الفئوية عندما أجرينا ترميز التهدف. احتفظت بجميع السمات وأضفت سمات ترميز الهدف فوقها. أيضا إستخدمت المتوسط (mean). يمكنك استخدام الانحراف المعياري أو المتوسط ​​أو أي وظيفة أخرى للأهداف. 

دعونا نرى النتائج.

Fold = 0, AUC = 0.9332240662017529
Fold = 1, AUC = 0.9363551625140347
Fold = 2, AUC = 0.9375013544556173
Fold = 3, AUC = 0.92237621307625
Fold = 4, AUC = 0.9292131180445478

جميل ! لدينا تحسن طفيف. ومع ذلك ، يجب أن تكون حذرًا للغاية عند استخدام ترميز الهدف لأنه عرضة جدًا لفرط التخصيص (overfitting) . عندما نستخدم ترميز الهدف ، فمن الأفضل استخدام نوع من التنعيم أو إضافة ضوضاء في القيم المشفرة. 

لدى Scikit-Learn  ترميز الهدف مع التنعيم ، أو يمكنك إنشاء التنعيم الخاص بك. يقدم التنعيم نوعًا من التنظيم الذي يساعد في عدم فرط تخصيص النموذج.

 يعتبر التعامل مع السمات الفئوية مهمة معقدة. هناك الكثير من المعلومات المتداولة في العديد من الموارد. و الهدف من هذه المقالة هو مساعدتك على البدء في أي مشكلة تتعلق بالمتغيرات الفئوية. 

ومع ذلك ، بالنسبة لمعظم المشاكل ، لن تحتاج إلى أي شيء أكثر من خط الترميز الأحادي و ترميز التسمية. و لتحسين النماذج بشكل أكبر ، قد تحتاج إلى المزيد!

الشبكات العصبية 

لا يمكننا إنهاء هذا المقالة دون استخدام شبكة عصبية على هذه البيانات. لذلك ، دعنا نلقي نظرة على تقنية تُعرف باسم تضمين الكيانات (entity embeddings) . يتم تمثيل الفئات كمتجهات . نحن نمثل الفئات بواسطة المتجهات في كل من أساليب الترميز الثنائي و خط الترميز الأحادي. ولكن ماذا لو كان لدينا عشرات الآلاف من الفئات. سيؤدي ذلك إلى إنشاء مصفوفات ضخمة وسيستغرق وقتًا طويلاً بالنسبة لنا لتدريب النماذج المعقدة. وبالتالي يمكننا تمثيلها بالمتجهات ذات القيم العائمة بدلاً من ذلك.

الفكرة بسيطة للغاية. لديك طبقة تضمين لكل سمة فئويه. لذلك ، يمكن الآن تعيين كل فئة في عمود إلى تضمين (مثل تعيين الكلمات لتضمينات في معالجة اللغة الطبيعية). ثم تقوم بإعادة تشكيل هذه التضمينات إلى أبعادها لجعلها مسطحة ثم تربط جميع المدخلات بالتضمينات . ثم أضف مجموعة من الطبقات الكثيفة وطبقة الإخراج ، وقد انتهيت.

 هذا سهل جدًا استخدام TF / Keras لتطبيق ذلك .

import copy
import pandas as pd

from sklearn import  metrics
from sklearn import  preprocessing
import xgboost as xgb

def mean_target_encoding(data):

    # عمل نسخة من إطار البيانات 
    df = copy.deepcopy(data)

    # قائمة بالأعمدة العددية 
    num_cols = [
        "fnlwgt",
        "age",
        "capital.gain",
        "capital.loss",
        "hours.per.week"
    ]


    #  تعيين الأهداف إلى 0   و 1 

    target_mapping = {
        "<=50K": 0,
        ">50K" : 1
    }
    df.loc[:, "income"] = df.income.map(target_mapping)

   # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in num_cols
        and f not in ("kfold", "income")
    ]

    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]
    # NONE بـ  NaN تعبئة جميع قيم 
    # strings سنحول جميع القيم إلى 
    # لن يؤثر هذا لأن بياناتنا فئويه
    for col in features:
        # لا نقوم بترميز الأعمدة العددية 
        if col not in num_cols:
            df.loc[:, col] = df[col].astype(str).fillna("NONE")
    
    # سنقوم اللأن بترميز تسميات السمات 
    for col in features: 
        if col not in num_cols:

            # لكل عامود سمة  LabelEncoder تهيئة 
            lbl = preprocessing.LabelEncoder()

            #مناسبة ترميز السميات مع كل البيانات 
            lbl.fit(df[col])

            #تحويل جميع البيانات 
            df.loc[:, col] = lbl.transform(df[col])
    encoded_dfs = []

    #إنشاء حلقة على كل الطيات
    for fold in range(5):
        # الحصول على بيانات التدريب و التحقق 
        df_train = df[df.kfold != fold].reset_index(drop = True)
        df_valid = df[df.kfold == fold].reset_index(drop = True)

        # لكل أعمدة السمات 
        for column in features :
            # إنشاء قاموس
            mapping_dict = dict(
                df_train.groupby(column)["income"].mean()
            )

            # هو العمود الجديد الذي لدينا مع متوسط الترميز column_enc
            df_valid.loc[
                :, column + "_enc"
            ] = df_valid[column].map(mapping_dict)
        # إضافة إلى القائمة إطار بيانات التحقق المرمبز
        encoded_dfs.append(df_valid)
    # إنشاء إطار بيانات كامل 
    encoded_dfs = pd.concat(encoded_dfs, axis=0)
    return encoded_dfs


def run(fold):

    # الحصول على البيانات في الطيات 
    df_train = df[df.kfold != fold].reset_index(drop=True)
     # الحصول على بيانات التحقق بإستحدام الطيات
    df_valid = df[df.kfold == fold].reset_index(drop = True)

    # income , kfold جميع الأعمدة هي سمات فيما عدا أعمدة 
    features = [
        f for f in df.columns if f not in ("income" , "kfold")
    ]

    # الحصول على بيانات التددريب 
    x_train = df_train[features].values

    # الحصول على بيانات التحقق 
    x_valid = df_valid[features].values
    
    # xgboost تهيئة نموذج 
    model = xgb.XGBClassifier(
        n_jobs=-1,
        max_depth=7
    )

    # مناسبة النموذج على بيانات التدريب 
    model.fit(x_train, df_train.income.values)

    # التنبو على بيانات التحقق
    # AUC سنحتاج إلى قيم الإحتمالات لأننا نحسب 
    valid_preds = model.predict_proba(x_valid)[:, 1]

    # AUC الحصول على نتيجة 
    auc=metrics.roc_auc_score(df_valid.income.values, valid_preds)

    # auc طباعة 
    print(f"Fold = {fold}, AUC = {auc}")

if __name__ == "__main__":
    # قراءة البيانات
    df = pd.read_csv("../input/adult_folds.csv")
    # إنشاء  متوسط ترميز الهدف للفئات 
    df = mean_target_encoding(df)
    
    # بدأ التدريب و التحقق في 5 طيات
    for fold_ in range(5):
        run(fold_)

ستلاحظ أن هذا النهج يعطي أفضل النتائج وهو أيضًا سريع للغاية إذا كان لديك GPU! يمكن أيضًا تحسين هذا بشكل أكبر ، ولا داعي للقلق بشأن هندسة السمات حيث تتعامل معها الشبكة العصبية من تلقاء نفسها. هذا بالتأكيد يستحق المحاولة عند التعامل مع مجموعة بيانات كبيرة من السمات الفئوية. عندما يكون حجم التضمين هو نفسه عدد الفئات الفريدة ، يكون لدينا خط ترميز أحادي. 

إضافة تعليق