Uczę się różnych metod konwersji zmiennych kategorialnych na numeryczne dla klasyfikatorów uczenia maszynowego. Natknąłem się na tę pd.get_dummies
metodę i sklearn.preprocessing.OneHotEncoder()
chciałem zobaczyć, jak różnią się pod względem wydajności i użytkowania.
Znalazłem poradnik, jak używać OneHotEncoder()
na https://xgdgsc.wordpress.com/2015/03/20/note-on-using-onehotencoder-in-scikit-learn-to-work-on-categorical-features/ od sklearn
dokumentacja nie był zbyt pomocny w tej funkcji. Mam wrażenie, że nie robię tego poprawnie ... ale
Czy ktoś może wyjaśnić zalety i wady używania w pd.dummies
kółko sklearn.preprocessing.OneHotEncoder()
i na odwrót? Wiem, że OneHotEncoder()
daje to rzadką matrycę, ale poza tym nie jestem pewien, jak jest używana i jakie są korzyści z tej pandas
metody. Czy używam go nieefektywnie?
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
sns.set()
%matplotlib inline
#Iris Plot
iris = load_iris()
n_samples, m_features = iris.data.shape
#Load Data
X, y = iris.data, iris.target
D_target_dummy = dict(zip(np.arange(iris.target_names.shape[0]), iris.target_names))
DF_data = pd.DataFrame(X,columns=iris.feature_names)
DF_data["target"] = pd.Series(y).map(D_target_dummy)
#sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
#0 5.1 3.5 1.4 0.2
#1 4.9 3.0 1.4 0.2
#2 4.7 3.2 1.3 0.2
#3 4.6 3.1 1.5 0.2
#4 5.0 3.6 1.4 0.2
#5 5.4 3.9 1.7 0.4
DF_dummies = pd.get_dummies(DF_data["target"])
#setosa versicolor virginica
#0 1 0 0
#1 1 0 0
#2 1 0 0
#3 1 0 0
#4 1 0 0
#5 1 0 0
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
def f1(DF_data):
Enc_ohe, Enc_label = OneHotEncoder(), LabelEncoder()
DF_data["Dummies"] = Enc_label.fit_transform(DF_data["target"])
DF_dummies2 = pd.DataFrame(Enc_ohe.fit_transform(DF_data[["Dummies"]]).todense(), columns = Enc_label.classes_)
return(DF_dummies2)
%timeit pd.get_dummies(DF_data["target"])
#1000 loops, best of 3: 777 µs per loop
%timeit f1(DF_data)
#100 loops, best of 3: 2.91 ms per loop
OneHotEncoder
nie można jej również zastosować do stringów w wersji 0.20.0.OneHotEncoder(sparse=False).fit_transform(pd.DataFrame(pd.Series(['good','bad','worst','good', 'good', 'bad'])))
działa, co oznacza, żeOneHotEncoder
może być stosowany do mieszania.pd.get_dummies
.W przypadku uczenia maszynowego prawie na pewno chcesz użyć
sklearn.OneHotEncoder
. W przypadku innych zadań, takich jak proste analizy, możesz użyćpd.get_dummies
, co jest nieco wygodniejsze.Zauważ, że
sklearn.OneHotEncoder
został zaktualizowany w najnowszej wersji, więc akceptuje ciągi znaków dla zmiennych kategorialnych, jak również liczby całkowite.Sednem tego jest to, że
sklearn
koder tworzy funkcję, która jest trwała i może być następnie zastosowana do nowych zestawów danych, które używają tych samych zmiennych kategorialnych, ze spójnymi wynikami .from sklearn.preprocessing import OneHotEncoder # Create the encoder. encoder = OneHotEncoder(handle_unknown="ignore") encoder.fit(X_train) # Assume for simplicity all features are categorical. # Apply the encoder. X_train = encoder.transform(X_train) X_test = encoder.transform(X_test)
Zwróć uwagę, jak stosujemy ten sam koder, który utworzyliśmy,
X_train
do nowego zestawu danychX_test
.Zastanów się, co się stanie, jeśli
X_test
zawiera inne poziomy niżX_train
dla jednej z jego zmiennych. Na przykład, powiedzmy, żeX_train["color"]
zawiera tylko"red"
i"green"
, ale oprócz nichX_test["color"]
czasami zawiera"blue"
.Jeśli używamy
pd.get_dummies
,X_test
skończy się z dodatkową"color_blue"
kolumnę, któraX_train
nie ma, a niespójność prawdopodobnie złamać nasz kod później, zwłaszcza jeśli mamy do karmieniaX_test
dosklearn
modelu, które ćwiczyliśmy naX_train
.A jeśli chcemy przetwarzać takie dane w środowisku produkcyjnym, w którym otrzymujemy pojedynczy przykład na raz,
pd.get_dummies
nie będą przydatne.Z
sklearn.OneHotEncoder
drugiej strony, kiedy już stworzymy koder, możemy go ponownie użyć do generowania tego samego wyjścia za każdym razem, z kolumnami tylko dla"red"
i"green"
. I możemy wyraźnie kontrolować, co się dzieje, gdy napotyka nowy poziom"blue"
: jeśli uważamy, że to niemożliwe, możemy powiedzieć mu, aby zgłosił błądhandle_unknown="error"
; w przeciwnym razie możemy nakazać mu kontynuowanie i po prostu ustawić czerwone i zielone kolumny na 0, używająchandle_unknown="ignore"
.źródło
dlaczego nie chcesz po prostu buforować lub zapisywać kolumn jako zmiennej col_list z otrzymanych get_dummies, a następnie użyć pd.reindex, aby wyrównać pociąg z testowymi zestawami danych ... przykład:
df = pd.get_dummies(data) col_list = df.columns.tolist() new_df = pd.get_dummies(new_data) new_df = new_df.reindex(columns=col_list).fillna(0.00)
źródło
Naprawdę podoba mi się odpowiedź Carla i zagłosowałem za nią. Po prostu rozszerzę nieco przykład Carla, aby więcej ludzi, miejmy nadzieję, doceni fakt, że pd.get_dummies poradzi sobie z nieznanymi. Dwa poniższe przykłady pokazują, że pd.get_dummies może osiągnąć to samo w obsłudze nieznanych elementów, jak OHE.
# data is from @dzieciou's comment above >>> data =pd.DataFrame(pd.Series(['good','bad','worst','good', 'good', 'bad'])) # new_data has two values that data does not have. >>> new_data= pd.DataFrame( pd.Series(['good','bad','worst','good', 'good', 'bad','excellent', 'perfect']))
Korzystanie z pd.get_dummies
>>> df = pd.get_dummies(data) >>> col_list = df.columns.tolist() >>> print(df) 0_bad 0_good 0_worst 0 0 1 0 1 1 0 0 2 0 0 1 3 0 1 0 4 0 1 0 5 1 0 0 6 0 0 0 7 0 0 0 >>> new_df = pd.get_dummies(new_data) # handle unknow by using .reindex and .fillna() >>> new_df = new_df.reindex(columns=col_list).fillna(0.00) >>> print(new_df) # 0_bad 0_good 0_worst # 0 0 1 0 # 1 1 0 0 # 2 0 0 1 # 3 0 1 0 # 4 0 1 0 # 5 1 0 0 # 6 0 0 0 # 7 0 0 0
Korzystanie z OneHotEncoder
>>> encoder = OneHotEncoder(handle_unknown="ignore", sparse=False) >>> encoder.fit(data) >>> encoder.transform(new_data) # array([[0., 1., 0.], # [1., 0., 0.], # [0., 0., 1.], # [0., 1., 0.], # [0., 1., 0.], # [1., 0., 0.], # [0., 0., 0.], # [0., 0., 0.]])
źródło