Digamos que tengo una matriz numpy 1d
a = array([1,0,3])
Me gustaría codificar esto como una matriz 2d 1-hot
b = array([[0,1,0,0], [1,0,0,0], [0,0,0,1]])
¿Hay una manera rápida de hacer esto? Más rápido que simplemente recorrer a
para establecer elementos de b
, eso es.
python
numpy
machine-learning
numpy-ndarray
one-hot-encoding
James Atwood
fuente
fuente
b = np.zeros((a.size, a.max()+1))
luego `b [np.arange (a.size), a] = 1`fuente
values
debe ser una matriz Numpy en lugar de una lista de Python, entonces funciona en todas las dimensiones, no solo en 1D.np.max(values) + 1
es posible que no sea conveniente tomar el número de cubetas si su conjunto de datos se muestrea aleatoriamente y por casualidad puede no contener el valor máximo. El número de depósitos debe ser más bien un parámetro y se puede establecer la aserción / verificación para verificar que cada valor esté dentro de 0 (incl.) Y el conteo de depósitos (excl).numpy
documentos): en cada ubicación en la matriz original (values
), tenemos un número enterok
y "colocamos" el vector 1-hoteye(n)[k]
en esa ubicación . Esto agrega una dimensión porque estamos "poniendo" un vector en la ubicación de un escalar en la matriz original.En caso de que esté usando keras, hay una utilidad incorporada para eso:
Y hace más o menos lo mismo que la respuesta de @ YXD (ver código fuente ).
fuente
Esto es lo que encuentro útil:
Aquí
num_classes
representa el número de clases que tiene. Entonces, si tiene una
vector con forma de (10000,) esta función lo transforma en (10000, C) . Tenga en cuenta quea
está indexado a cero, es decirone_hot(np.array([0, 1]), 2)
, dará[[1, 0], [0, 1]]
.Exactamente lo que querías tener, creo.
PD: la fuente son los modelos de secuencia - deeplearning.ai
fuente
np.eye(num_classes)[a.reshape(-1)]. What you are simply doing is using
np.eye` está creando una matriz diagonal con cada índice de clase como 1 resto cero y luego usando los índices proporcionados pora.reshape(-1)
la producción de la salida correspondiente al índice ennp.eye()
. No entendí la necesidad denp.sqeeze
hacerlo, ya que lo usamos para eliminar simplemente dimensiones individuales que nunca tendremos, ya que en la dimensión de salida siempre será(a_flattened_size, num_classes)
Puedes usar
sklearn.preprocessing.LabelBinarizer
:Ejemplo:
salida:
Entre otras cosas, puede inicializar
sklearn.preprocessing.LabelBinarizer()
para que la salida detransform
sea escasa.fuente
También puede usar la función de ojo de numpy:
numpy.eye(number of classes)[vector containing the labels]
fuente
np.identity(num_classes)[indices]
podría ser mejor. ¡Buena respuesta!Aquí hay una función que convierte un vector 1-D en una matriz 2-D one-hot.
A continuación se muestra un ejemplo de uso:
fuente
assert
que verificar la forma del vector;)).assert ___
enif not ___ raise Exception(<Reason>)
.Para 1-hot-encoding
Por ejemplo
DISFRUTE DE LA CODIFICACIÓN
fuente
>>> import numpy as np >>> import pandas >>> a = np.array([1,0,3]) >>> one_hot_encode=pandas.get_dummies(a) >>> print(one_hot_encode) 0 1 3 0 0 1 0 1 1 0 0 2 0 0 1 >>> print(one_hot_encode[1]) 0 1 1 0 2 0 Name: 1, dtype: uint8 >>> print(one_hot_encode[0]) 0 0 1 1 2 0 Name: 0, dtype: uint8 >>> print(one_hot_encode[3]) 0 0 1 0 2 1 Name: 3, dtype: uint8
Creo que la respuesta corta es no. Para un caso más genérico en
n
dimensiones, se me ocurrió esto:Me pregunto si hay una solución mejor. No me gusta que tenga que crear esas listas en las últimas dos líneas. De todos modos, hice algunas mediciones
timeit
y parece que la versiónnumpy
basada en (indices
/arange
) y la iterativa tienen un rendimiento similar.fuente
Solo para explicar la excelente respuesta de K3 --- rnc , aquí hay una versión más genérica:
Además, aquí hay un punto de referencia rápido y sucio de este método y un método de la respuesta actualmente aceptada por YXD (ligeramente modificado, para que ofrezcan la misma API, excepto que este último funciona solo con nDray de 1D):
El último método es ~ 35% más rápido (MacBook Pro 13 2015), pero el primero es más general:
fuente
Puede usar el siguiente código para convertirlo en un vector único:
let x es el vector de clase normal que tiene una sola columna con clases 0 a algún número:
si 0 no es una clase; luego elimine +1.
fuente
Recientemente me encontré con un problema del mismo tipo y encontré dicha solución que resultó ser solo satisfactoria si tienes números que van dentro de cierta formación. Por ejemplo, si desea codificar en caliente la siguiente lista:
adelante, las soluciones publicadas ya se mencionaron anteriormente. Pero qué pasa si consideramos estos datos:
Si lo hace con los métodos mencionados anteriormente, es probable que termine con 90 columnas de una sola vez. Esto se debe a que todas las respuestas incluyen algo como
n = np.max(a)+1
. Encontré una solución más genérica que funcionó para mí y quería compartir con ustedes:Espero que alguien haya encontrado las mismas restricciones en las soluciones anteriores y esto pueda ser útil
fuente
Tal tipo de codificación suele ser parte de una matriz numpy. Si está utilizando una matriz numpy como esta:
entonces hay una manera muy simple de convertir eso a codificación 1-hot
Eso es.
fuente
Solución limpia y fácil:
fuente
Usando un paso de tubería Neuraxle :
Enlace a la documentación: neuraxle.steps.numpy.OneHotEncoder
fuente
Aquí hay una función de ejemplo que escribí para hacer esto en base a las respuestas anteriores y mi propio caso de uso:
fuente
Estoy agregando para completar una función simple, usando solo operadores numpy:
Toma como entrada una matriz de probabilidad: por ejemplo:
Y volverá
fuente
Aquí hay una solución independiente de dimensionalidad independiente.
Esto convertirá cualquier matriz N-dimensional
arr
de enteros no negativos en una matriz N + 1-dimensional de un solo calorone_hot
, dondeone_hot[i_1,...,i_N,c] = 1
significaarr[i_1,...,i_N] = c
. Puede recuperar la entrada a través denp.argmax(one_hot, -1)
fuente
Usa el siguiente código. Funciona mejor
Lo encontré aquí PD No es necesario entrar en el enlace.
fuente