Wenn a sklearn.LabelEncoder
in ein Trainingsset eingebaut wurde, kann es brechen, wenn es bei Verwendung in einem Testset auf neue Werte stößt.
Die einzige Lösung, die ich dafür finden könnte, besteht darin, alles Neue im Testsatz (dh keine zu einer vorhandenen Klasse gehörend) zuzuordnen "<unknown>"
und anschließend explizit eine entsprechende Klasse hinzuzufügen LabelEncoder
:
# train and test are pandas.DataFrame's 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])
Das funktioniert, aber gibt es eine bessere Lösung?
Aktualisieren
Wie @sapo_cosmico in einem Kommentar hervorhebt, scheint das oben Gesagte nicht mehr zu funktionieren, da ich davon ausgehe, dass es sich um eine Implementierungsänderung handelt LabelEncoder.transform
, die jetzt zu verwenden scheint np.searchsorted
(ich weiß nicht, ob dies zuvor der Fall war). Anstatt die <unknown>
Klasse an die LabelEncoder
Liste der bereits extrahierten Klassen anzuhängen, muss sie in sortierter Reihenfolge eingefügt werden:
import bisect
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, '<unknown>')
le.classes_ = le_classes
Da sich dies jedoch insgesamt ziemlich klobig anfühlt, bin ich mir sicher, dass es dafür einen besseren Ansatz gibt.