【问题标题】:Generating an array of arrays in Python在 Python 中生成数组数组
【发布时间】:2022-06-13 02:18:52
【问题描述】:

我想将B的每个元素乘以整个数组A得到P。附加了当前和所需的输出。所需的输出基本上是一个由 2 个数组组成的数组,因为 B 中有两个元素。

import numpy as np
A=np.array([[1, 2, 3],
       [4, 5, 6],
       [7 , 8, 9]])
t = np.linspace(0,1,2)
B = 0.02109*np.exp(-t)
P=B*A
print(P)

目前产生错误:

ValueError: operands could not be broadcast together with shapes (2,) (3,3) 

想要的输出是

array(([[0.02109, 0.04218, 0.06327],
       [0.08436, 0.10545, 0.12654],
       [0.14763, 0.16872, 0.18981]]),
([[0.00775858, 0.01551716, 0.02327574],
       [0.03103432, 0.0387929 , 0.04655148],
       [0.05431006, 0.06206864, 0.06982722]]))

【问题讨论】:

  • np.einsum('i,jk', B, A)

标签: python arrays numpy multidimensional-array tensordot


【解决方案1】:

您可以这样做:

B.reshape(-1, 1, 1) * A

B[:, None, None] * A

其中-1: 指的是B.shape[0],即21, 1None, NoneB 添加两个额外的维度以获得所需的结果形状,即 (2, 3, 3).

【讨论】:

  • 这是最快的;充分利用numpy 广播。
【解决方案2】:

我能想到的最简单的方法是使用列表理解,然后再转换回 numpy.ndarray

np.asarray([A*i for i in B])

答案:

array([[[0.02109   , 0.04218   , 0.06327   ],
        [0.08436   , 0.10545   , 0.12654   ],
        [0.14763   , 0.16872   , 0.18981   ]],

       [[0.00775858, 0.01551715, 0.02327573],
        [0.03103431, 0.03879289, 0.04655146],
        [0.05431004, 0.06206862, 0.0698272 ]]])

【讨论】:

  • 当我们可以通过 numpy 数组执行此操作时,循环不是一个好的选择。
  • 是的,你是对的。这是一个相当的黑客
  • @Ali_Sh - 使用示例数组,速度是公认的np.tensordot 解决方案的两倍。
  • @MichaelSzczesny 是的,AYK,在小型阵列上(对于较大的阵列,这种循环可以通过 numba 加速)。
【解决方案3】:

有很多可能的方法:

以下是给定数组的运行时概览(请记住,对于更大的数组,这些会发生变化):

  • 重塑:0.000174 秒
  • 张量点:0.000550 秒
  • einsum:0.000196 秒
  • 手动循环:0.000326 秒

查看每个的实现:

numpy 重塑

在此处查找文档: Link

在不更改数据的情况下为数组赋予新形状。

在这里我们重塑了数组B,以便我们以后可以将它相乘:

import numpy as np
A=np.array([[1, 2, 3],
            [4, 5, 6],
            [7 , 8, 9]])

t = np.linspace(0,1,2)
B = 0.02109*np.exp(-t)
P = B.reshape(-1, 1, 1) * A
print(P)


numpy 张量点

在此处查找文档: Link

给定两个张量,a 和 b,以及一个包含两个 array_like 对象,(a_axes, b_axes),对 a 和 b 的乘积求和 a_axes 和 b_axes 指定的轴上的元素(组件)。 第三个参数可以是单个非负 integer_like 标量, N;如果是这样,那么 a 的最后 N 个维度和第一个 N b 的维度相加。

import numpy as np
A=np.array([[1, 2, 3],
            [4, 5, 6],
            [7 , 8, 9]])

t = np.linspace(0,1,2)
B = 0.02109*np.exp(-t)

P = np.tensordot(B, A, 0)
print(P)

numpy einsum(爱因斯坦求和)

在此处查找文档: Link

import numpy as np 
A=np.array([[1, 2, 3],
            [4, 5, 6],
            [7 , 8, 9]])

t = np.linspace(0,1,2)
B = 0.02109*np.exp(-t)
   
P = np.einsum('ij,k', A, B)
print(P)

注意:A 有两个维度,我们为它们的索引分配 ij。 B 有一个维度,我们将 k 分配给它的索引


手动循环

另一种简单的方法是循环(对于给定的输入比 tensordot 更快)。如果您出于某种原因不想使用 numpy,则可以将这种方法设为“无 numpy”。这是带有 numpy 的版本:

import numpy as np
A=np.array([[1, 2, 3],
            [4, 5, 6],
            [7 , 8, 9]])

t = np.linspace(0,1,2)
B = 0.02109*np.exp(-t)

products = []
for b in B:
    products.append(b*A)
P = np.array(products)
print(P)

#or the same as one-liner: np.asarray([A * elem for elem in B])

【讨论】:

  • tensordot 将问题转换为dot,例如np.dot(B[:,None],A.ravel()[None]).reshape(2,3,3)
猜你喜欢
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-26
  • 2015-12-21
  • 2011-03-11
  • 1970-01-01
相关资源
最近更新 更多