web-dev-qa-db-fra.com

Comment normaliser un tableau NumPy dans une certaine plage?

Après avoir effectué certains traitements sur un tableau audio ou image, il doit être normalisé dans une plage avant de pouvoir être réécrit dans un fichier. Cela peut être fait comme suit:

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

Existe-t-il une manière moins verbeuse et pratique de faire cela? matplotlib.colors.Normalize() ne semble pas être lié.

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

En utilisant /= et *= vous permet d’éliminer un tableau temporaire intermédiaire et d’économiser de la mémoire. La multiplication est moins chère que la division, donc

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

est légèrement plus rapide que

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

Étant donné que nous utilisons des méthodes numpy de base, je pense que cette solution est aussi efficace que numpy.


Les opérations sur place ne modifient pas le type de données du tableau de conteneurs. Comme les valeurs normalisées souhaitées sont des valeurs flottantes, les tableaux audio et image doivent comporter un type de point en virgule flottante avant que les opérations in-situ ne soient effectuées. S'ils ne sont pas déjà de type d à virgule flottante, vous devrez les convertir en utilisant astype. Par exemple,

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

Si le tableau contient à la fois des données positives et négatives, je choisirais:

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

aussi, mérite d'être mentionné même si ce n'est pas la question de OP, normalisation :

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

Vous pouvez également redimensionner avec sklearn. Les avantages sont que vous pouvez ajuster la déviation standard, normaliser, en plus du centrage de la moyenne des données, et que vous pouvez le faire sur un axe, par entité ou par enregistrement.

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

Les arguments de mots clés axis, with_mean, with_std s'expliquent d'eux-mêmes et sont affichés dans leur état par défaut. L'argument copy exécute l'opération sur place s'il est défini sur False. Documentation ici .

36
cjohnson318

Vous pouvez utiliser la version "i" (comme dans idiv, imul ..), et elle n’a pas l’air mauvais:

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

Dans l’autre cas, vous pouvez écrire une fonction pour normaliser un tableau à n dimensions par des colonnes:

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

Vous essayez de min-max mettre à l'échelle les valeurs de audio entre -1 et +1 et image entre 0 et 255.

Utiliser sklearn.preprocessing.minmax_scale , devrait facilement résoudre votre problème.

par exemple.:

audio_scaled = minmax_scale(audio, feature_range=(-1,1))

et

shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)

note : à ne pas confondre avec l'opération qui met à l'échelle le norme (longueur) d'un vecteur à une certaine valeur (généralement 1), qui est également communément appelé la normalisation.

4
yellow01

Une solution simple consiste à utiliser les scalers proposés par la bibliothèque sklearn.preprocessing.

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)

L'erreur X_rec-X sera zéro. Vous pouvez adapter la fonctionnalité à vos besoins, ou même utiliser un détartreur standard. Sk.StandardScaler ()

4
Pantelis

J'ai essayé de suivre this , et j'ai eu l'erreur

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

Le tableau numpy que je tentais de normaliser était un tableau integer. Il semble qu'ils déconseillent la conversion de types dans les versions> 1.10, Et vous devez utiliser numpy.true_divide() pour résoudre ce problème.

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

img était un objet PIL.Image.

2
SpoiledBrat