python 在numpy数组中乘

06odsfpq  于 2023-01-19  发布在  Python
关注(0)|答案(7)|浏览(167)

我尝试将2D数组中的每一项乘以1D数组中的相应项。如果我想将每一列乘以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 人这么做?非常感谢,亚历克斯

hsgswve4

hsgswve41#

如你所示的正规乘法:

>>> 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]])
41zrol4v

41zrol4v2#

我比较了不同选项的速度,发现所有选项(除了diag)的速度都一样快,这让我很惊讶。

A * b[:, None]

(or (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(13)],
    xlabel="len(A), len(b)",
)
1u4esq0p

1u4esq0p3#

您还可以使用矩阵乘法(又名点积):

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

numpy.dot(c,a)

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

lkaoscv7

lkaoscv74#

还有一个技巧(从v1.6开始)

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

np.einsum('ij,i->ij',A,b)

我对numpy broadcasting(newaxis)很精通,但是我仍然在摸索这个新的einsum工具,所以我不得不尝试一下来找到这个解决方案。
计时(使用Ipython timeit):

einsum: 4.9 micro
transpose: 8.1 micro
newaxis: 8.35 micro
dot-diag: 10.5 micro

顺便说一句,把i改成jnp.einsum('ij,j->ij',A,b),会产生亚历克斯不想要的矩阵,而np.einsum('ji,j->ji',A,b)实际上是双重转置。

2eafrhcq

2eafrhcq5#

对于那些在谷歌上迷失的灵魂,使用numpy.expand_dims然后numpy.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]])
trnvg8h3

trnvg8h36#

你需要将行数组转换成列数组,而transpose不能做到这一点。请改用reshape

>>> import numpy as np
>>> a = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> b = np.array([0,1,2])
>>> a * b
array([[ 0,  2,  6],
       [ 0,  5, 12],
       [ 0,  8, 18]])

使用整形:

>>> a * b.reshape(-1,1)
array([[ 0,  0,  0],
       [ 4,  5,  6],
       [14, 16, 18]])
uajslkp6

uajslkp67#

你为什么不

>>> m = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> c = np.array([0,1,2])
>>> (m.T * c).T

??

相关问题