udemy neural network machine library learning example español book python numpy machine-learning numpy-ndarray one-hot-encoding

python - neural - Convierta una matriz de índices en una matriz numpy codificada en caliente



python machine learning by example pdf (17)

Aquí hay una función de ejemplo que escribí para hacer esto en base a las respuestas anteriores y mi propio caso de uso:

def label_vector_to_one_hot_vector(vector, one_hot_size=10): """ Use to convert a column vector to a ''one-hot'' matrix Example: vector: [[2], [0], [1]] one_hot_size: 3 returns: [[ 0., 0., 1.], [ 1., 0., 0.], [ 0., 1., 0.]] Parameters: vector (np.array): of size (n, 1) to be converted one_hot_size (int) optional: size of ''one-hot'' row vector Returns: np.array size (vector.size, one_hot_size): converted to a ''one-hot'' matrix """ squeezed_vector = np.squeeze(vector, axis=-1) one_hot = np.zeros((squeezed_vector.size, one_hot_size)) one_hot[np.arange(squeezed_vector.size), squeezed_vector] = 1 return one_hot label_vector_to_one_hot_vector(vector=[[2], [0], [1]], one_hot_size=3)

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 , es decir.


Aquí hay una función que convierte un vector 1-D en una matriz hot-one 2-D.

#!/usr/bin/env python import numpy as np def convertToOneHot(vector, num_classes=None): """ Converts an input 1-D vector of integers into an output 2-D array of one-hot vectors, where an i''th input value of j will set a ''1'' in the i''th row, j''th column of the output array. Example: v = np.array((1, 0, 4)) one_hot_v = convertToOneHot(v) print one_hot_v [[0 1 0 0 0] [1 0 0 0 0] [0 0 0 0 1]] """ assert isinstance(vector, np.ndarray) assert len(vector) > 0 if num_classes is None: num_classes = np.max(vector)+1 else: assert num_classes > 0 assert num_classes >= np.max(vector) result = np.zeros(shape=(len(vector), num_classes)) result[np.arange(len(vector)), vector] = 1 return result.astype(int)

A continuación se muestra un ejemplo de uso:

>>> a = np.array([1, 0, 3]) >>> convertToOneHot(a) array([[0, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1]]) >>> convertToOneHot(a, num_classes=10) array([[0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]])


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-one-hot one_hot , donde one_hot[i_1,...,i_N,c] = 1 significa arr[i_1,...,i_N] = c . Puede recuperar la entrada a través de np.argmax(one_hot, -1)

def expand_integer_grid(arr, n_classes): """ :param arr: N dim array of size i_1, ..., i_N :param n_classes: C :returns: one-hot N+1 dim array of size i_1, ..., i_N, C :rtype: ndarray """ one_hot = np.zeros(arr.shape + (n_classes,)) axes_ranges = [range(arr.shape[i]) for i in range(arr.ndim)] flat_grids = [_.ravel() for _ in np.meshgrid(*axes_ranges, indexing=''ij'')] one_hot[flat_grids + [arr.ravel()]] = 1 assert((one_hot.sum(-1) == 1).all()) assert(np.allclose(np.argmax(one_hot, -1), arr)) return one_hot


Creo que la respuesta corta es no. Para un caso más genérico en n dimensiones, se me ocurrió esto:

# For 2-dimensional data, 4 values a = np.array([[0, 1, 2], [3, 2, 1]]) z = np.zeros(list(a.shape) + [4]) z[list(np.indices(z.shape[:-1])) + [a]] = 1

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 con timeit y parece que las numpy basadas en numpy ( indices / arange ) y las versiones iterativas funcionan casi igual.


En caso de que esté usando keras, hay una utilidad incorporada para eso:

from keras.utils.np_utils import to_categorical categorical_labels = to_categorical(int_labels, num_classes=3)

Y hace más o menos lo mismo que la respuesta de @ YXD (ver source-code ).


Esto es lo que encuentro útil:

import sklearn.preprocessing a = [1,0,3] label_binarizer = sklearn.preprocessing.LabelBinarizer() label_binarizer.fit(range(max(a)+1)) b = label_binarizer.transform(a) print(''{0}''.format(b))

Aquí num_classes representa el número de clases que tiene. Entonces, si tiene a vector con forma de (10000,) esta función lo transforma en (10000, C) . Tenga en cuenta que a está indexado a cero, es decir, one_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


Estoy agregando para completar una función simple, usando solo operadores numpy:

def probs_to_onehot(output_probabilities): argmax_indices_array = np.argmax(output_probabilities, axis=1) onehot_output_array = np.eye(np.unique(argmax_indices_array).shape[0])[argmax_indices_array.reshape(-1)] return onehot_output_array

Toma como entrada una matriz de probabilidad: por ejemplo:

[[0.03038822 0.65810204 0.16549407 0.3797123] ... [0.02771272 0.2760752 0.3280924 0.33458805]]

Y volverá

[[0 1 0 0] ... [0 0 0 1]]


Puede usar sklearn.preprocessing.LabelBinarizer :

Ejemplo:

[[0 1 0 0] [1 0 0 0] [0 0 0 1]]

salida:

def one_hot(a, num_classes): return np.squeeze(np.eye(num_classes)[a.reshape(-1)])

Entre otras cosas, puede inicializar sklearn.preprocessing.LabelBinarizer() para que la salida de la transform sea ​​escasa.


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:

import numpy as np np.eye(x.max()+1)[x]

si 0 no es una clase; luego elimine +1.


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:

all_good_list = [0,1,2,3,4]

adelante, las soluciones publicadas ya se mencionaron anteriormente. Pero, ¿qué pasa si consideramos estos datos?

problematic_list = [0,23,12,89,10]

Si lo hace con los métodos mencionados anteriormente, es probable que termine con 90 columnas únicas. 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:

import numpy as np import sklearn sklb = sklearn.preprocessing.LabelBinarizer() a = np.asarray([1,2,44,3,2]) n = np.unique(a) sklb.fit(n) b = sklb.transform(a)

Espero que alguien haya encontrado las mismas restricciones en las soluciones anteriores y esto pueda ser útil


Solo para explicar la excelente respuesta de , aquí hay una versión más genérica:

def onehottify(x, n=None, dtype=float): """1-hot encode x with the max value n (computed from data if n is None).""" x = np.asarray(x) n = np.max(x) + 1 if n is None else n return np.eye(n, dtype=dtype)[x]

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 (ligeramente modificado, para que ofrezcan la misma API, excepto que este último funciona solo con nDray de 1D):

def onehottify_only_1d(x, n=None, dtype=float): x = np.asarray(x) n = np.max(x) + 1 if n is None else n b = np.zeros((len(x), n), dtype=dtype) b[np.arange(len(x)), x] = 1 return b

El último método es ~ 35% más rápido (MacBook Pro 13 2015), pero el primero es más general:

>>> import numpy as np >>> np.random.seed(42) >>> a = np.random.randint(0, 9, size=(10_000,)) >>> a array([6, 3, 7, ..., 5, 8, 6]) >>> %timeit onehottify(a, 10) 188 µs ± 5.03 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) >>> %timeit onehottify_only_1d(a, 10) 139 µs ± 2.78 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)


Su matriz a define las columnas de los elementos distintos de cero en la matriz de salida. También debe definir las filas y luego usar una indexación elegante:

>>> a = np.array([1, 0, 3]) >>> b = np.zeros((3, 4)) >>> b[np.arange(3), a] = 1 >>> b array([[ 0., 1., 0., 0.], [ 1., 0., 0., 0.], [ 0., 0., 0., 1.]])


Tal tipo de codificación suele ser parte de una matriz numpy. Si está utilizando una matriz numpy como esta:

a = np.array([1,0,3])

entonces hay una manera muy simple de convertir eso a codificación 1-hot

out = (np.arange(4) == a[:,None]).astype(np.float32)

Eso es.


También puede usar eye función de eye de numpy:

numpy.eye(number of classes)[vector containing the labels]


Usa el siguiente código. Funciona mejor

def one_hot_encode(x): """ argument - x: a list of labels return - one hot encoding matrix (number of labels, number of class) """ encoded = np.zeros((len(x), 10)) for idx, val in enumerate(x): encoded[idx][val] = 1 return encoded

Lo encontré aquí PD No es necesario entrar en el enlace.


>>> values = [1, 0, 3] >>> n_values = np.max(values) + 1 >>> np.eye(n_values)[values] array([[ 0., 1., 0., 0.], [ 1., 0., 0., 0.], [ 0., 0., 0., 1.]])


  • p será un 2d ndarray.
  • Queremos saber qué valor es el más alto en una fila, para poner allí 1 y en todas partes 0.

Solución limpia y fácil:

max_elements_i = np.expand_dims(np.argmax(p, axis=1), axis=1) one_hot = np.zeros(p.shape) np.put_along_axis(one_hot, max_elements_i, 1, axis=1)