web-dev-qa-db-fra.com

Un encodage à chaud utilisant numpy

Si l'entrée est zéro, je veux faire un tableau qui ressemble à ceci:

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

et si l'entrée est 5:

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

Pour ce qui précède, j'ai écrit:

np.put(np.zeros(10),5,1)

mais cela n'a pas fonctionné.

Existe-t-il un moyen de le mettre en œuvre sur une seule ligne?

23
Abhijay Ghildyal

Généralement, lorsque vous souhaitez obtenir un codage unique pour la classification en apprentissage automatique, vous disposez d'un tableau d'indices.

import numpy as np
nb_classes = 6
targets = np.array([[2, 3, 4, 0]]).reshape(-1)
one_hot_targets = np.eye(nb_classes)[targets]

Le one_hot_targets est maintenant

array([[[ 0.,  0.,  1.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  1.,  0.,  0.],
        [ 0.,  0.,  0.,  0.,  1.,  0.],
        [ 1.,  0.,  0.,  0.,  0.,  0.]]])

La .reshape(-1) est là pour vous assurer que vous avez le bon format d'étiquettes (vous pourriez aussi avoir [[2], [3], [4], [0]]). Le -1 est une valeur spéciale qui signifie "mettre tous les éléments restants dans cette dimension". Comme il n'y en a qu'un, cela aplatit le tableau.

Solution Copier-Coller

def get_one_hot(targets, nb_classes):
    res = np.eye(nb_classes)[np.array(targets).reshape(-1)]
    return res.reshape(list(targets.shape)+[nb_classes])

Paquet

Vous pouvez utiliser mpu.ml.indices2one_hot . C'est testé et simple à utiliser:

import mpu.ml
one_hot = mpu.ml.indices2one_hot([1, 3, 0], nb_classes=5)
49
Martin Thoma

Quelque chose comme : 

np.array([int(i == 5) for i in range(10)])

Devrait faire l'affaire ... Mais je suppose qu'il existe d'autres solutions utilisant numpy.

edit: la raison pour laquelle votre formule ne fonctionne pas: np.put ne renvoie rien, il modifie simplement l'élément indiqué dans le premier paramètre La bonne réponse lorsque vous utilisez np.put() est:

a = np.zeros(10)
np.put(a,5,1)

Le problème est que cela ne peut pas être fait sur une seule ligne, car vous devez définir le tableau avant de le passer à np.put()

9
HolyDanna

Vous pouvez utiliser la compréhension de liste:

[0 if i !=5 else 1 for i in range(10)]

se tourne vers

[0,0,0,0,0,1,0,0,0,0]
3
Rikku Porta

Utilisez np.identify ou np.eye. Vous pouvez essayer quelque chose comme ceci avec votre entrée i et la taille du tableau s:

np.identify(s)[i:i+1]

Par exemple, print(np.identity(5)[0:1]) résultera:

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

Si vous utilisez TensorFlow, vous pouvez utiliser tf.one_hot: https://www.tensorflow.org/api_docs/python/array_ops/slicing_and_joining#one_hot

2
Sung Kim

Le np.put mute son tableau arg in-place. Il est classique en Python pour les fonctions/méthodes qui effectuent une mutation sur place de retourner None; np.put adhère à cette convention. Donc, si a est un tableau 1D et que vous faites

a = np.put(a, 5, 1)

alors a sera remplacé par None.

Votre code est similaire à celui-ci, mais il transmet un tableau non nommé à np.put.

Une façon simple et efficace de faire ce que vous voulez consiste à utiliser une fonction simple, par exemple:

import numpy as np

def one_hot(i):
    a = np.zeros(10, 'uint8')
    a[i] = 1
    return a

a = one_hot(5) 
print(a)

sortie

[0 0 0 0 0 1 0 0 0 0]
2
PM 2Ring

Le problème ici est que vous ne sauvegardez votre tableau nulle part. La fonction put fonctionne à la place du tableau et ne renvoie rien. Puisque vous ne donnez jamais un nom à votre tableau, vous ne pourrez plus l’adresser plus tard. Donc ça

one_pos = 5
x = np.zeros(10)
np.put(x, one_pos, 1)

fonctionnerait, mais alors vous pourriez simplement utiliser l’indexation:

one_pos = 5
x = np.zeros(10)
x[one_pos] = 1

À mon avis, ce serait la bonne façon de procéder si aucune raison particulière n'existait pour le faire en une ligne. Cela pourrait aussi être plus facile à lire et le code lisible est un bon code.

2
m00am

En regardant rapidement le manuel , vous verrez que np.put ne renvoie pas de valeur. Tant que votre technique est correcte, vous accédez à None au lieu de votre tableau de résultats.

Pour un tableau 1-D, il est préférable d’utiliser simplement l’indexation directe, en particulier pour un cas aussi simple.

Voici comment réécrire votre code avec une modification minimale:

arr = np.zeros(10)
np.put(arr, 5, 1)

Voici comment faire la deuxième ligne avec indexation au lieu de put:

arr[5] = 1
2
Mad Physicist

Je ne suis pas sûr de la performance, mais le code suivant fonctionne et c'est bien.

x = np.array([0, 5])
x_onehot = np.identity(6)[x]
0
Ken Chan
import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
    a= np.repeat(0,10)
    np.put(a,l,1)
    z.append(a)
print("--- %s seconds ---" % (time.time() - start_time))

#--- 0.00174784660339 seconds ---

import time
start_time = time.time()
z=[]
for l in [1,2,3,4,5,6,1,2,3,4,4,6,]:
    z.append(np.array([int(i == l) for i in range(10)]))
print("--- %s seconds ---" % (time.time() - start_time))

#--- 0.000400066375732 seconds ---
0
Abhijay Ghildyal