Evalml: One Hot Encoder: قم بإسقاط ميزة واحدة متكررة بشكل افتراضي للميزات ذات الفئتين

تم إنشاؤها على ٥ مارس ٢٠٢١  ·  14تعليقات  ·  مصدر: alteryx/evalml

يُنشئ برنامج التشفير الساخن الوحيد الخاص بنا ميزة لكل مستوى من مستويات الميزة الفئوية الأصلية:

from evalml.pipelines import OneHotEncoder
import pandas as pd
df = pd.DataFrame({"category": ["a", "b"], "number": [4,5 ]})
OneHotEncoder().fit_transform(df).to_dataframe()

image

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

تضمين التغريدة

enhancement

التعليق الأكثر فائدة

القانون الثالث للتشفير: يجب ألا تجري مقارنات مع العوامات

ال 14 كومينتر

💯٪ يجب أن نسقط عمود الحالة السلبية.

إذا قمنا بعمل OHE بأنفسنا أولاً ، فمن المأمول ألا تقوم sklearn بتوسيعها. كما قال فريدي ، يمكنك التفكير في هذا على أنه إنشاء عمودين لهما علاقة خطية متداخلة مثالية.

هناك مشكلتان أراها عند توسيع ثنائي إلى عمودين بدلاً من عمود واحد:

  1. مثل الأشكال الأخرى للعلاقة الخطية للميزات ، فإنه يفسد الكثير من الأشياء في القابلية للتفسير ، لأن تأثير عمود المصدر الأصلي واحد مقسم بين عمودي OHE. من الواضح أن مجموعات فريدي الجديدة من SHAP تعالج هذا الأمر ، ولكن أشياء مثل أهمية الميزة ومؤامرات الاعتماد الجزئي ستظل تواجه المشكلة.
  2. تقوم نماذج الشجرة مثل Random Forest و GBM بأخذ عينات عشوائية من ميزات الإدخال الخاصة بهم. سيتم أخذ عينات من عمود المصدر في هذه الحالة بشكل عشوائي مرتين كما ينبغي ، لذلك يمكن أن يكون لها تأثير كبير على النموذج.

freddyaboulton س: يُظهر إطار البيانات أعلاه لأعمدة OHE أنها عائمة. هل هذا حقا صحيح؟

rpeck نعم!

freddyaboulton Whatthe؟ هذا غريب. لم أر أبدًا أي شيء سوى القيم المنطقية الحقيقية ، أو 0/1 أعداد صحيحة. أتساءل كيف تتعامل النماذج الشجرية مع هذا الأمر. لها رائحة كريهة بالنسبة لي.

القانون الثالث للتشفير: يجب ألا تجري مقارنات مع العوامات

(حسنًا ، ما لم يكن بـ Math.NaN )

حسنًا ، اعتقدت أننا نفعل هذا!

أوافق على أننا يجب. اعتقدت أنه كان مجرد علم كان علينا وضعه في الضمنية الأساسية.

dsherryfreddyaboulton يبدو أننا يكون الدعم له من خلال موقعنا drop المعلمة ولكنه يأخذ فقط إلى إدخال المستخدم نظر فيها ولا يستخدم من قبل impl لدينا حتى هذه المسألة مسارات مجرد وضع الافتراضي drop لشيء آخر غير لا شيء؟

https://github.com/alteryx/evalml/blob/91775ffc26c47205adc0fb255832d828ead6e7c9/evalml/pipelines/components/transformers/encoders/onehot_encoder.py#L28

https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html

يمكننا إما استخدام first أو if_binary ، لست متأكدًا من المكالمة الصحيحة.

@ angela97lin أنت محق في أن تغيير القيمة الافتراضية سيكون كافيًا! أعتقد أن first هو الطريق الذي يجب اتباعه حيث يجب علينا تجنب الميزات الخطية تمامًا حتى عندما يكون عدد الفئات> 2. ما رأيك في

كنت تقرأ هذا قليلاً ووجدت هذا الرابط: https://inmachineswetrust.com/posts/drop-first-columns/

الماخذ الرئيسية:

  • مطلوب إسقاط الأعمدة فقط عند إنشاء نموذج OLS بدون تنظيم (أعتقد أن الانحدار الخطي يقع ضمن هذه الفئة: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html، https: // scikit-learn.org/stable/modules/linear_model.html#ordinary-least-squares)
  • يؤدي إسقاط الأعمدة المشفرة ذات درجة حرارة واحدة إلى تغيير معلمات وتوقعات نموذج الانحدار الخطي ، مما يؤثر على النموذج الذي تم إرجاعه. ومع ذلك ، يصعب علي تحديد ما إذا كان هذا للأفضل أم لا.

التعليق الأول لـ RErpeck : "مثل الأشكال الأخرى من العلاقة الخطية فإنه يفسد الكثير من الأشياء في قابلية التفسير ، لأن تأثير عمود المصدر الأصلي واحد مقسم بين عمودين OHE. مجموعات SHAP الجديدة لـ Freddy تعالج هذا ، من الواضح ، لكن أشياء مثل "أهمية الميزة" و "الاعتماد الجزئي" ستظل تواجه المشكلة ".

هذا منطقي بالنسبة للحالات الثنائية ، ولكن في حالة وجود فئات متعددة ، فإن إسقاط عمود واحد سيظل يعاني من هذه المشكلة.

ربما لا ينبغي علينا القيام بذلك افتراضيًا ، ولكن يجب تحديث make_pipeline لإنشاء OHE باستخدام first كمعامل إذا كان المقدر هو منحدر خطي؟

للأسف، وأنا لم يكن لديك فهم قوي في الرياضيات الأساسية لجعل الحكم لذلك أنا أحب أن أسمع أفكارك،freddyaboultonrpeckdsherry

بعد مناقشة معfreddyaboultonrpeckdsherrychukarstenjeremyliweishih

  • سنفعل هذا فقط للحالات الثنائية.
  • "من الأفضل أن يكون لديك" ، في الحالة الثنائية ، هو فئة الأقلية ، ولكن بخلاف ذلك ، يكفي اختيار واحدة من الفئتين.

@ angela97lin تبدو جيدة السلوك الافتراضي RE. من الجيد امتلاكها: القدرة على تجاوز هذا السلوك الافتراضي عبر معلمات المكون

dsherry إذا فهمت بشكل صحيح ، نظرًا لأننا نقوم بتحديث القيمة الافتراضية drop (معلمة) ، سيكون لدى المستخدمين القدرة على تجاوز ذلك عن طريق تعيين معلمة المكون يدويًا؟

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

وكانت نتيجة هذا الحفر:

  • مع scikit-Learn ، من الصعب تحديد الفئة المراد إزالتها. من الوثائق ، يبدو هذا ممكنًا عبر خيار المصفوفة للمعامل drop (https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html). ومع ذلك ، بعد تجربته ، فإنه يتطلب تحديد قيمة فهرس لكل عمود. ومن ثم ، فإن ما يلي ، والذي يحاول إزالة الفئة المحددة في الفهرس 0 للعمود 0 ولا توجد قيم أخرى لأخطاء العمودين 1 و 2:
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

X = pd.DataFrame({'col_1': ["a", "b", "b", "a", "b"],
                      'col_2': ["a", "b", "a", "c", "b"],
                      'col_3': ["a", "a", "a", "a", "a"]})

indices_to_drop = np.array([0, None, None])

ohe = OneHotEncoder(drop=indices_to_drop)
ohe.fit(X)
ValueError                                Traceback (most recent call last)
<ipython-input-4-a099fa2fc4a7> in <module>
----> 1 ohe.fit(X)

~/Desktop/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders.py in fit(self, X, y)
    417         self._fit(X, handle_unknown=self.handle_unknown,
    418                   force_all_finite='allow-nan')
--> 419         self.drop_idx_ = self._compute_drop_idx()
    420         return self
    421 

~/Desktop/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders.py in _compute_drop_idx(self)
    394                                 ["Category: {}, Feature: {}".format(c, v)
    395                                     for c, v in missing_drops])))
--> 396                 raise ValueError(msg)
    397             return np.array(drop_indices, dtype=object)
    398 

ValueError: The following categories were supposed to be dropped, but were not found in the training data.
Category: 0, Feature: 0
Category: 1, Feature: None
Category: 2, Feature: None

أعتقد أن هذا أيضًا نصف ما تشير إليه هذه المشكلة: https://github.com/scikit-learn/scikit-learn/issues/16511

البديل الذي يمكننا القيام به لدعم ذلك هو تتبع الأعمدة يدويًا والقيم التي نريد إسقاطها أثناء التركيب. قم بتمرير البيانات إلى scikit-Learn. بعد ذلك ، قم بقص الأعمدة التي قمنا بتخزينها وتحديدها التي أردنا إسقاطها. ومع ذلك ، يتطلب هذا بعض المعالجة المنطقية لتحديد الأصل (الميزة ، القيمة) من اسم العمود المحول. (لدينا هذا المنطق في get_feature_names لكن هذا يساعدنا على توصيل أسماء الأعمدة على افتراض أنه لا يجب إسقاط أي شيء ...)

كل هذا يعني ، ربما يكفي استخدام scikit-Learn الافتراضي if_binary في الوقت الحالي ، ويمكننا تقديم مشكلة منفصلة لاستخدام فئة الأقلية دائمًا. بصراحة أيضًا لصالح الابتعاد عن تطبيق OHE الخاص بـ scikit-Learn نظرًا لمقدار ما كان علينا العمل عليه.

موارد مفيدة:
مستند OHE: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
الكود في scikit-Learn يسبب عدم المرونة: https://github.com/scikit-learn/scikit-learn/blob/95119c13af77c76e150b753485c662b7c52a41a2/sklearn/preprocessing/_encoders.py#L338
المشكلة ذات الصلة: https://github.com/scikit-learn/scikit-learn/issues/16511


لاستخدام if_binary : يتطلب scikit-learn أن يكون handle_unknown هو error . هذا لا يعمل بشكل جيد مع معلماتنا top_n ، والتي تسقط كل شيء ما عدا الفئات N لأن البيانات المراد تحويلها لن تعرف ما يجب فعله بالفئات الجديدة. كما لاحظت Becca في https://github.com/alteryx/evalml/pull/830 ، سيتعين علينا تعيين top_n إلى لا شيء حتى تعمل هذه المعلمات.

مع وضع ذلك في الاعتبار ، ربما يكون من الأفضل أن نلفك الضمني الخاص بنا 🤔

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات