如何在python中规范化一个二维numpy数组?
给定一个3乘以3的numpy数组如何在python中规范化一个二维numpy数组?,python,arrays,syntax,numpy,normalization,Python,Arrays,Syntax,Numpy,Normalization,给定一个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 enu
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
一定有更好的办法,不是吗
也许要澄清一下:通过规范化,我的意思是,每行入口的总和必须是一。但我认为大多数人都会明白这一点。广播对这一点非常有益:
row_sums = a.sum(axis=1)
new_matrix = a / row_sums[:, numpy.newaxis]
行总和[:,numpy.newaxis]
将行总和从(3,)
重塑为(3,1)
。当您执行a/b
时,a
和b
会相互广播
你可以了解更多关于广播的内容,甚至更好。我认为这应该行得通
a = numpy.arange(0,27.,3).reshape(3,3)
a /= a.sum(axis=1)[:,numpy.newaxis]
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。如果您试图规范化每一行,使其大小为1(即,一行的单位长度为1或一行中每个元素的平方和为1): 验证:
np.sum( result**2, axis=-1 )
# array([ 1., 1., 1.])
看来这也行得通
def normalizeRows(M):
row_sums = M.sum(axis=1)
return M / row_sums
或者使用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的每个向量都有一个单位范数。您也可以使用矩阵转置:
(a.T / row_sums).T
我认为您可以通过以下方式将行元素总和规格化为1:
new_matrix=a/a.sum(axis=1,keepdims=1)
。
可以使用new_matrix=a/a.sum(axis=0,keepdims=1)
进行列规范化。希望这能有帮助
normed_matrix = normalize(input_data, axis=1, norm='l1')
print(normed_matrix)
如果input_data是2D阵列的名称,则可以使用内置的numpy函数:
np.linalg.norm(a,axis=1,keepdims=True)
以下是使用重塑的另一种可能方法:
a_norm = (a/a.sum(axis=1).reshape(-1,1)).round(3)
print(a_norm)
或者使用None
也可以:
a_norm = (a/a.sum(axis=1)[:,None]).round(3)
print(a_norm)
输出:
array([[0. , 0.333, 0.667],
[0.25 , 0.333, 0.417],
[0.286, 0.333, 0.381]])
好。请注意,通过将小数点添加到27,将数据类型更改为arange。Axis似乎不是np.linalg.norm的参数(不再是了?)。值得注意的是,这对应于l2范数(其中,与1相加的行对应于l1范数),这可以使用a.sum(Axis=1,keepdims=True)进一步简化
为了保持单例列维度,您可以在不使用np.newaxis
的情况下播放该维度。如果任何行和为零,该怎么办?这是上述问题的正确答案-但是如果需要常规意义上的规范化,请使用np.linalg.norm
而不是a.sum
!这比行和更可取吗?重塑(3,1)
?因为行和可能为0,所以它没有那么稳健。小心,“规格化”通常意味着组件的平方和为1。你的定义对大多数人来说都不太清楚;)@coldfix谈到了L2
norm,并认为它是最常见的(这可能是真的),而Aufwind使用L1
norm,它实际上也是一个norm。这还有一个优点,即它在稀疏数组上工作,而稀疏数组不能作为密集数组装入内存。
array([[0. , 0.333, 0.667],
[0.25 , 0.333, 0.417],
[0.286, 0.333, 0.381]])