使用`numpy.vectorize`在ValueError中创建多维数组结果:使用序列设置数组元素

时间:2018-05-22 20:02:04

标签: python numpy vectorization scientific-computing

当我的dummy函数返回一个数组时,似乎只会出现这个问题,因此,正在创建一个多维数组。

我将问题简化为以下示例:

def dummy(x):
    y = np.array([np.sin(x), np.cos(x)])
    return y

x = np.array([0, np.pi/2, np.pi])

我想要优化的代码如下所示:

y = []
for x_i in x:
    y_i = dummy(x_i)
    y.append(y_i)
y = np.array(y)

所以我想,我可以使用vectorize摆脱慢循环:

y = np.vectorize(dummy)(x)

但这会导致

ValueError: setting an array element with a sequence.

错误所在的序列甚至在哪里?!

2 个答案:

答案 0 :(得分:1)

我也不太了解错误,但是使用python 3.6.3你可以写:

y = dummy(x)

因此它会自动矢量化。

同样在官方documentation中写有以下内容:

  

提供矢量化功能主要是为了方便,而不是为了提高性能。实现基本上是for循环。

我希望这至少有一点帮助。

答案 1 :(得分:1)

给定标量时,您的函数返回一个数组:

In [233]: def dummy(x):
     ...:     y = np.array([np.sin(x), np.cos(x)])
     ...:     return y
     ...: 
     ...: 
In [234]: dummy(1)
Out[234]: array([0.84147098, 0.54030231])



In [235]: f = np.vectorize(dummy)
In [236]: f([0,1,2])
...
ValueError: setting an array element with a sequence.

vectorize构造一个空结果数组,并尝试将每个计算的结果放入其中。但是目标数组的单元格不能接受数组。

如果我们指定otypes参数,它确实有效:

In [237]: f = np.vectorize(dummy, otypes=[object])
In [238]: f([0,1,2])
Out[238]: 
array([array([0., 1.]), array([0.84147098, 0.54030231]),
       array([ 0.90929743, -0.41614684])], dtype=object)

也就是说,每个dummy数组都放在一个shape(3,)结果数组的元素中。

由于组件数组都具有相同的形状,我们可以stack

In [239]: np.stack(_)
Out[239]: 
array([[ 0.        ,  1.        ],
       [ 0.84147098,  0.54030231],
       [ 0.90929743, -0.41614684]])

但如上所述,vectorize并不承诺加速。我怀疑我们也可以使用较新的signature参数,但速度更慢。

如果你的函数有几个标量参数,那么

vectorize会有所帮助,并且你想在提供多组值时利用numpy广播。但作为1d阵列上的简单迭代的替代,它不是一种改进。