具有非标量输出的Numpy向量化功能 [英] Numpy vectorize function with non-scalar output

查看:104
本文介绍了具有非标量输出的Numpy向量化功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试对输出列表的函数进行向量化.我希望从numpy列表中获取所有值,并使其返回一个矩阵,这样每一行都是输入向量中元素的输出.

I'm trying to vectorize a function that outputs a list. I wish to feed it all values from a numpy list and have it return a matrix, such that each row is an output for an element in the input vector.

import numpy as np

def func(x, n):
    o = []
    for i in range(n):
        o.append(x+i)
    return o

vec_func = np.vectorize(func)
matrix = vec_func(np.asarray([0, 1, 2]), 10)

但是我得到了错误

ValueError:设置具有序列的数组元素.

ValueError: setting an array element with a sequence.

我该如何解决?

推荐答案

frompyfunc可能更好:

In [525]: def fun(x):
     ...:     return x+.1, x+.2, x+.3
     ...: 

我指定1个输入,3个输出值.它返回dtype对象:

I specify 1 input, 3 output values. It returns dtype object:

In [526]: np.frompyfunc(fun,1,3)(np.arange(5))
Out[526]: 
(array([0.1, 1.1, 2.1, 3.1, 4.1], dtype=object),
 array([0.2, 1.2, 2.2, 3.2, 4.2], dtype=object),
 array([0.3, 1.3, 2.3, 3.3, 4.3], dtype=object))

这是3个数组的元组.可以使用stack将它们变成一个2d数组:

That's a tuple of 3 arrays. They can be turned into one 2d array with stack:

In [527]: np.stack(_, 1)
Out[527]: 
array([[0.1, 0.2, 0.3],
       [1.1, 1.2, 1.3],
       [2.1, 2.2, 2.3],
       [3.1, 3.2, 3.3],
       [4.1, 4.2, 4.3]], dtype=object)

我可以使用astype(float)来进一步.

我当然认为这是一个玩具功能.对于这种简单的事情,无需使用vectorize.

I assume, of course, that this is a toy func. For something this simple there's no need to use vectorize.

In [528]: fun(np.arange(5))
Out[528]: 
(array([ 0.1,  1.1,  2.1,  3.1,  4.1]),
 array([ 0.2,  1.2,  2.2,  3.2,  4.2]),
 array([ 0.3,  1.3,  2.3,  3.3,  4.3]))

vectorize所需的全部是otypes参数:

In [536]: np.vectorize(fun, otypes='ddd')(np.arange(5))
Out[536]: 
(array([ 0.1,  1.1,  2.1,  3.1,  4.1]),
 array([ 0.2,  1.2,  2.2,  3.2,  4.2]),
 array([ 0.3,  1.3,  2.3,  3.3,  4.3]))

如果函数返回的是数组而不是元组或列表,则可以使用signature:

If the function returns an array instead of a tuple or list, we could use signature:

In [546]: def fun(x):
     ...:     return np.array([x+.1, x+.2, x+.3])

In [547]: np.vectorize(fun, signature='()->(n)')(np.arange(5))
Out[547]: 
array([[ 0.1,  0.2,  0.3],
       [ 1.1,  1.2,  1.3],
       [ 2.1,  2.2,  2.3],
       [ 3.1,  3.2,  3.3],
       [ 4.1,  4.2,  4.3]])

或者使用原始的元组/列表大小写,将其包装在lambda中,np.vectorize(lambda x:np.array(fun(x)), signature='()->(n)')

Or with the original tuple/list case, wrap it in a lambda, np.vectorize(lambda x:np.array(fun(x)), signature='()->(n)')

经验表明,frompyfunc方法最快.具有otypes的vectorize稍慢一些(但它使用frompyfunc). signature是较新的方法,使用不同的代码,并且速度较慢.

Experience suggests that the frompyfunc approach is fastest. vectorize with otypes is a bit slower (but it uses frompyfunc). signature is newer method, using different code, and somewhat slower.

对于新的funcsignature方法仍然有效.我添加了excluded,因此它不会尝试broadcast n参数:

With your new func, the signature approach still works. I added excluded so it doesn't try to broadcast the n argument:

In [553]: np.vectorize(lambda x,n:np.array(func(x,n)), signature='()->(n)',excluded=[1])(np.arange(5),3)
Out[553]: 
array([[0, 1, 2],
       [1, 2, 3],
       [2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])
In [554]: np.vectorize(lambda x,n:np.array(func(x,n)), signature='()->(n)',excluded=[1])(np.arange(5),7)
Out[554]: 
array([[ 0,  1,  2,  3,  4,  5,  6],
       [ 1,  2,  3,  4,  5,  6,  7],
       [ 2,  3,  4,  5,  6,  7,  8],
       [ 3,  4,  5,  6,  7,  8,  9],
       [ 4,  5,  6,  7,  8,  9, 10]])

这篇关于具有非标量输出的Numpy向量化功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆