web-dev-qa-db-fra.com

Comment normaliser un tableau numpy à 2 dimensions en python moins détaillé?

Étant donné un tableau 3 fois 3 numpy

a = numpy.arange(0,27,3).reshape(3,3)

# array([[ 0,  3,  6],
#        [ 9, 12, 15],
#        [18, 21, 24]])

Pour normaliser les lignes du tableau à 2 dimensions auquel j'ai pensé

row_sums = a.sum(axis=1) # array([ 9, 36, 63])
new_matrix = numpy.zeros((3,3))
for i, (row, row_sum) in enumerate(Zip(a, row_sums)):
    new_matrix[i,:] = row / row_sum

Il doit y avoir un meilleur moyen, n'est-ce pas?

Peut-être pour clarifier: par normalisation, je veux dire, la somme des entrées par ligne doit être une. Mais je pense que cela sera clair pour la plupart des gens.

71
Aufwind

La radiodiffusion est vraiment bonne pour cela:

row_sums = a.sum(axis=1)
new_matrix = a / row_sums[:, numpy.newaxis]

row_sums[:, numpy.newaxis] remodèle les sommes de row_de somme de (3,) à (3, 1). Lorsque vous faites a / b, a et b sont diffusés l'un contre l'autre.

Vous pouvez en savoir plus sur broadcasthere ou même mieux here .

108
Bi Rico

Scikit-learn a une fonction de normalisation qui vous permet d’appliquer diverses normalisations. Le "faire la somme à 1" est la norme L1, et pour prendre cela faire:

from sklearn.preprocessing import normalize
matrix = numpy.arange(0,27,3).reshape(3,3).astype(numpy.float64)

#array([[  0.,   3.,   6.],
#   [  9.,  12.,  15.],
#   [ 18.,  21.,  24.]])

normed_matrix = normalize(matrix, axis=1, norm='l1')

#[[ 0.          0.33333333  0.66666667]
#[ 0.25        0.33333333  0.41666667]
#[ 0.28571429  0.33333333  0.38095238]]

Maintenant, vos lignes totaliseront 1.

75
rogueleaderr

Je pense que cela devrait fonctionner,

a = numpy.arange(0,27.,3).reshape(3,3)

a /=  a.sum(axis=1)[:,numpy.newaxis]
8
tom10

Si vous essayez de normaliser chaque ligne de telle sorte que sa magnitude soit égale à un (c'est-à-dire que la longueur unitaire d'une ligne est égale à un ou que la somme du carré de chaque élément d'une ligne correspond à un)

import numpy as np

a = np.arange(0,27,3).reshape(3,3)

result = a / np.linalg.norm(a, axis=-1)[:, np.newaxis]
# array([[ 0.        ,  0.4472136 ,  0.89442719],
#        [ 0.42426407,  0.56568542,  0.70710678],
#        [ 0.49153915,  0.57346234,  0.65538554]])

Vérification:

np.sum( result**2, axis=-1 )
# array([ 1.,  1.,  1.]) 
3
walt

il semble que cela fonctionne aussi

def normalizeRows(M):
    row_sums = M.sum(axis=1)
    return M / row_sums
1
Jamesszm

Ou en utilisant la fonction lambda, comme

>>> vec = np.arange(0,27,3).reshape(3,3)
>>> import numpy as np
>>> norm_vec = map(lambda row: row/np.linalg.norm(row), vec)

chaque vecteur de vec aura une norme d'unité.

0
XY.W

Je pense que vous pouvez normaliser la somme des éléments de ligne à 1 par ceci: new_matrix = a / a.sum(axis=1, keepdims=1). Et la normalisation des colonnes peut être effectuée avec new_matrix = a / a.sum(axis=0, keepdims=1). J'espère que ça peut marcher.

0
Fanwang Meng

Vous pouvez également utiliser la transposition matricielle:

(a.T / row_sums).T
0
Maciek