Конвейер OrdinalEncoder ValueError Найдены неизвестные категории
Пожалуйста, успокойся на мне. Я переключаю карьеру на науку о данных и у меня нет опыта работы с CS или программирования - так что я могу делать что-то очень глупое. Я провел несколько часов безуспешно.
Цель: заставить конвейер работать с OrdinalEncoder.
Проблема: код не запускается с вызовом OrdinalEncoder. Это работает без OrdinalEncoder. Насколько я могу судить, я могу передать два аргумента: категории и dtype. Ни одна помощь.
Я передаю общедоступный набор данных о диабете в модель. Это проблема? IOW, передача функций высокой мощности в OrdinalEncoder вызывает проблему между данными поезда / теста после построения модели, т.е. тестовое разделение имеет значение, которое не имеет набор поездов?
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OrdinalEncoder
from sklearn.ensemble import RandomForestClassifier
pipe = Pipeline([
('imputer', SimpleImputer()),
('ordinal_encoder', OrdinalEncoder()),
('classifier', RandomForestClassifier(criterion='gini', n_estimators=100))])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Construct model
model = pipe.fit(X_train, y_train)
# Show results
print("Hold-out AUC score: %.3f" %roc_auc_score(model.predict_proba(X_test),y_test))
Вот ошибка, которую я получаю:
ValueError: Found unknown categories [17.0] in column 0 during transform
Что я делаю неправильно?
Настроить:
The scikit-learn version is 0.20.2.
3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43)
[Clang 6.0 (clang-600.0.57)]
sys.version_info(major=3, minor=7, micro=2, releaselevel='final', serial=0)
10 ответов
Ваша проблема в том, что модель обнаружила в тестовых данных значение, которого она не увидела в обучающих данных. Это хорошо. Вам просто нужно добавить аргумент handle_unknown в кодировщик.
Вам следует
fit
кодировщики и скейлеры к обучающим данным (но не к тестовым данным), а затем использовать их для
transform
как обучающие, так и тестовые данные. Таким образом, вы должны предусмотреть возможность непредвиденных значений в тестовых данных.
Это решит вашу проблему:
OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)
Обратите внимание, что для того, чтобы это работало, вы должны использовать Scikit Learn версии 0.24 или выше.
У меня была такая же проблема, я просто использовал
OneHotEncoder(handle_unknown='ignore')
вместо
OneHotEncoder()
и проблема была исправлена.
Я опаздываю в игру, но я попал на эту страницу, поэтому решил, что все равно отвечу.
Вы сказали в своем комментарии: "Внаборе данных о диабете слишком много значений во многих функциях для данного разделения теста / поезда, чтобы оба отражали все значения"
Эта ошибка возникает с кодировщиками, когда набор для тестирования содержит данные, которые не были просмотрены во время обучения.
Я не думаю, что OrdinalEncoder является правильным выбором в этой ситуации. Набор данных о диабете состоит из непрерывных, а не категориальных признаков. Как указано в документации для OrdinalEncoder
:
Входные данные для этого преобразователя должны быть массивом целых чисел или строк, обозначающих значения, принимаемые категориальными (дискретными) функциями.
При этом без дополнительного вывода данных трассировки или вашей настройки я не могу однозначно сказать, почему вы получаете ошибку, которую сделали. Мне удалось успешно разделить и выполнить вышеуказанный код, используя данные, загруженные с load_diabetes
функция. Я предполагаю, что в вашем случае вы каким-то образом упустили установку кодера с категорией "17.0", но опять же я бы не рекомендовал использовать категориальный кодер в этом случае.
У меня такая же ошибка во время ColumnTransformer()
я подозреваю, что это связано с тем, что кодировщик требует ввода в кодировщик 2D-массива.
Вы можете попробовать .apply(lambda x: [x])
или какую-то аналогичную функцию для ваших порядковых значений, чтобы повысить их обусловленность.
Я бы подумал о том, чтобы сохранить порядковые значения в виде файла json во время обучения и прочитать ту же кодировку во время тестирования. Любое новое значение, поступающее в набор тестовых данных, которое не видно, должно обрабатываться перед тестированием или оценкой.
У меня была та же проблема, кодировка X перед разделением на поезд и тестовый рабочий для меня. Кодирование перед разделением делает все категории регистрируемыми
В «Scikit Learn версии 0.24» порядковый кодировщик имеет два новых параметра:
handle_unknown{‘error’, ‘use_encoded_value’}, default=’error’
а также
unknown_value:{int or np.nan}, default=None
Что касается обоих параметров, в документации scikit-learn говорится:
Когда для параметра handle_unknown установлено значение use_encoded_value, этот параметр является обязательным и устанавливает закодированное значение неизвестных категорий. Оно должно отличаться от значений, используемых для кодирования любой из подходящих категорий. Если установлено значение np.nan, параметр dtype должен быть типом с плавающей запятой.
Использоватьfit_transform
вместоfit
илиtransform
. Это сработало для меня.