2017-10-22 2 views
0

Ich bin do code eine Funktion, die ein NumPy-Array übernimmt und die Normalisierung durchführt. Ich habe geschrieben, was ist unten:NumPy Array - Ändern aller Eingänge

def normalize_min_max(A, axis = None): 
    ptr = axis 
    minimum = np.amin(A, ptr) 
    maximum = np.amax(A, ptr) 
    for x in np.nditer(A): 
     x = (x - minimum)/(maximum - minimum) 
    return A 

Leider funktioniert es nicht, weil das zurückgegebene Array unverändert ist. Wie kann ich es reparieren?

+0

müssen Sie x nein zurückgeben? – percusse

+0

@percusse Ich muss ein Array mit der gleichen Form aber neuen Werten zurückgeben – Hendrra

Antwort

2

In jedem Python Iteration

for x in np.nditer(A): 
    x = (x - minimum)/(maximum - minimum) 

eine Zuordnung Der Wert für die Iterationsvariable ändert seine Referenz und ändert nicht die ursprüngliche Liste/das ursprüngliche Array.

versuchte ich

for x in np.nditer(A): 
    x[:] = (x - minimum)/(maximum - minimum) 

bekam aber einen Fehler

ValueError: assignment destination is read-only 

ich in die nditer Dokumentation gehen, https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.nditer.html#arrays-nditer um herauszufinden, wie es zu einem Lese ändern/schreiben variable

In [388]: def normalize_min_max(A, axis = None): 
    ...:  ptr = axis 
    ...:  minimum = np.amin(A, ptr) 
    ...:  maximum = np.amax(A, ptr) 
    ...:  for x in np.nditer(A, op_flags=['readwrite']): 
    ...:   x[...] = (x - minimum)/(maximum - minimum) 
    ...:  return A 
    ...: 
    ...: 
In [389]: normalize_min_max(np.arange(10)) 
Out[389]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) 

Hoppla, das ursprüngliche Array ist eine Ganzzahl

In [390]: normalize_min_max(np.arange(10.)) 
Out[390]: 
array([ 0.  , 0.11111111, 0.22222222, 0.33333333, 0.44444444, 
     0.55555556, 0.66666667, 0.77777778, 0.88888889, 1.  ]) 

Aber ich brauche nicht diese Art von Berechnung auszuführen iterieren:

In [391]: def normalize_min_max1(A, axis = None): 
    ...:  ptr = axis 
    ...:  minimum = np.amin(A, ptr, keepdims=True) 
    ...:  maximum = np.amax(A, ptr, keepdims=True) 
    ...:  return (A-minimum)/(maximum-minimum) 

In [392]: normalize_min_max1(np.arange(10.)) 
Out[392]: 
array([ 0.  , 0.11111111, 0.22222222, 0.33333333, 0.44444444, 
     0.55555556, 0.66666667, 0.77777778, 0.88888889, 1.  ]) 

nditer hat in diesem Zusammenhang der Arbeit, weil die Iterationsvariable veränderbar ist, wo, da es nicht mit for x in A: ... ist . Aber ansonsten ist es ein komplexer Iterator und bietet keine Geschwindigkeitsvorteile. Wie auf der Tutorial-Seite nditer gezeigt, ist es am nützlichsten, um nditer in cython zu verwenden.

Auch Ihr nditer Code funktioniert nicht mit Achsenwerten. Mine, mit dem keep_dims Parameter arbeitet:

In [396]: normalize_min_max1(np.arange(10.).reshape(5,2),0) 
Out[396]: 
array([[ 0. , 0. ], 
     [ 0.25, 0.25], 
     [ 0.5 , 0.5 ], 
     [ 0.75, 0.75], 
     [ 1. , 1. ]]) 
In [397]: normalize_min_max1(np.arange(10.).reshape(5,2),1) 
Out[397]: 
array([[ 0., 1.], 
     [ 0., 1.], 
     [ 0., 1.], 
     [ 0., 1.], 
     [ 0., 1.]]) 
In [398]: normalize_min_max1(np.arange(10.).reshape(5,2),None) 
Out[398]: 
array([[ 0.  , 0.11111111], 
     [ 0.22222222, 0.33333333], 
     [ 0.44444444, 0.55555556], 
     [ 0.66666667, 0.77777778], 
     [ 0.88888889, 1.  ]]) 

Der nditer Code mit einer Achse Wert:

In [395]: normalize_min_max(np.arange(10.).reshape(5,2),0) 
... 
ValueError: could not broadcast input array from shape (2) into shape() 

Die nditer Variable eine 0T Array ist, das es modifiziert werden kann. Dies erschwert jedoch die Verwendung der Min/Max-Werte, bei denen es sich um Arrays handeln kann. Wir müssten diese Arrays in das nditer Setup aufnehmen. So ist es möglich, aber normalerweise nicht die zusätzliche Arbeit wert.

1
return [(x - minimum)/(maximum - minimum) for x in np.nditer(A)] 

Alternativ zur In-Place-Array-Normalisierung siehe this answer.

1

Warum die for Schleife? Hier ist eine vektorisiert Lösung mit einem gewissen Achse Tricks, um sicherzustellen, die Formen mit dem Eingangsachse ausrichten:

def normalize_min_max(A, axis=None): 
    A = np.asarray(A) 
    A_min = A.min(axis=axis) 
    A = (np.rollaxis(A, (0 if axis is None else axis)) - A_min)/(A.max(axis=axis) - A_min) 
    return np.rollaxis(A, (0 if axis is None else axis)) 

Einige Ergebnisse:

In[175]: a = np.arange(4*3, dtype='float32').reshape(4, 3) 
In[176]: a 
Out[176]: 

array([[ 0., 1., 2.], 
     [ 3., 4., 5.], 
     [ 6., 7., 8.], 
     [ 9., 10., 11.]], dtype=float32) 
In[177]: normalize_min_max(a, None) 
Out[177]: 

array([[ 0.  , 0.09090909, 0.18181819], 
     [ 0.27272728, 0.36363637, 0.45454547], 
     [ 0.54545456, 0.63636363, 0.72727275], 
     [ 0.81818181, 0.90909094, 1.  ]], dtype=float32) 
In[178]: normalize_min_max(a, 0) 
Out[178]: 

array([[ 0.  , 0.  , 0.  ], 
     [ 0.33333334, 0.33333334, 0.33333334], 
     [ 0.66666669, 0.66666669, 0.66666669], 
     [ 1.  , 1.  , 1.  ]], dtype=float32) 
In[179]: normalize_min_max(a, 1) 
Out[179]: 

array([[ 0. , 0.5, 1. ], 
     [ 0. , 0.5, 1. ], 
     [ 0. , 0.5, 1. ], 
     [ 0. , 0.5, 1. ]], dtype=float32) 
+0

Das ist ziemlich genau das, was ich gerne mit der Achse machen würde. Aber leider funktioniert es nicht. Es gibt einen Fehler: Operanden konnten nicht zusammen mit Shapes gesendet werden (2,3) (2,) – Hendrra

+0

Ist Ihr Ziel, die Normalisierung für jede Achse getrennt durchzuführen? –

+0

Ja. Ich möchte einen Parameter hinzufügen (Achse = None, 1 oder -1). Und die Funktion sollte die Normalisierung für das Array, die Zeilen oder die Spalten durchführen. – Hendrra

1

Eine Methode: In-Place-Modifikation, ohne ein neues Numpy Array erstellen

import numpy as np 

def normalize_min_max(A, axis = None): 
    ptr = axis 
    minimum = np.amin(A, ptr) 
    maximum = np.amax(A, ptr) 
    A = (A - minimum)/(maximum - minimum) 
    return A 

np_array = np.array([[1,2, 3,4],[2,3,4,5]]) # example input 

print(normalize_min_max(np_array)) 

Ausgang:

[[ 0. 0.25 0.5 0.75] 
[ 0.25 0.5 0.75 1. ]] 

** Die zweite Methode (Stil): Erstellen Sie neue Numpy Array mit die gleiche Form wie Ihr Eingabe-Array und speichern Sie dort Ihre normalisierten Werte **

Ausgang:

[[ 0. 0.25 0.5 0.75] 
[ 0.25 0.5 0.75 1. ]] 

HINWEIS: Ich bin davon aus, dass Sie in min/max aller Elemente Ihrer Numpy Array nur daran interessiert sind, das ist, warum Achse Ihr Standard Keiner ist. Andere Werte der Achse funktionieren nicht mit Ndenumerate mit einer anderen Achse als None, wie von @hpaulj für nditer erklärt. Wenn Sie andere Achsen verwenden möchten, empfehle ich die obige Methode 1.

Verwandte Themen