如何解决 numpy.vectorize() 的广播问题
How to fix broadcasting issues with numpy.vectorize()
我正在编写一个自定义函数,我希望它的行为就像一个 numpy 函数,能够接收一个数组,并对输入列表的每个元素执行相同的操作,然后返回包含所有结果的相同形状的列表。
幸运的是,有一个解决方案:numpy.vectorize()
所以我使用了它:我有一个以正弦波形式创建模型的函数,它接受两个变量:一个 numpy 列表 X
包含正弦函数的一些输入值,和一个包含正弦曲线可能具有的四个可能参数的 numpy 列表 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,)
由于列表 param
有 4 个元素长,我知道该函数忽略了我将其从矢量化中排除的命令。那是个问题。
我尝试指定最终结果应该是一个 ndArray,这并没有改变错误。
np_sine = np.vectorize(sine, excluded=['param'], otypes=[np.ndarray])
使用此功能的正确方法是什么?
您指定的 excluded
错误。
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])
对于关键字参数:
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])
我正在编写一个自定义函数,我希望它的行为就像一个 numpy 函数,能够接收一个数组,并对输入列表的每个元素执行相同的操作,然后返回包含所有结果的相同形状的列表。
幸运的是,有一个解决方案:numpy.vectorize()
所以我使用了它:我有一个以正弦波形式创建模型的函数,它接受两个变量:一个 numpy 列表 X
包含正弦函数的一些输入值,和一个包含正弦曲线可能具有的四个可能参数的 numpy 列表 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,)
由于列表 param
有 4 个元素长,我知道该函数忽略了我将其从矢量化中排除的命令。那是个问题。
我尝试指定最终结果应该是一个 ndArray,这并没有改变错误。
np_sine = np.vectorize(sine, excluded=['param'], otypes=[np.ndarray])
使用此功能的正确方法是什么?
您指定的 excluded
错误。
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])
对于关键字参数:
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])