python-如何在python中更详细地规范二维numpy数组?


87

给定一个3乘3 numpy数组

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

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

为了规范二维数组的行,我想到了

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

必须有更好的方法,不是吗?

可能需要澄清:通过标准化我的意思是,每行条目的总和必须为1。但是我认为这对于大多数人来说都是显而易见的。


16
仔细地,“规格化”通常表示成分的平方和是1。您的定义对于大多数人来说很难说清楚;)
Coldfix

Answers:


137

广播确实对此有好处:

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

row_sums[:, numpy.newaxis]重塑row_sums从存在(3,)到存在(3, 1)。当你这样做a / bab会相互播出。

您可以在此处了解更多有关广播的 信息,甚至可以在此处了解更多。


27
使用a.sum(axis=1, keepdims=True)保持单例列的尺寸甚至可以进一步简化此尺寸,然后您可以在不使用的情况下一起广播np.newaxis
ali_m 2015年

6
如果row_sums中的任何一个为零怎么办?
2015年

7
这是上述问题的正确答案-但是,如果需要通常意义上的标准化,请使用np.linalg.norm代替a.sum
Coldfix

1
这是首选row_sums.reshape(3,1)吗?
Paul

1
它并不像强大的自排总和可以是0

103

Scikit-learn具有规范化功能,可让您应用各种规范化。“求和等于1”是L1范数,并且要这样做:

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]]

现在,您的行总计为1。


3
这还有一个优势,它可以在稀疏数组上工作,而稀疏数组不能像密集数组那样适合内存。
JEM_Mosig

10

我认为这应该有效,

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

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

2
好。注意D型的,以人气指数的变化,通过附加小数点27
维姆

3

如果要对每一行进行规范化,使其大小为1(即,一行的单位长度为1或一行中每个元素的平方和为1):

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

验证中:

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

Axis似乎不是np.linalg.norm的参数(是吗?)。
Ztyx

值得注意的是,这对应于l2规范(其中加总为1的行对应于l1规范)
dpb

3

我想你可以通过这个标准化行元素之和为1: new_matrix = a / a.sum(axis=1, keepdims=1)。并且可以使用进行列归一化new_matrix = a / a.sum(axis=0, keepdims=1)。希望这可以帮助您。



1

看来这也有效

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

1

您还可以使用矩阵转置:

(a.T / row_sums).T

0

或使用lambda函数,例如

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

vec的每个向量都有一个单位范数。


-2
normed_matrix = normalize(input_data, axis=1, norm='l1')
print(normed_matrix)

其中input_data是2D数组的名称

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.