我试图将2D数组中的每个项乘以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可以做到这一点吗?非常感谢Alex
我试图将2D数组中的每个项乘以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可以做到这一点吗?非常感谢Alex
A * B
需要通过添加新轴()来进行A * B[...,None]
转置。B
None
x = [[1],[2],[3]]
或类似的东西。
Answers:
像您显示的正常乘法:
>>> 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]])
您还可以移调两次:
>>> (m.T * c).T
array([[ 0, 0, 0],
[ 4, 5, 6],
[14, 16, 18]])
[a,b] op [c,d] -> [[a*c, b*c], [a*d, b*d]]
。
我比较了不同的速度选项,发现–令我惊讶的是-所有选项(除外diag
)都同样快。我个人使用
A * b[:, None]
(或(A.T * b).T
),因为它很短。
复制剧情的代码:
import numpy
import perfplot
def newaxis(data):
A, b = data
return A * b[:, numpy.newaxis]
def none(data):
A, b = data
return A * b[:, None]
def double_transpose(data):
A, b = data
return (A.T * b).T
def double_transpose_contiguous(data):
A, b = data
return numpy.ascontiguousarray((A.T * 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.save(
"p.png",
setup=lambda n: (numpy.random.rand(n, n), numpy.random.rand(n)),
kernels=[
newaxis,
none,
double_transpose,
double_transpose_contiguous,
diag_dot,
einsum,
],
n_range=[2 ** k for k in range(14)],
logx=True,
logy=True,
xlabel="len(A), len(b)",
)
您还可以使用矩阵乘法(又名点积):
a = [[1,2,3],[4,5,6],[7,8,9]]
b = [0,1,2]
c = numpy.diag(b)
numpy.dot(c,a)
哪个更优雅可能是一个品味问题。
dot
在这里真的太过分了。你只是在做不必要乘以0和补充为0
diag
矩阵时会占用大量内存。
另一个技巧(从v1.6开始)
A=np.arange(1,10).reshape(3,3)
b=np.arange(3)
np.einsum('ij,i->ij',A,b)
我精通numpy广播(newaxis
),但仍可以在这个新einsum
工具周围找到自己的出路。因此,我花了些力气找到了这个解决方案。
时间(使用Ipython timeit):
einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro
顺便说一句,将a更改i
为j
,np.einsum('ij,j->ij',A,b)
会生成Alex不需要的矩阵。并且np.einsum('ji,j->ji',A,b)
实际上会进行双重转置。
einsumm
(25 micro)的速度是其他速度的两倍(点diag的速度更慢)。这是NP 1.7,使用“ libatlas3gf-sse2”和“ libatlas-base-dev”(Ubuntu 10.4,单处理器)进行了最新编译。 timeit
给出10000个循环中的最佳循环。
numpy
版本。
对于那些在Google上迷失了灵魂的人,使用numpy.expand_dims
thennumpy.repeat
将起作用,并且还将在更高维度的情况下起作用(即,将形状(10,12,3)乘以(10,12))。
>>> import numpy
>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b = numpy.array([0,1,2])
>>> b0 = numpy.expand_dims(b, axis = 0)
>>> b0 = numpy.repeat(b0, a.shape[0], axis = 0)
>>> b1 = numpy.expand_dims(b, axis = 1)
>>> b1 = numpy.repeat(b1, a.shape[1], axis = 1)
>>> a*b0
array([[ 0, 2, 6],
[ 0, 5, 12],
[ 0, 8, 18]])
>>> a*b1
array([[ 0, 0, 0],
[ 4, 5, 6],
[14, 16, 18]])
你为什么不做
>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> (m.T * c).T
??