Если sklearn.LabelEncoder
установлен на обучающем наборе, он может сломаться, если он встретит новые значения при использовании в тестовом наборе.
Единственное решение, которое я мог бы предложить для этого, - сопоставить все новое в тестовом наборе (т.е. Не принадлежащее к существующему классу) до "<unknown>"
, а затем явно добавить соответствующий класс в LabelEncoder
:
# train and test are pandas.DataFrame and c is whatever column
le = LabelEncoder()
le.fit(train[c])
test[c] = test[c].map(lambda s: '<unknown>' if s not in le.classes_ else s)
le.classes_ = np.append(le.classes_, '<unknown>')
train[c] = le.transform(train[c])
test[c] = le.transform(test[c])
Это работает, но есть ли лучшее решение?
Обновить
Как замечает @sapo_cosmico в комментарии, кажется, что выше не работает больше, учитывая то, что я предполагаю, это изменение реализации в LabelEncoder.transform
, которое теперь, похоже, использует np.searchsorted
(я не знаю, было ли это случай раньше). Поэтому вместо добавления класса <unknown>
в список уже выделенных классов LabelEncoder
его необходимо вставить в отсортированном порядке:
import bisect
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, '<unknown>')
le.classes_ = le_classes
Однако, поскольку это кажется довольно неуклюжим в целом, я уверен, что для этого есть лучший подход.