cadenas como características en árbol de decisión / bosque aleatorio

64

Estoy haciendo algunos problemas en una aplicación de árbol de decisión / bosque aleatorio. Estoy tratando de ajustar un problema que tiene números y cadenas (como el nombre del país) como características. Ahora, la biblioteca, scikit-learn toma solo números como parámetros, pero quiero inyectar las cadenas y llevar una gran cantidad de conocimiento.

¿Cómo manejo tal escenario?

Puedo convertir una cadena a números mediante algún mecanismo, como el hash en Python. Pero me gustaría conocer la mejor práctica sobre cómo se manejan las cadenas en los problemas del árbol de decisiones.

user3001408
fuente
En el caso de sckitlearn, he visto que necesitamos codificar las variables categóricas, de lo contrario, el método de ajuste arrojaría un error que dice ValueError: no se pudo convertir la cadena en flotante
Kar

Respuestas:

56

En la mayoría de los sistemas de aprendizaje automático bien establecidos, las variables categóricas se manejan de forma natural. Por ejemplo, en R usaría factores, en WEKA usaría variables nominales. Este no es el caso en scikit-learn. Los árboles de decisión implementados en scikit-learn usan solo características numéricas y estas características se interpretan siempre como variables numéricas continuas .

Por lo tanto, se debe evitar simplemente reemplazar las cadenas por un código hash, ya que al ser considerado como una característica numérica continua, cualquier codificación que utilice inducirá un orden que simplemente no existe en sus datos.

Un ejemplo es codificar ['rojo', 'verde', 'azul'] con [1,2,3], produciría cosas extrañas como 'rojo' es más bajo que 'azul', y si promedia un 'rojo' y un "azul" obtendrá un "verde". Otro ejemplo más sutil puede suceder cuando codifica ['bajo', 'medio', 'alto'] con [1,2,3]. En el último caso, puede ocurrir que tenga un orden que tenga sentido, sin embargo, pueden ocurrir algunas inconsistencias sutiles cuando 'medio' no está en el medio de 'bajo' y 'alto'.

Finalmente, la respuesta a su pregunta radica en codificar la característica categórica en múltiples características binarias . Por ejemplo, puede codificar ['rojo', 'verde', 'azul'] con 3 columnas, una para cada categoría, con 1 cuando la categoría coincide y 0 en caso contrario. Esto se llama codificación en caliente, codificación binaria, codificación uno de k o lo que sea. Puede consultar la documentación aquí para codificar características categóricas y extracción de características: hash y dictos . Obviamente, una codificación en caliente expandirá sus requisitos de espacio y, a veces, también perjudica el rendimiento.

rapaio
fuente
2
Es la implementación de scikit que no maneja las variables categóricas correctamente. Grabar como sugiere esta respuesta es probablemente lo mejor que puede hacer. El usuario más serio podría buscar un paquete alternativo.
SmallChess
3
Se puede usar sklearn.preprocessing.LabelBinarizer para una codificación en caliente de una variable categórica.
GuSuku
@rapaio Creo que la codificación binaria no es la misma codificación activa. La codificación binaria es cuando representa 8 categorías con 3 columnas, o entre 9 y 16 categorías con 4 columnas, etc. ¿Me equivoco?
Alok Nayak
el paquete patsy python se ocupará de una codificación de variables categóricas. patsy.readthedocs.io/en/latest/quickstart.html
zhespelt
55
No use LabelBinarizer, use sklearn.preprocessing.OneHotEncoder . Si está usando pandas para importar y preprocesar sus datos, también puede hacerlo directamente usando pandas.get_dummies . Apesta que scikit-learn no admita variables categóricas.
Ricardo Cruz
11

Debe codificar sus cadenas como características numéricas que sci-kit puede usar para los algoritmos ML. Esta funcionalidad se maneja en el módulo de preprocesamiento (por ejemplo, consulte sklearn.preprocessing.LabelEncoder para ver un ejemplo).

Kyle
fuente
44
rapaio explica en su respuesta por qué esto obtendría un resultado incorrecto
Keith
7

Por lo general, debe codificar de forma activa variables categóricas para los modelos de aprendizaje de scikit, incluido el bosque aleatorio. El bosque aleatorio a menudo funcionará bien sin una codificación de un solo uso, pero generalmente funciona mejor si realiza una codificación de un solo uso. Las variables de codificación única y "dummying" significan lo mismo en este contexto. Scikit-learn tiene sklearn.preprocessing.OneHotEncoder y Pandas tiene pandas.get_dummies para lograr esto.

Sin embargo, hay alternativas. El artículo "Beyond One-Hot" en KDnuggets hace un gran trabajo al explicar por qué necesita codificar variables categóricas y alternativas a la codificación one-hot.

Hay implementaciones alternativas de bosque aleatorio que no requieren codificación de un solo uso, como R o H2O. La implementación en R es computacionalmente costosa y no funcionará si sus características tienen muchas categorías . H2O funcionará con un gran número de categorías. Continuum ha hecho que H2O esté disponible en Anaconda Python.

Hay un esfuerzo continuo para hacer que scikit-learn maneje las características categóricas directamente .

Este artículo tiene una explicación del algoritmo utilizado en H2O. Hace referencia al documento académico A Streaming Parallel Decision Tree Algorithm y una versión más larga del mismo documento.

denson
fuente
5

¡Actualización 2018!

Puede crear un espacio de incrustación (vector denso) para sus variables categóricas. Muchos de ustedes están familiarizados con word2vec y fastext, que incorporan palabras en un espacio vectorial denso y significativo. La misma idea aquí: sus variables categóricas se asignarán a un vector con algún significado.

Del documento Guo / Berkhahn :

La incrustación de entidades no solo reduce el uso de memoria y acelera las redes neuronales en comparación con la codificación única, sino que, lo que es más importante, al mapear valores similares entre sí en el espacio de incrustación, revela las propiedades intrínsecas de las variables categóricas. Lo aplicamos con éxito en una competencia reciente de Kaggle y pudimos alcanzar la tercera posición con características relativamente simples.

Los autores descubrieron que representar variables categóricas de esta manera mejoraba la efectividad de todos los algoritmos de aprendizaje automático probados, incluido el bosque aleatorio.

El mejor ejemplo podría ser la aplicación de Pinterest de la técnica para agrupar Pines relacionados:

ingrese la descripción de la imagen aquí

La gente de fastai ha implementado incrustaciones categóricas y ha creado una publicación de blog muy agradable con el cuaderno de demostración complementario .

Detalles adicionales y explicación

Se utiliza una red neuronal para crear las incrustaciones, es decir, asignar un vector a cada valor categórico. Una vez que tenga los vectores, puede usarlos en cualquier modelo que acepte valores numéricos. Cada componente del vector se convierte en una variable de entrada. Por ejemplo, si usó vectores tridimensionales para incrustar su lista categórica de colores, podría obtener algo como: rojo = (0, 1.5, -2.3), azul = (1, 1, 0) etc. Utilizaría tres ingrese variables en su bosque aleatorio correspondiente a los tres componentes. Para las cosas rojas, c1 = 0, c2 = 1.5 y c3 = -2.3. Para las cosas azules, c1 = 1, c2 = 1 y c3 = 0.

En realidad, no necesita usar una red neuronal para crear incrustaciones (aunque no recomiendo alejarse de la técnica). Usted es libre de crear sus propias incrustaciones a mano u otros medios, cuando sea posible. Algunos ejemplos:

  1. Mapa de colores a vectores RGB.
  2. Mapa de ubicaciones a vectores lat / long.
  3. En un modelo político de EE. UU., Asigne ciudades a algunos componentes vectoriales que representen la alineación izquierda / derecha, la carga fiscal, etc.
Pete
fuente
Está bien, pero a menos que me haya perdido algo, esto es para las redes de principio a fin. ¿Cómo creamos una incrustación y luego la pasamos a un Forrest? Supongo que tiene que entrenar una red completa con todas las características y luego tomar las primeras capas y usarlas como su característica de entrada a su Forrest. No está claro cómo se haría esto.
Keith
@Keith se utiliza una red neuronal para crear las incrustaciones, es decir, asignar un vector a cada valor categórico. Una vez que tenga los vectores, puede usarlos en cualquier modelo que acepte valores numéricos. Cada componente del vector se convierte en una variable de entrada. Por ejemplo, si usó vectores tridimensionales para incrustar su lista categórica de colores, podría obtener algo como: rojo = (0, 1.5, -2.3), azul = (1, 1, 0)etc. Utilizaría tres variables de entrada en su bosque aleatorio correspondientes a los tres componentes. Para las cosas rojas, c1 = 0, c2 = 1.5 y c3 = -2.3. Para cosas azules, c1 = 1, c2 = 1 y c3 = 0.
Pete
Entiendo totalmente el concepto, ya que es bastante simple. Quiero decir, ¿cómo se haría esto en la implementación? El cuaderno de demostración fast.ai que vincula tiene un poco con un RandomForestRegressor al final, pero realmente no veo cómo esto se agrega en las incrustaciones.
Keith
Creo que este puede ser un buen ejemplo de código en Keras github.com/entron/entity-embedding-rossmann
Keith
3

Puede usar variables ficticias en tales escenarios. Con los pandas, panda.get_dummiespuede crear variables ficticias para las cadenas que desea colocar en el Árbol de decisión o en el Bosque aleatorio.

Ejemplo:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies
ozn
fuente
2

Conviértalos en números, por ejemplo para cada país único asignando un número único (como 1,2,3 y ...)

Además, no es necesario utilizar la codificación en caliente (también conocida como variables ficticias) cuando se trabaja con bosque aleatorio, porque los árboles no funcionan como otro algoritmo (como la regresión lineal / logística) y no funcionan a distancia (ellos trabaje con la búsqueda de una buena división para sus características), por lo que NO NECESITA una codificación de uno en caliente

Arash Jamshidi
fuente
1
De hecho, depende del algoritmo particular que entrena el árbol. En particular, scikit NO admite variables categóricas.
chuse