python - sklearn - scikit-learn: una codificación en caliente de características categóricas de cadenas
sklearn learning curve (3)
He enfrentado este problema muchas veces y encontré una solución en este libro en su página 100:
Podemos aplicar ambas transformaciones (desde categorías de texto a categorías enteras, luego de categorías enteras a vectores únicos) en una sola toma usando la clase LabelBinarizer:
y el código de muestra está aquí:
from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(data)
housing_cat_1hot
y como resultado: tenga en cuenta que esto devuelve una matriz NumPy densa por defecto. En su lugar, puede obtener una matriz dispersa pasando sparse_output = True al constructor LabelBinarizer.
Y puede encontrar más información sobre LabelBinarizer, aquí en la documentación oficial de sklearn
Estoy tratando de realizar una codificación en caliente de un conjunto de datos triviales.
data = [[''a'', ''dog'', ''red'']
[''b'', ''cat'', ''green'']]
¿Cuál es la mejor manera de preprocesar estos datos con Scikit-Learn?
Al primer instinto, miraría hacia OneHotEncoder de Scikit -Learn. Pero el codificador en caliente no admite cadenas como características; solo discretiza enteros.
Entonces usaría un LabelEncoder , que codificaría las cadenas en enteros. Pero luego debe aplicar el codificador de etiquetas en cada una de las columnas y almacenar cada uno de estos codificadores de etiquetas (así como las columnas sobre las que se aplicaron). Y esto se siente extremadamente torpe.
Entonces, ¿cuál es la mejor manera de hacerlo en Scikit-Learn?
Por favor, no sugieras pandas.get_dummies . Eso es lo que generalmente uso hoy en día para codificaciones en caliente. Sin embargo, está limitado en el hecho de que no puede codificar su conjunto de entrenamiento / prueba por separado.
Muy buena pregunta.
Sin embargo, en cierto sentido, es un caso privado de algo que surge (al menos para mí) bastante a menudo: dadas sklearn
etapas de sklearn
aplicables a subconjuntos de la matriz X
, me gustaría aplicar (posiblemente varias) dada la matriz completa . Aquí, por ejemplo, tiene una etapa que sabe ejecutar en una sola columna y desea aplicarla tres veces, una por columna.
Este es un caso clásico para usar el patrón de diseño compuesto .
Aquí hay un (esbozo de) una etapa reutilizable que acepta un diccionario mapeando un índice de columna en la transformación para aplicarlo:
class ColumnApplier(object):
def __init__(self, column_stages):
self._column_stages = column_stages
def fit(self, X, y):
for i, k in self._column_stages.items():
k.fit(X[:, i])
return self
def transform(self, X):
X = X.copy()
for i, k in self._column_stages.items():
X[:, i] = k.transform(X[:, i])
return X
Ahora, para usarlo en este contexto, comenzando con
X = np.array([[''a'', ''dog'', ''red''], [''b'', ''cat'', ''green'']])
y = np.array([1, 2])
X
solo lo usaría para asignar cada índice de columna a la transformación que desea:
multi_encoder = /
ColumnApplier(dict([(i, preprocessing.LabelEncoder()) for i in range(3)]))
multi_encoder.fit(X, None).transform(X)
Una vez que desarrollas esa etapa (no puedo publicar la que uso), puedes usarla una y otra vez para varias configuraciones.
Para su información, esto va a estar en producción en sklearn muy pronto: consulte https://github.com/scikit-learn/scikit-learn/pull/9151
In [30]: cat = CategoricalEncoder()
In [31]: X = np.array([[''a'', ''b'', ''a'', ''c''], [0, 1, 0, 1]], dtype=object).T
In [32]: cat.fit_transform(X).toarray() Out[32]: array([[ 1., 0.,
0., 1., 0.],
[ 0., 1., 0., 0., 1.],
[ 1., 0., 0., 1., 0.],
[ 0., 0., 1., 0., 1.]])
Si instala la rama principal, debería poder hacerlo.
Otra forma de hacerlo es usar category_encoders.
Aquí hay un ejemplo:
%pip install category_encoders
import category_encoders as ce
le = ce.OneHotEncoder(return_df=False,impute_missing=False,handle_unknown="ignore")
X = np.array([[''a'', ''dog'', ''red''], [''b'', ''cat'', ''green'']])
le.fit_transform(X)
array([[1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1]])