it-swarm.com.de

Eine Hot Encoding mit Numpy

Wenn die Eingabe Null ist, möchte ich ein Array erstellen, das folgendermaßen aussieht:

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

und wenn die Eingabe 5 ist:

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

Für das oben Gesagte schrieb ich:

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

aber es hat nicht funktioniert.

Gibt es eine Möglichkeit, wie dies in einer Zeile implementiert werden kann?

23

Normalerweise, wenn Sie eine One-Hot-Kodierung für die Klassifizierung beim maschinellen Lernen erhalten möchten, verfügen Sie über ein Array von Indizes.

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

Der one_hot_targets ist jetzt

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

.reshape(-1) sorgt dafür, dass Sie das richtige Etikettenformat haben (möglicherweise haben Sie auch [[2], [3], [4], [0]]). Der -1 ist ein spezieller Wert, der "alle verbleibenden Elemente in dieser Dimension" bedeutet. Da es nur einen gibt, wird das Array abgeflacht.

Copy-Paste-Lösung

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])

Paket

Sie können mpu.ml.indices2one_hot verwenden. Es ist getestet und einfach zu bedienen:

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

So etwas wie : 

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

Sollte den Trick tun ... Aber ich denke, es gibt andere Lösungen, die numpy verwenden.

edit: Der Grund, warum Ihre Formel nicht funktioniert: np.put gibt nichts zurück, sondern ändert nur das im ersten Parameter angegebene Element. Die gute Antwort bei der Verwendung von np.put() lautet:

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

Das Problem ist, dass dies nicht in einer Zeile erfolgen kann, da Sie das Array definieren müssen, bevor Sie es an np.put() übergeben

9
HolyDanna

Sie können Listenverständnis verwenden:

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

wendet sich an

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

Verwenden Sie np.identify oder np.eye. Sie können so etwas mit Ihrer Eingabe i und der Arraygröße s versuchen:

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

Zum Beispiel wird print(np.identity(5)[0:1]) folgendes ergeben:

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

Bei Verwendung von TensorFlow können Sie tf.one_hot: https://www.tensorflow.org/api_docs/python/array_ops/slicing_and_joining#one_hot

2
Sung Kim

Der np.put mutiert sein Array arg in-place. Es ist in Python für Funktionen/Methoden üblich, die In-Place-Mutationen ausführen, um None zurückzugeben. np.put hält sich an diese Konvention. Wenn also a ein 1D-Array ist, ist dies der Fall

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

dann wird a durch None ersetzt.

Ihr Code ist dem ähnlich, übergibt jedoch ein nicht benanntes Array an np.put.

Eine kompakte und effiziente Möglichkeit, das zu tun, was Sie möchten, ist eine einfache Funktion, z.

import numpy as np

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

a = one_hot(5) 
print(a)

Ausgabe

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

Das Problem hier ist, dass Sie Ihr Array nirgendwo speichern. Die put-Funktion arbeitet im Array und gibt nichts zurück. Da Sie Ihrem Array nie einen Namen geben, können Sie es später nicht mehr ansprechen. Also das

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

würde funktionieren, aber dann könnten Sie einfach die Indizierung verwenden:

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

Meiner Meinung nach wäre dies der richtige Weg, wenn es keinen besonderen Grund dafür gibt, dies als Einliner zu tun. Dies kann auch einfacher zu lesen und lesbarer Code ist guter Code.

2
m00am

Ein kurzer Blick auf das Handbuch - zeigt, dass np.put keinen Wert zurückgibt. Während Ihre Technik in Ordnung ist, greifen Sie anstelle Ihres Ergebnis-Arrays auf None zu.

Für ein 1-D-Array ist es besser, die direkte Indizierung zu verwenden, insbesondere für einen so einfachen Fall.

So schreiben Sie Ihren Code mit minimaler Änderung um:

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

So wird die zweite Zeile mit der Indexierung anstelle von put ausgeführt:

arr[5] = 1
2
Mad Physicist

Ich bin nicht sicher, was die Leistung angeht, aber der folgende Code funktioniert und ist ordentlich.

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