在一个numpy数组中相乘

Ale*_*x S 64 python arrays numpy

我试图将二维数组中的每个项乘以一维数组中的相应项.如果我想将每列乘以1D数组,这很容易,如numpy.multiply函数所示.但我想做相反的事情,将行中的每个术语相乘.换句话说,我想成倍增加:

[1,2,3]   [0]
[4,5,6] * [1]
[7,8,9]   [2]
Run Code Online (Sandbox Code Playgroud)

得到

[0,0,0]
[4,5,6]
[14,16,18]
Run Code Online (Sandbox Code Playgroud)

但我得到了

[0,2,6]
[0,5,12]
[0,8,18]
Run Code Online (Sandbox Code Playgroud)

有没有人知道是否有一种优雅的方式来做numpy?非常感谢,Alex

jte*_*ace 90

像你所示的正常乘法:

>>> 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]])
Run Code Online (Sandbox Code Playgroud)

如果添加轴,它将以您希望的方式相乘:

>>> m * c[:, np.newaxis]
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])
Run Code Online (Sandbox Code Playgroud)

你也可以转置两次:

>>> (m.T * c).T
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])
Run Code Online (Sandbox Code Playgroud)


Nic*_*mer 25

我比较了不同的速度选项,发现 - 令我惊讶的是 - 所有选项(除外diag)都同样快.我个人用

A * b[:, None]
Run Code Online (Sandbox Code Playgroud)

(或(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)",
)
Run Code Online (Sandbox Code Playgroud)

  • 很好的接触,提供了情节的代码。谢谢。 (4认同)

Jam*_*s K 16

你也可以使用矩阵乘法(aka dot product):

a = [[1,2,3],[4,5,6],[7,8,9]]
b = [0,1,2]
c = numpy.diag(b)

numpy.dot(c,a)
Run Code Online (Sandbox Code Playgroud)

哪个更优雅可能是品味问题.

  • `dot`在这里真的太过分了.你只是做了不必要的乘法0和0的加法. (10认同)
  • 很好,+ 1,没有想到这一点 (2认同)
  • 如果您想将nx1向量乘以d大于n的nxd矩阵,这也可能触发内存问题。 (2认同)

hpa*_*ulj 15

又一招(截至v1.6)

A=np.arange(1,10).reshape(3,3)
b=np.arange(3)

np.einsum('ij,i->ij',A,b)
Run Code Online (Sandbox Code Playgroud)

我精通numpy broadcast(newaxis),但我仍然在找到这个新einsum工具的方法.所以我玩了一下找到这个解决方案.

计时(使用Ipython timeit):

einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro
Run Code Online (Sandbox Code Playgroud)

顺便说一句,将a更改ij,np.einsum('ij,j->ij',A,b)会生成Alex不想要的矩阵.而且np.einsum('ji,j->ji',A,b)呢,实际上,双转.