Evalml: لا يمكن احتواء Imputer عندما لا يكون هناك أي شيء في عمود فئوي أو منطقي

تم إنشاؤها على ١٩ أغسطس ٢٠٢٠  ·  3تعليقات  ·  مصدر: alteryx/evalml

الناسخ

from evalml.pipelines.components import Imputer
df = pd.DataFrame({"a": [1, 2, 3], "b": ["1", "2", None]})
imputer = Imputer()
imputer.fit(df)
from evalml.pipelines.components import Imputer
df_with_bool = pd.DataFrame({"a": [1, 2, 3], "b": [True, False, None]})
imputer = Imputer()
imputer.fit(df_with_bool)

كلاهما لهما نفس التتبع المكدس:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-69-9af4cfc17aec> in <module>
      1 df_with_bool = pd.DataFrame({"a": [1, 2, 3], "b": [True, False, None]})
      2 imputer = Imputer()
----> 3 imputer.fit(df_with_bool)

~/sources/evalml/evalml/utils/base_meta.py in _set_fit(self, X, y)
     12         @wraps(method)
     13         def _set_fit(self, X, y=None):
---> 14             return_value = method(self, X, y)
     15             self._is_fitted = True
     16             return return_value

~/sources/evalml/evalml/pipelines/components/transformers/imputers/imputer.py in fit(self, X, y)
     76         X_categorical = X_null_dropped.select_dtypes(include=categorical_dtypes + boolean)
     77         if len(X_categorical.columns) > 0:
---> 78             self._categorical_imputer.fit(X_categorical, y)
     79             self._categorical_cols = X_categorical.columns
     80         return self

~/sources/evalml/evalml/utils/base_meta.py in _set_fit(self, X, y)
     12         @wraps(method)
     13         def _set_fit(self, X, y=None):
---> 14             return_value = method(self, X, y)
     15             self._is_fitted = True
     16             return return_value

~/sources/evalml/evalml/pipelines/components/transformers/imputers/simple_imputer.py in fit(self, X, y)
     42         if not isinstance(X, pd.DataFrame):
     43             X = pd.DataFrame(X)
---> 44         self._component_obj.fit(X, y)
     45         self._all_null_cols = set(X.columns) - set(X.dropna(axis=1, how='all').columns)
     46         return self

~/miniconda3/envs/evalml/lib/python3.8/site-packages/sklearn/impute/_base.py in fit(self, X, y)
    300                                                     fill_value)
    301         else:
--> 302             self.statistics_ = self._dense_fit(X,
    303                                                self.strategy,
    304                                                self.missing_values,

~/miniconda3/envs/evalml/lib/python3.8/site-packages/sklearn/impute/_base.py in _dense_fit(self, X, strategy, missing_values, fill_value)
    384                 row_mask = np.logical_not(row_mask).astype(np.bool)
    385                 row = row[row_mask]
--> 386                 most_frequent[i] = _most_frequent(row, np.nan, 0)
    387 
    388             return most_frequent

~/miniconda3/envs/evalml/lib/python3.8/site-packages/sklearn/impute/_base.py in _most_frequent(array, extra_value, n_repeat)
     40             # has already been NaN-masked.
     41             warnings.simplefilter("ignore", RuntimeWarning)
---> 42             mode = stats.mode(array)
     43 
     44         most_frequent_value = mode[0][0]

~/miniconda3/envs/evalml/lib/python3.8/site-packages/scipy/stats/stats.py in mode(a, axis, nan_policy)
    498     counts = np.zeros(a_view.shape[:-1], dtype=np.int)
    499     for ind in inds:
--> 500         modes[ind], counts[ind] = _mode1D(a_view[ind])
    501     newshape = list(a.shape)
    502     newshape[axis] = 1

~/miniconda3/envs/evalml/lib/python3.8/site-packages/scipy/stats/stats.py in _mode1D(a)
    485 
    486     def _mode1D(a):
--> 487         vals, cnts = np.unique(a, return_counts=True)
    488         return vals[cnts.argmax()], cnts.max()
    489 

<__array_function__ internals> in unique(*args, **kwargs)

~/miniconda3/envs/evalml/lib/python3.8/site-packages/numpy/lib/arraysetops.py in unique(ar, return_index, return_inverse, return_counts, axis)
    259     ar = np.asanyarray(ar)
    260     if axis is None:
--> 261         ret = _unique1d(ar, return_index, return_inverse, return_counts)
    262         return _unpack_tuple(ret)
    263 

~/miniconda3/envs/evalml/lib/python3.8/site-packages/numpy/lib/arraysetops.py in _unique1d(ar, return_index, return_inverse, return_counts)
    320         aux = ar[perm]
    321     else:
--> 322         ar.sort()
    323         aux = ar
    324     mask = np.empty(aux.shape, dtype=np.bool_)

TypeError: '<' not supported between instances of 'NoneType' and 'bool'

يعمل هذا عندما يكون np.nan بدلاً من None

bug

ال 3 كومينتر

freddyaboulton شكرا

مشكلة
إذا كانت أي ميزة في إطار بيانات الباندا لها نوع object وتحتوي على قيمة None ، فسيخفق Imputer .

  1. ينشئ X = pd.DataFrame({'feature1': [False, True, None, np.nan]}) ميزة بنوع object . فشل Imputer.fit .
  2. ينشئ X = pd.DataFrame({'feature1': [False, True, np.nan]}) ميزة بنوع object . Imputer.fit يعمل.
  3. ينشئ X = pd.DataFrame({'feature1': [False, True]}) ميزة بنوع bool . Imputer.fit يعمل.

وينطبق الشيء نفسه على النوع category . يحدث موقف مماثل لأنواع السلاسل ، على الرغم من أن الحالة الأخيرة لا تنطبق.

ملاحظات
الشيء المربك هنا هو أن None يمكن أن يعني أشياء مختلفة. يمكن أن تكون مماثلة لـ nan ، أو يمكن أن تكون فئة خاصة بها.

أعتقد أنه من الجيد معاملتها على أنها nan طالما قمنا بتوثيق وشرح هذه الاتفاقية.

الحل
تنظيف None من ميزات bool / category / string: df = df.fillna(value=np.nan)

يصلح
المدى القصير:

  • قم بتحديث Imputer لاستبدال None بـ np.nan
  • تحديث Imputer API doc و automl دليل المستخدم لذكر ذلك.
  • أضف تغطية اختبارية Imputer مع تضمين None في البيانات ، لجميع أنواع البيانات المقصودة.

يمكننا بدلاً من ذلك إضافة DataCheck والذي يحتوي على أخطاء إذا كان هناك None s في البيانات. ولكن هذا غير ضروري لأنه يمكن تحويل None s بسهولة.

طويل الأمد:
بمجرد تحديث Evalml لاستخدام بنية البيانات الجديدة DataTable ، سيتمكن المستخدمون من تكوين أنواع كل ميزة في وقت مبكر. آمل أن يعني هذا أن التوحيد القياسي سيجعل هذه الأنواع من الأخطاء غير ذات صلة.

هل هذا متعلق بالرقم 540؟

@ angela97lin 🤦 100٪ مرتبط ... في الحقيقة إنه نسخة مزدوجة. هاها. حتى أننا قررنا أن يقوم الحاجب بتحويل None s إلى np.nan s.

إغلاق # 540 لصالح هذا لأن عمليات الكتابة هنا أكثر حداثة.

شكرا لك!

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