Using `numpy.vectorize` to create multidimensional array results in ValueError: setting an array element with a sequence

Using `numpy.vectorize` to create multidimensional array results in ValueError: setting an array element with a sequence

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

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

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.

错误所指的序列在哪里?!

我也不太明白这个错误,但是使用 python 3.6.3 你可以写:

y = dummy(x)

所以它是自动向量化的。

在官方documentation中也有这样写的:

The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.

我希望这至少能有所帮助。

你的函数 returns 给定标量时的数组:

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数组放入一个形状为(3,)结果数组的元素中。

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

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

但如前所述,vectorize 不保证加速。我怀疑我们也可以使用较新的 signature 参数,但那会更慢。

vectorize 如果您的函数采用多个标量参数,并且您希望在提供值集时利用 numpy 广播,则有些意义。但是作为对一维数组的简单迭代的替代,它并不是一个改进。