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?
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.
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])
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)
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()
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]
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
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]
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.
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
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]
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 ---