wake-up-neo.com

Wie normalisiere ich ein NumPy-Array auf einen bestimmten Bereich?

Nach der Verarbeitung eines Audio- oder Bild-Arrays muss es innerhalb eines Bereichs normalisiert werden, bevor es in eine Datei zurückgeschrieben werden kann. Das kann so gemacht werden:

# 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ührliche, praktische Möglichkeit, dies zu tun? matplotlib.colors.Normalize() scheint nicht verwandt zu sein.

107
endolith
audio /= np.max(np.abs(audio),axis=0)
image *= (255.0/image.max())

Mit /= und *= ermöglicht es Ihnen, ein temporäres Zwischenarray zu entfernen, wodurch Speicherplatz gespart wird. Multiplikation ist also billiger als Division

image *= 255.0/image.max()    # Uses 1 division and image.size multiplications

ist etwas schneller als

image /= image.max()/255.0    # Uses 1+image.size divisions

Da wir hier grundlegende Numpy-Methoden anwenden, denke ich, dass dies eine möglichst effiziente Lösung für Numpy ist.


In-Place-Vorgänge ändern den d-Typ des Container-Arrays nicht. Da die gewünschten normalisierten Werte Gleitkommazahlen sind, müssen die Arrays audio und image Gleitkommazahlen vom Typ d aufweisen, bevor die In-Place-Operationen ausgeführt werden. Wenn sie noch keinen Gleitkomma-D-Typ haben, müssen Sie sie mit astype konvertieren. Beispielsweise,

image = image.astype('float64')
118
unutbu

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

erwähnenswert, auch wenn es sich nicht um die Frage von OP handelt, Standardisierung :

e = (a - np.mean(a)) / np.std(a)
46
Tactopoda

Sie können auch mit sklearn neu skalieren. Die Vorteile bestehen darin, dass Sie die Standardabweichung zusätzlich zur Mittelwertzentrierung der Daten normalisieren und dies entweder auf der Achse, nach Features oder nach Datensätzen tun können.

from sklearn.preprocessing import scale
X = scale( X, axis=0, with_mean=True, with_std=True, copy=True )

Die Schlüsselwortargumente axis, with_mean, with_std sind selbsterklärend und werden in ihrem Standardzustand angezeigt. Das Argument copy führt die Operation direkt aus, wenn es auf False gesetzt ist. Dokumentation hier .

36
cjohnson318

Sie können die "i" -Version (wie in idiv, imul ..) verwenden, und es sieht nicht halb so schlecht aus:

image /= (image.max()/255.0)

Für den anderen Fall können Sie eine Funktion schreiben, um ein n-dimensionales Array nach Spalten zu normalisieren:

def normalize_columns(arr):
    rows, cols = arr.shape
    for col in xrange(cols):
        arr[:,col] /= abs(arr[:,col]).max()
11
u0b34a0f6ae

Sie versuchen, die Werte von audio zwischen -1 und +1 und image zwischen 0 und 255 von Min-Max zu skalieren.

Mit sklearn.preprocessing.minmax_scale , sollte Ihr Problem leicht lösen.

z.B.:

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)

Anmerkung : Nicht zu verwechseln mit der Operation, die die Norm (Länge) eines Vektors auf einen bestimmten Wert skaliert (normalerweise) 1), was üblicherweise auch als Normalisierung bezeichnet wird.

4
yellow01

Eine einfache Lösung ist die Verwendung der von der Bibliothek sklearn.preprocessing angebotenen Skalierer.

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 ist Null. Sie können den feature_range an Ihre Bedürfnisse anpassen oder sogar einen Standard-Scaler sk.StandardScaler () verwenden.

4
Pantelis

Ich habe versucht, this zu folgen, und habe den Fehler erhalten

TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''

Das Array numpy, das ich zu normalisieren versuchte, war ein Array integer. Es scheint, als hätten sie das Typumwandeln in Versionen> 1.10 Abgelehnt, und Sie müssen numpy.true_divide() verwenden, um dies zu beheben.

arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)

img war ein PIL.Image Objekt.

2
SpoiledBrat