Wie ein NumPy Array innerhalb eines bestimmten Bereichs zu normalisieren?
-
20-09-2019 - |
Frage
Nach einiger Verarbeitung auf einer Audio- oder Bildanordnung zu tun, muss er innerhalb eines Bereichs normalisiert werden, bevor es wieder in eine Datei geschrieben werden kann. Dies kann etwa so erfolgen:
# Normalize audio channels to between -1.0 and +1.0
audio[:,0] = audio[:,0]/abs(audio[:,0]).max()
audio[:,1] = audio[:,1]/abs(audio[:,1]).max()
# Normalize image to between 0 and 255
image = image/(image.max()/255.0)
Gibt es eine weniger ausführlich, Komfortfunktion Art und Weise, dies zu tun? matplotlib.colors.Normalize()
scheint nicht verwandt zu sein.
Lösung
audio /= np.max(np.abs(audio),axis=0)
image *= (255.0/image.max())
Mit /=
und *=
ermöglicht es Ihnen, eine Zwischen temporäre Array zu beseitigen, so etwas Speicher sparen. Die Multiplikation ist weniger teuer als Teilung, so
image *= 255.0/image.max() # Uses 1 division and image.size multiplications
ist geringfügig schneller als
image /= image.max()/255.0 # Uses 1+image.size divisions
Da wir grundlegende numpy Methoden verwenden hier, ich denke, das etwa so effizient eine Lösung in numpy ist, wie sein kann.
In-Place-Operationen ändern nicht die dtype des Behälters Array. Da die gewünschten normalisierten Werte Schwimmer sind, muß der audio
und image
Arrays Gleitkommazahlen Punkt dtype haben, bevor die in-Place-Operationen durchgeführt werden.
Wenn sie Gleitkommazahlen dtype nicht bereits sind, müssen Sie sie konvertieren astype
verwenden. Zum Beispiel:
image = image.astype('float64')
Andere Tipps
Wenn das Array sowohl positive als auch negative Daten enthält, würde ich gehen mit:
import numpy as np
a = np.random.rand(3,2)
# Normalised [0,1]
b = (a - np.min(a))/np.ptp(a)
# Normalised [0,255] as integer
c = 255*(a - np.min(a))/np.ptp(a).astype(int)
# Normalised [-1,1]
d = 2.*(a - np.min(a))/np.ptp(a)-1
Auch erwähnenswert, auch wenn es nicht OPs Frage ist, Standardisierung :
e = (a - np.mean(a)) / np.std(a)
Sie können rescale auch sklearn
verwenden. Die Vorteile sind, dass Sie normalisieren die Standardabweichung einstellen kann, zusätzlich zu den mittleren Zentrieren der Daten, und dass Sie diese auf jeder Achse tun, durch Funktionen oder durch Aufzeichnungen.
from sklearn.preprocessing import scale
X = scale( X, axis=0, with_mean=True, with_std=True, copy=True )
Das Schlüsselwort Argumente axis
, with_mean
, with_std
sind selbsterklärend und werden in ihren Standardzustand gezeigt. Das Argument copy
führt die Operation an Ort und Stelle, wenn es um False
gesetzt. Dokumentation href="http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.scale.html">.
Sie können die "i" (wie in idiv, IMUL ..) Version, und es sieht nicht halb so schlimm:
image /= (image.max()/255.0)
Für den anderen Fall, dass Sie eine Funktion schreiben, kann ein n-dimensionales Array von Spalten zu normalisieren:
def normalize_columns(arr):
rows, cols = arr.shape
for col in xrange(cols):
arr[:,col] /= abs(arr[:,col]).max()
Eine einfache Lösung wird unter Verwendung der Scaler von der sklearn.preprocessing Bibliothek angeboten.
scaler = sk.MinMaxScaler(feature_range=(0, 250))
scaler = scaler.fit(X)
X_scaled = scaler.transform(X)
# Checking reconstruction
X_rec = scaler.inverse_transform(X_scaled)
Der Fehler X_rec-X Null. Sie können die feature_range für Ihre Bedürfnisse anpassen oder sogar ein standart Scaler sk.StandardScaler () verwenden,
Sie versuchen, Min-Max-Skala die Werte von audio
zwischen -1 und +1 und image
zwischen 0 und 255.
Mit sklearn.preprocessing.minmax_scale
sollte Ihr Problem leicht lösen.
z.
audio_scaled = minmax_scale(audio, feature_range=(-1,1))
und
shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)
Hinweis : Nicht mit dem Betrieb zu verwechseln, dass Skalen des Norm (Länge) eines Vektors auf einen bestimmten Wert (in der Regel 1), die auch bezeichnet wird allgemein als Normalisierung.
Ich habe versucht, nach diesem , und bekam den Fehler
TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''
Die numpy
Array Ich war zu normalisieren versuchen, war ein integer
Array. Es scheint, sie in Versionen Casting deprecated Typ> 1.10
, und Sie müssen den Einsatz numpy.true_divide()
zu lösen, die.
arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)
img
war ein PIL.Image
Objekt.