scikit learn - labelencoder - Problema con OneHotEncoder para características categóricas
onehotencoder examples (6)
Quiero codificar 3 características categóricas de 10 características en mis conjuntos de datos. Uso el preprocessing
de sklearn.preprocessing para hacerlo de la siguiente manera:
from sklearn import preprocessing
cat_features = [''color'', ''director_name'', ''actor_2_name'']
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)
Sin embargo, no pude proceder ya que estoy recibiendo este error:
array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: could not convert string to float: PG
¡¡Me sorprende que se queje de la cadena porque se supone que la convierte !! ¿Me estoy perdiendo de algo?
@Medo,
Encontré el mismo comportamiento y lo encontré frustrante. Como han señalado otros, Scikit-Learn requiere que todos los datos sean numéricos antes de que incluso considere la selección de las columnas proporcionadas en el parámetro categorical_features
.
Específicamente, la selección de la columna es manejada por el método _transform_selected()
en /sklearn/preprocessing/data.py y la primera línea de ese método es
X = check_array(X, accept_sparse=''csc'', copy=copy, dtype=FLOAT_DTYPES)
.
Esta comprobación falla si alguno de los datos en el marco de datos X
proporcionado no se puede convertir con éxito en un flotador.
Estoy de acuerdo en que la documentación de sklearn.preprocessing.OneHotEncoder es muy engañosa en ese sentido.
De la documentación:
categorical_features : “all” or array of indices or mask
Specify what features are treated as categorical.
‘all’ (default): All features are treated as categorical.
array of indices: Array of categorical feature indices.
mask: Array of length n_features and with dtype=bool.
los nombres de columna de los datos de pandas no funcionarán. Si sus características categóricas son los números de columna 0, 2 y 6 use:
from sklearn import preprocessing
cat_features = [0, 2, 6]
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)
También se debe tener en cuenta que si estas características categóricas no están codificadas por etiquetas, debe usar LabelEncoder
en estas características antes de usar OneHotEncoder
Hay una solución simple si, como yo, te sientes frustrado por esto. Simplemente use el codificador de categoría OneHotEncoder . Este es un paquete de Sklearn Contrib, por lo que se reproduce muy bien con la API scikit-learn.
Esto funciona como un reemplazo directo y hace la codificación de la etiqueta aburrida para usted.
from category_encoders import OneHotEncoder
cat_features = [''color'', ''director_name'', ''actor_2_name'']
enc = OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)
Puede aplicar ambas transformaciones (de las categorías de texto a las categorías de enteros, luego de las categorías de enteros a los vectores de un solo color) en una sola toma usando la clase LabelBinarizer:
cat_features = [''color'', ''director_name'', ''actor_2_name'']
encoder = LabelBinarizer()
new_cat_features = encoder.fit_transform(cat_features)
new_cat_features
Tenga en cuenta que esto devuelve una matriz NumPy densa de forma predeterminada. Puede obtener una matriz dispersa al pasar sparse_output = True al constructor LabelBinarizer.
Aprendizaje automático de fuentes con Scikit-Learn y TensorFlow
Si el conjunto de datos está en el marco de datos de pandas, usando
pandas.get_dummies
Será más sencillo.
* corregido de pandas.get_getdummies a pandas.get_dummies
Si lees los documentos de OneHotEncoder
, verás que la entrada para el fit
es "Matriz de entrada de tipo int". Así que necesitas hacer dos pasos para tus datos codificados en caliente.
from sklearn import preprocessing
cat_features = [''color'', ''director_name'', ''actor_2_name'']
enc = preprocessing.LabelEncoder()
enc.fit(cat_features)
new_cat_features = enc.transform(cat_features)
print new_cat_features # [1 2 0]
new_cat_features = new_cat_features.reshape(-1, 1) # Needs to be the correct shape
ohe = preprocessing.OneHotEncoder(sparse=False) #Easier to read
print ohe.fit_transform(new_cat_features)
Salida :
[[ 0. 1. 0.]
[ 0. 0. 1.]
[ 1. 0. 0.]]
EDITAR
A partir de la OneHotEncoder
0.20
esto se volvió un poco más fácil, no solo porque OneHotEncoder
ahora maneja cadenas de manera agradable, sino también porque podemos transformar varias columnas fácilmente usando ColumnTransformer
, vea a continuación un ejemplo
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import numpy as np
X = np.array([[''apple'', ''red'', 1, ''round'', 0],
[''orange'', ''orange'', 2, ''round'', 0.1],
[''bannana'', ''yellow'', 2, ''long'', 0],
[''apple'', ''green'', 1, ''round'', 0.2]])
ct = ColumnTransformer(
[(''oh_enc'', OneHotEncoder(sparse=False), [0, 1, 3]),], # the column numbers I want to apply this to
remainder=''passthrough'' # This leaves the rest of my columns in place
)
print(ct2.fit_transform(X)) # Notice the output is a string
Salida:
[[''1.0'' ''0.0'' ''0.0'' ''0.0'' ''0.0'' ''1.0'' ''0.0'' ''0.0'' ''1.0'' ''1'' ''0'']
[''0.0'' ''0.0'' ''1.0'' ''0.0'' ''1.0'' ''0.0'' ''0.0'' ''0.0'' ''1.0'' ''2'' ''0.1'']
[''0.0'' ''1.0'' ''0.0'' ''0.0'' ''0.0'' ''0.0'' ''1.0'' ''1.0'' ''0.0'' ''2'' ''0'']
[''1.0'' ''0.0'' ''0.0'' ''1.0'' ''0.0'' ''0.0'' ''0.0'' ''0.0'' ''1.0'' ''1'' ''0.2'']]