在一个numpy数组中相乘
我试图用二维数组中的每个项乘以一维数组中的相应项。 如果我想用1D数组乘以每一列,这很容易,如numpy.multiply函数所示。 但是我想做相反的事情,把每一个词汇都放在一行中。 换句话说,我想要繁殖:
[1,2,3] [0] [4,5,6] * [1] [7,8,9] [2]
并得到
[0,0,0] [4,5,6] [14,16,18]
但是我得到了
[0,2,6] [0,5,12] [0,8,18]
有谁知道是否有一个优雅的方式来做到这一点与numpy? 亚历克斯,谢谢
像你这样的正常乘法表明:
>>> import numpy as np >>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> m * c array([[ 0, 2, 6], [ 0, 5, 12], [ 0, 8, 18]])
如果你添加一个轴,它将会以你想要的方式相乘:
>>> m * c[:, np.newaxis] array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]])
你也可以转置两次:
>>> (mT * c).T array([[ 0, 0, 0], [ 4, 5, 6], [14, 16, 18]])
你也可以使用matrix乘法(又名点积):
a = [[1,2,3],[4,5,6],[7,8,9]] b = [0,1,2] c = numpy.diag(b) numpy.dot(c,a)
更优雅的可能是品味的问题。
还有一个技巧(截至v1.6)
A=np.arange(1,10).reshape(3,3) b=np.arange(3) np.einsum('ij,i->ij',A,b)
我熟练掌握numpy广播( newaxis
),但我仍然find了解决这个新的工具的方法。 所以我玩了一下find这个解决scheme。
计时(使用Ipython timeit):
einsum: 4.9 micro transpose: 8.1 micro newaxis: 8.35 micro dot-diag: 10.5 micro
顺便说一句,将i
改为j
, np.einsum('ij,j->ij',A,b)
产生Alex不想要的matrix。 而np.einsum('ji,j->ji',A,b)
实际上是双转置。
我比较了不同的速度选项,发现 – 令我惊讶的是 – 所有选项( diag
除外)同样快:
代码重现情节:
import numpy import perfplot def newaxis(data): A, b = data return A * b[:, numpy.newaxis] def double_transpose(data): A, b = data return (AT * b).T def double_transpose_contiguous(data): A, b = data return numpy.ascontiguousarray((AT * b).T) def diag_dot(data): A, b = data return numpy.dot(numpy.diag(b), A) def einsum(data): A, b = data return numpy.einsum('ij,i->ij', A, b) perfplot.show( setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)), kernels=[ newaxis, double_transpose, double_transpose_contiguous, diag_dot, einsum ], n_range=[2**k for k in range(10)], logx=True, logy=True, xlabel='len(A), len(b)' )
你为什么不这样做?
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> c = np.array([0,1,2]) >>> (mT * c).T
??