numpy:如何向量化返回不同形状数组的函数?

numpy: How to vectorize a function returning arrays of different shapes?

我需要矢量化一个函数,该函数可以 return 形状为 (2,3)(3,3) 的数组。可能吗?

我这样创建矢量化函数:

my_func_v = np.vectorize(my_func, signature='()->(n,m)')

而且只要函数returns只有(2,3)或(3,3)数组,就可以正常工作。但是一旦结果形状混合,numpy 就会失败并出现错误:

ValueError: could not broadcast input array from shape (3,3) into shape (2,3)

是否可以混合来自矢量化函数的 returned 形状?

我可能不应该花时间,因为您没有提供最小的工作示例。但是让我举例说明 signature:

In [190]: f = np.vectorize(lambda x: x * np.ones((2, 3), int), signature="()->(n,m)")
In [191]: f(np.arange(4))
Out[191]: 
array([[[0, 0, 0],
        [0, 0, 0]],

       [[1, 1, 1],
        [1, 1, 1]],

       [[2, 2, 2],
        [2, 2, 2]],

       [[3, 3, 3],
        [3, 3, 3]]])

return 的形状是参数加上 (n,m)。显然对于数字数组,最后两个维度不能混合。上面产生 (4,2,3),下面产生 (2,2,2,3)

In [192]: f(np.arange(4).reshape(2,2))
Out[192]: 
array([[[[0, 0, 0],
         [0, 0, 0]],

        [[1, 1, 1],
         [1, 1, 1]]],


       [[[2, 2, 2],
         [2, 2, 2]],

        [[3, 3, 3],
         [3, 3, 3]]]])

如果我删除签名,并指定对象 return 类型:

In [194]: f = np.vectorize(lambda x: x * np.ones((2, 3), int), otypes=['object'])
In [195]: f(np.arange(4).reshape(2, 2))
Out[195]: 
array([[array([[0, 0, 0],
               [0, 0, 0]]), array([[1, 1, 1],
                                   [1, 1, 1]])],
       [array([[2, 2, 2],
               [2, 2, 2]]), array([[3, 3, 3],
                                   [3, 3, 3]])]], dtype=object)

现在元素数组的形状可以变化。

通常我不鼓励使用 vectorize,因为它不是真正的“矢量化”。它有明确的性能免责声明。对象 dtype 数组比列表好一点,在某些方面更差。

In [196]: timeit f(np.arange(1000))
9.45 ms ± 67.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [197]: timeit [x*np.ones((2,3),int) for x in range(1000)]
9.46 ms ± 290 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [198]: timeit np.array([x*np.ones((2,3),int) for x in range(1000)])
9.83 ms ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

以前 np.vectorize 比等效的列表理解慢。现在它对于小参数仍然较慢,但它的扩展性更好。