Python 如何使用numpy.vectorize()解决广播问题

Python 如何使用numpy.vectorize()解决广播问题,python,numpy,vectorization,array-broadcasting,Python,Numpy,Vectorization,Array Broadcasting,我正在编写一个自定义函数,我希望它的行为就像一个numpy函数一样,能够接受数组,对输入列表的每个元素执行相同的操作,并返回一个具有相同形状的列表和所有结果 幸运的是,有一个解决方案: 所以我使用了它:我有一个函数,它以正弦波的形式创建一个模型,它包含两个变量:一个numpy listX,包含一些正弦函数的输入值,一个numpy listparam,它包含正弦曲线可能具有的四个参数 import numpy as np def sine(X, param): #Unpacking par

我正在编写一个自定义函数,我希望它的行为就像一个numpy函数一样,能够接受数组,对输入列表的每个元素执行相同的操作,并返回一个具有相同形状的列表和所有结果

幸运的是,有一个解决方案:

所以我使用了它:我有一个函数,它以正弦波的形式创建一个模型,它包含两个变量:一个numpy list
X
,包含一些正弦函数的输入值,一个numpy list
param
,它包含正弦曲线可能具有的四个参数

import numpy as np
def sine(X, param):
    #Unpacking param
    A = param[0]
    P = param[1]
    Phi = param[2]
    B = param[3]

    #translating variables
    #Phi = t0/P
    f = X/P
    Y = A*np.sin(2*np.pi*(f + Phi)) + B
    return Y
由于只有输入值
X
需要广播,而所有参数始终是必需的,因此,根据文档,将函数矢量化的方法如下:

np_sine = np.vectorize(sine, excluded=['param']) #makes sine() behave like a numpy function
…以便
param
正确地从矢量化中排除

此方法非常有用,因为我将使此模型适合数据集,这需要偶尔调整参数,同时,使用此方法,我需要的代码只有一行:

CHIsqrt = np.sum(((ydata - np_sine(xdata, param))/yerr)**2)
其中,
ydata
xdata
yerr
是同样长的数据点列表,其中
param
是四个参数的列表

然而,结果是一个广播错误:

 File "C:\Users\Anonymous\AppData\Local\Programs\Python\Python36\lib\site-packages\numpy\lib\function_base.py", line 2831, in _vectorize_call outputs = ufunc(*inputs)
 ValueError: operands could not be broadcast together with shapes (500,) (4,)
由于list
param
有4个元素长,因此该函数忽略了我的命令,将其从矢量化中排除。这是个问题

我尝试指定最终结果应该是一个ndArray,这并没有改变错误

np_sine = np.vectorize(sine, excluded=['param'], otypes=[np.ndarray])

使用此功能的正确方法是什么?

您指定的
排除
错误

In [270]: def foo(x, param):
     ...:     a,b,c = param
     ...:     return a*x
     ...: 
In [271]: f = np.vectorize(foo, excluded=[1])  # specify by position
In [272]: f(np.arange(4),[1,3,2])
Out[272]: array([0, 1, 2, 3])
对于关键字arg:

In [277]: def foo(x, param=[0,0,0]):
     ...:     a,b,c = param
     ...:     return a*x
     ...:
In [278]: f = np.vectorize(foo, excluded=['param'])
In [279]: f(np.arange(4),param=[1,3,2])
Out[279]: array([0, 1, 2, 3])

有趣的是,使用字符串不适用于普通参数。文档中有一个示例说
>>def mypolyval(p,x):
,它显然有两个正常参数。然后,它继续排除
p
,方法是说
>>vpolyval=np.vectorize(mypolyval,excluded=['p'])
。您的解决方案有效,因此文档是错误的。但在示例中,
p
作为关键字参数传递,
p=[1,2,3]
vpolyval([1,2,3],x=[0,1])
仅在
之后有效。排除。添加(0)。Excluded实际上可能是指矢量化函数中的参数,而不是源(尽管在某种意义上它们是相同的)
您命名的
excluded
可能与
np_sine(扩展数据,param=param)
一起使用。