具有非标量输出的Numpy向量化功能 [英] Numpy vectorize function with non-scalar output
问题描述
我正在尝试对输出列表的函数进行向量化.我希望从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.
对于新的func
,signature
方法仍然有效.我添加了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屋!