Python 如何将numpy.linalg.norm应用于矩阵的每一行?

Python 如何将numpy.linalg.norm应用于矩阵的每一行?,python,numpy,Python,Numpy,我有一个2D矩阵,我想取每一行的范数。但是当我直接使用numpy.linalg.norm(X)时,它取整个矩阵的范数 我可以通过使用for循环获取每一行的范数,然后获取每一行的范数X[I],但这需要花费大量时间,因为我有3万行 有什么建议可以找到更快的方法吗?或者可以将np.linalg.norm应用于矩阵的每一行吗?尝试以下操作: In [16]: numpy.apply_along_axis(numpy.linalg.norm, 1, a) Out[16]: array([ 5.385164

我有一个2D矩阵,我想取每一行的范数。但是当我直接使用
numpy.linalg.norm(X)
时,它取整个矩阵的范数

我可以通过使用for循环获取每一行的范数,然后获取每一行的范数
X[I]
,但这需要花费大量时间,因为我有3万行

有什么建议可以找到更快的方法吗?或者可以将
np.linalg.norm
应用于矩阵的每一行吗?

尝试以下操作:

In [16]: numpy.apply_along_axis(numpy.linalg.norm, 1, a)
Out[16]: array([ 5.38516481,  1.41421356,  5.38516481])
其中
a
是二维阵列

上面计算L2范数。对于不同的标准,您可以使用以下内容:

In [22]: numpy.apply_along_axis(lambda row:numpy.linalg.norm(row,ord=1), 1, a)
Out[22]: array([9, 2, 9])
请注意,从NumPy版本1.9开始,
np.linalg.norm(x,axis=1)
是计算L2范数的最快方法


如果要计算L2范数,可以直接计算它(使用
axis=-1
参数沿行求和):

当然,Lp范数也可以类似地计算

它比np快得多。沿轴应用,尽管可能不那么方便:

In [48]: %timeit np.apply_along_axis(np.linalg.norm, 1, x)
1000 loops, best of 3: 208 us per loop

In [49]: %timeit np.sum(np.abs(x)**2,axis=-1)**(1./2)
100000 loops, best of 3: 18.3 us per loop
其他
ord
形式的
norm
也可以直接计算(具有类似的加速比):


由于numpy更新而恢复旧问题。从1.9版本开始,
numpy.linalg.norm
现在接受一个
axis
参数。[,]

这是镇上最快的新方法:

In [10]: x = np.random.random((500,500))

In [11]: %timeit np.apply_along_axis(np.linalg.norm, 1, x)
10 loops, best of 3: 21 ms per loop

In [12]: %timeit np.sum(np.abs(x)**2,axis=-1)**(1./2)
100 loops, best of 3: 2.6 ms per loop

In [13]: %timeit np.linalg.norm(x, axis=1)
1000 loops, best of 3: 1.4 ms per loop
为了证明它在计算同样的东西:

In [14]: np.allclose(np.linalg.norm(x, axis=1), np.sum(np.abs(x)**2,axis=-1)**(1./2))
Out[14]: True

比公认的答案快得多的是使用NumPy的

numpy.sqrt(numpy.einsum('ij,ij->i',a,a))
请注意对数刻度:


复制绘图的代码:

导入numpy
导入性能图
定义总和(a):
返回numpy.sqrt(numpy.sum(numpy.abs(a)**2,轴=-1))
def沿_轴(a)应用_norm_:
返回numpy。沿_轴应用_(numpy.linalg.norm,1,a)
def norm_轴(a):
返回numpy.linalg.norm(a,轴=1)
def einsum_sqrt(a):
返回numpy.sqrt(numpy.einsum(“ij,ij->i”,a,a))
perfplot.show(
setup=lambda n:numpy.random.rand(n,3),
内核=[sum_sqrt,沿_轴应用_norm_,norm_轴,einsum_sqrt],
n_范围=[2**k表示范围(20)中的k],
xlabel=“len(a)”,
)

如果你把x平方,为什么要做np.abs(x)?@Patrick:如果
x
的数据类型很复杂,那么它就有区别了。例如,如果
x=np.array([(1+1j,2+1j)])
那么
np.sum(np.abs(x)**2,axis=-1)**(1./2)
数组([2.64575131])
,而
np.sum(x**2,axis=-1)**(1./2)
数组([2.20320266+1.36165413j])
@perimosocordiae使用其
参数的更新是当前最快的方法。如果要对矩阵按列应用范数,如何执行相同操作?@user3515225:
np.linalg.norm(x,axis=0)
是指被求和的轴。对于2D数组,0轴表示行,因此
axis=0
导致
norm
对每个固定列的行进行求和。是否要解释这是/做什么?
In [10]: x = np.random.random((500,500))

In [11]: %timeit np.apply_along_axis(np.linalg.norm, 1, x)
10 loops, best of 3: 21 ms per loop

In [12]: %timeit np.sum(np.abs(x)**2,axis=-1)**(1./2)
100 loops, best of 3: 2.6 ms per loop

In [13]: %timeit np.linalg.norm(x, axis=1)
1000 loops, best of 3: 1.4 ms per loop
In [14]: np.allclose(np.linalg.norm(x, axis=1), np.sum(np.abs(x)**2,axis=-1)**(1./2))
Out[14]: True