Panda get_dummies против Sklearn OneHotEncoder() :: Каковы плюсы и минусы?
Я изучаю разные методы для преобразования категориальных переменных в числовые для классификаторов машинного обучения. Я наткнулся на метод pd.get_dummies
и sklearn.preprocessing.OneHotEncoder()
, и я хотел посмотреть, как они отличаются по производительности и использованию.
Я нашел учебное пособие по использованию OneHotEnocder()
в https://xgdgsc.wordpress.com/2015/03/20/note-on-using-onehotencoder-in-scikit-learn-to-work-on-categorical-features/, так как документация sklearn
не слишком полезна для этой функции. У меня такое чувство, что я делаю это неправильно... но
Можно ли объяснить плюсы и минусы использования pd.dummies
над sklearn.preprocessing.OneHotEncoder()
и наоборот? Я знаю, что OneHotEncoder()
дает вам разреженную матрицу, но кроме этого я не уверен как он используется и каковы преимущества по методу pandas
. Я использую его неэффективно?
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
Ответы
Ответ 1
OneHotEncoder
не может напрямую обрабатывать строковые значения. Если ваши номинальные функции являются строками, тогда вам нужно сначала отобразить их в целые числа.
pandas.get_dummies
- это нечто противоположное. По умолчанию он преобразует столбцы строк в одно горячее представление, если не указаны столбцы.
Ответ 2
Для машинного обучения вы почти наверняка захотите использовать sklearn.OneHotEncoder
. Для других задач, таких как простой анализ, вы можете использовать pd.get_dummies
, что немного удобнее.
Обратите внимание, что sklearn.OneHotEncoder
был обновлен в последней версии, так что он принимает строки для категориальных переменных, а также целые числа.
Суть в том, что кодировщик sklearn
создает функцию, которая сохраняется и затем может быть применена к новым наборам данных, которые используют те же категориальные переменные, с согласованными результатами.
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)
Обратите внимание, как мы применяем тот же кодер, который мы создали с помощью X_train
к новому набору данных X_test
.
Подумайте, что произойдет, если X_test
содержит уровни, отличные от X_train
для одной из его переменных. Например, допустим, что X_train["color"]
содержит только "red"
и "green"
, но в дополнение к ним, X_test["color"]
иногда содержит "blue"
.
Если мы используем pd.get_dummies
, X_test
будет заканчиваться дополнительным "color_blue"
которого у X_train
нет, и несоответствие, вероятно, нарушит наш код позже, особенно если мы подаем X_test
в модель sklearn
которой мы обучались X_train
.
И если мы хотим обрабатывать такие данные в производственной среде, где мы получаем один пример за раз, pd.get_dummies
не будет pd.get_dummies
.
С другой стороны, с помощью sklearn.OneHotEncoder
, после того как мы создали кодировщик, мы можем повторно использовать его для получения одного и того же результата каждый раз со столбцами только для "red"
и "green"
. И мы можем явно контролировать то, что происходит, когда он встречает новый уровень "blue"
: если мы думаем, что это невозможно, то мы можем сказать ему, чтобы он handle_unknown="error"
ошибку с handle_unknown="error"
; в противном случае мы можем сказать ему продолжить и просто установить красные и зеленые столбцы в 0, с handle_unknown="ignore"
.
Ответ 3
почему бы вам не кешировать или не сохранить столбцы как переменную col_list из полученного get_dummies, а затем использовать pd.reindex для выравнивания набора данных по сравнению с наборами тестовых данных.... пример:
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)