Unser One-Hot-Encoder erstellt ein Feature fĂŒr jede Ebene des ursprĂŒnglichen kategorialen Features:
from evalml.pipelines import OneHotEncoder
import pandas as pd
df = pd.DataFrame({"category": ["a", "b"], "number": [4,5 ]})
OneHotEncoder().fit_transform(df).to_dataframe()
Die Spalten category_a
und category_b
sind vollstĂ€ndig kollinear, was eine ĂŒberflĂŒssig macht. Dies könnte nachteilige Auswirkungen auf die Anpassung des SchĂ€tzers haben. Ich denke, wir sollten standardmĂ€Ăig einen löschen.
Zur Info @rpeck
đŻ % sollten wir die Negativ-Case-Spalte weglassen.
Wenn wir die OHE zuerst selbst machen, dann wird sklearn sie hoffentlich nicht erweitern. Wie Freddy sagte, können Sie sich dies so vorstellen, als wĂŒrden Sie zwei Spalten erzeugen, die eine perfekte KollinearitĂ€t aufweisen.
Es gibt zwei Probleme, die ich beim Erweitern einer BinÀrdatei in zwei Spalten statt in eine sehe:
@freddyaboulton F: Der obige Datenrahmen fĂŒr die OHE-Spalten zeigt sie als Floats an. Ist das wirklich wahr?
@rpeck Ja!
@freddyaboulton Was? Das ist seltsam. Ich habe noch nie etwas anderes als echte boolesche Werte oder 0/1-Ganzzahlen gesehen. Ich frage mich, wie die Baummodelle eigentlich damit umgehen. FĂŒr mich riecht es unangenehm.
Drittes Gesetz des Codes: Du sollst nicht machen == Vergleiche mit Floats
(ok, es sei denn, es ist mit Math.NaN
)
Hmm, ich dachte, wir machen das!
Ich stimme zu, wir sollten. Ich dachte, es wĂ€re nur ein Flag, das wir im zugrunde liegenden Impl setzen mĂŒssen.
@dsherry @freddyaboulton Es sieht so aus, als hĂ€tten wir UnterstĂŒtzung dafĂŒr ĂŒber unseren Parameter drop
, aber berĂŒcksichtigt nur Benutzereingaben und wird von unserem Impl nicht verwendet, daher verfolgt dieses Problem nur die Einstellung der Standardeinstellung fĂŒr drop
zu etwas anderem als None?
https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
Wir könnten entweder first
oder if_binary
wÀhlen, sind uns nicht sicher, was der richtige Anruf ist.
@angela97lin Sie haben Recht, dass es ausreichen wĂŒrde, den Standardwert zu Ă€ndern! Ich denke, first
ist der richtige Weg, da wir perfekt kollineare Merkmale vermeiden sollten, selbst wenn die Anzahl der Kategorien > 2 ist. Was denkst du
Habe ein bisschen hineingelesen und diesen Link gefunden: https://inmachineswetrust.com/posts/drop-first-columns/
Die zentralen Thesen:
Der erste Kommentar von RE durcheinander , weil der Effekt der einen ursprĂŒnglichen Quellspalte auf die beiden OHE-Spalten aufgeteilt wird. Freddys neue SHAP-Rollups gehen dies offensichtlich an. Aber Dinge wie Feature Importance und Partial Dependence Plots werden das Problem immer noch haben."
Dies ist fĂŒr binĂ€re FĂ€lle sinnvoll, aber in dem Fall, in dem wir mehrere Kategorien haben, wird das Löschen einer Spalte immer noch dieses Problem haben.
Vielleicht sollten wir dies nicht standardmĂ€Ăig tun, sondern make_pipeline
aktualisieren, um einen OHE mit first
als Parameter zu erstellen, wenn der SchÀtzer ein linearer Regressor ist?
Leider habe ich kein starkes VerstĂ€ndnis fĂŒr die zugrunde liegende Mathematik, um ein Urteil zu fĂ€llen, also wĂŒrde ich gerne Ihre Gedanken hören, @freddyaboulton @rpeck @dsherry
NachgesprÀch mit @rpeck @dsherry @chukarsten @jeremyliweishih
@angela97lin klingt nach einem guten RE-Standardverhalten. Ein weiterer Vorteil: Möglichkeit, dieses Standardverhalten ĂŒber die Komponentenparameter zu ĂŒberschreiben
@dsherry Wenn ich das richtig verstehe, haben Benutzer die Möglichkeit, dies zu ĂŒberschreiben, indem sie den Komponentenparameter manuell drop
(einem Parameter) aktualisieren.
Habe herumgegraben, um zu sehen, was notwendig war, um dies zu implementieren. Insbesondere war ich neugierig, wie schwierig es sein wĂŒrde, die Minderheitsklasse im binĂ€ren Fall immer zu entfernen.
Das Ergebnis dieses Grabens ist:
drop
(https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html) machbar zu sein. Nach dem Ausprobieren muss jedoch fĂŒr jede Spalte ein Indexwert angegeben werden. Daher der folgende Fehler, der versucht, die bei Index 0 angegebene Kategorie fĂŒr Spalte 0 und keine anderen Werte fĂŒr die Spalten 1 und 2 zu entfernen: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
Ich glaube, dies ist auch die HĂ€lfte dessen, was in dieser Ausgabe herausgestellt wird: https://github.com/scikit-learn/scikit-learn/issues/16511
Eine Alternative, die wir tun können, um dies zu unterstĂŒtzen, besteht darin, manuell zu verfolgen, welche Spalten und welche Werte wir wĂ€hrend der Anpassung löschen möchten. Ăbergeben Sie die Daten an scikit-learn. Beschneiden Sie dann die Spalten, die wir gespeichert und angegeben haben, dass wir sie löschen möchten. Dies erfordert jedoch einige logische Handhabung, um das Original (Merkmal, Wert) aus dem transformierten Spaltennamen zu ermitteln. (Wir haben diese Logik in get_feature_names
aber das hilft uns, die Spaltennamen zu verbinden, vorausgesetzt, dass nichts weggelassen werden sollte ...)
All dies soll sagen, dass vielleicht nur die Verwendung des Standard-Scikit-Learn if_binary
fĂŒr den Moment ausreicht, und wir können ein separates Problem einreichen, um immer die Minderheitsklasse zu verwenden. Ehrlich gesagt auch dafĂŒr, dass wir uns von der OHE-Implementierung von scikit-learn abwenden, da wir so viel daran arbeiten mussten.
NĂŒtzliche Ressourcen:
OHE-Dokument: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html
Code in scikit-learn verursacht InflexibilitÀt: https://github.com/scikit-learn/scikit-learn/blob/95119c13af77c76e150b753485c662b7c52a41a2/sklearn/preprocessing/_encoders.py#L338
Verwandtes Problem: https://github.com/scikit-learn/scikit-learn/issues/16511
Um if_binary
: scikit-learn erfordert, dass handle_unknown
error
. Dies passt nicht gut zu unseren top_n
Parametern, die alles auĂer den Top N Kategorien fallen lassen, weil die zu transformierenden Daten nicht wissen, was sie mit den neuen Kategorien anfangen sollen. Wie Becca in https://github.com/alteryx/evalml/pull/830 feststellte, mĂŒssten wir top_n
auf None setzen, damit diese Parameter funktionieren.
In diesem Sinne ist es vielleicht am besten, einfach unser eigenes Impl zu rollen đ€
Hilfreichster Kommentar
Drittes Gesetz des Codes: Du sollst nicht machen == Vergleiche mit Floats