如何将numpy.linalg.norm应用到matrix的每一行?

我有一个二维matrix,我想要采取每行的规范。 但是当我直接使用numpy.linalg.norm(X) ,它就是整个matrix的规范。

我可以通过使用一个for循环来取每一行的规范,然后对每个X[i]进行规范,但是从我有30k行开始需要很长的时间。

任何build议find更快的方法? 或者是否可以将np.linalg.norm应用于matrix的每一行?

请注意,如perimosordiae所示 ,从NumPy版本1.9开始, np.linalg.norm(x, axis=1)是计算L2范数的最快方法。


如果你正在计算L2范数,你可以直接计算(使用axis=-1参数来计算行数):

 np.sum(np.abs(x)**2,axis=-1)**(1./2) 

Lp-norms当然可以被类似地计算。

它比np.apply_along_axis ,虽然可能不方便:

 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 

还可以直接计算其他normforms(具有类似的加速):

 In [55]: %timeit np.apply_along_axis(lambda row:np.linalg.norm(row,ord=1), 1, x) 1000 loops, best of 3: 203 us per loop In [54]: %timeit np.sum(abs(x), axis=-1) 100000 loops, best of 3: 10.9 us per loop 

复活一个老问题由于一个颠簸的更新。 从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 

并且certificate它正在计算同样的事情:

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

尝试以下操作:

 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.sqrt(numpy.einsum('ij,ij->i', a, a)) 

在这里输入图像说明


代码重现情节:

 import numpy import perfplot def sum_sqrt(a): return numpy.sqrt(numpy.sum(numpy.abs(a)**2, axis=-1)) def apply_norm_along_axis(a): return numpy.apply_along_axis(numpy.linalg.norm, 1, a) def norm_axis(a): return numpy.linalg.norm(a, axis=1) def einsum_sqrt(a): return numpy.sqrt(numpy.einsum('ij,ij->i', a, a)) perfplot.show( setup=lambda n: numpy.random.rand(n, 3), kernels=[sum_sqrt, apply_norm_along_axis, norm_axis, einsum_sqrt], n_range=[2**k for k in range(15)], logx=True, logy=True, xlabel='len(a)' )