Python 如何将numpy.linalg.norm应用于矩阵的每一行?
我有一个2D矩阵,我想取每一行的范数。但是当我直接使用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
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