Python函数与部分函数 - Scipy不支持部分函数
我在看 curve_fit
的 文档。这个 curve_fit
函数的第一个参数是要拟合的函数。我稍微修改了一下示例代码,试着把一个部分函数作为第一个参数传进去:
In:
import numpy as np
from scipy.optimize import curve_fit
def func( t, x , a, b, c): # I added a dummy variable t so that I can apply partials later
return a*np.exp(-b*x) + c + t
func = partial( func, 0 ) # use of partial to remove the dummy variable
x = np.linspace(0,4,50)
y = func(x, 2.5, 1.3, 0.5)
yn = y + 0.2*np.random.normal(size=len(x))
popt, pcov = curve_fit(func, x, yn) # curve_fit gets a partial instead of a Python function
Out:
TypeError: <functools.partial object at 0x104551c58> is not a Python function
唉,这让我有点失望。我想下次我会用 lambda
函数。那这里的问题是什么呢?函数能做的事情,部分函数又做不了什么呢?
2 个回答
2
更新:在Python 3.5和3.6中,getargspec可以处理部分函数,所以在使用curve_fit时搭配partial是可以正常工作的。我没有安装更早版本的Python 3,所以无法检查它们的情况。
使用的版本是:Python 3.6,SciPy 0.18.1,NumPy 1.12.0
import numpy as np
from functools import partial
from scipy.optimize import curve_fit
def func(t, x, a, b, c):
return a*np.exp(-b*x) + c + t
x = np.linspace(0,4,50)
pfunc = partial(func, 0.0)
y = pfunc(x, 2.5, 1.3, 0.5)
popt, pcov = curve_fit(pfunc, x, y)
print(popt, y[0:2])
pfunc = partial(func, 100.0)
y = pfunc(x, 2.5, 1.3, 0.5)
popt, pcov = curve_fit(pfunc, x, y)
print(popt, y[0:2])
[ 2.5 1.3 0.5] [ 3. 2.7482863]
[ 2.5 1.3 0.5] [ 103. 102.7482863]
3
curve_fit
这个函数使用了标准库中的 getargspec
,这个库叫做 inspect
,用来确定函数的参数。不过,遗憾的是,getargspec
不能处理部分函数:
In [31]: from inspect import getargspec
In [32]: from functools import partial
In [33]: def func(t, x, a, b, c):
....: return a*np.exp(-b*x) + c + t
....:
In [34]: pfunc = partial(func, 0)
getargspec(func)
这个用法是没问题的。
In [35]: getargspec(func)
Out[35]: ArgSpec(args=['t', 'x', 'a', 'b', 'c'], varargs=None, keywords=None, defaults=None)
但是 getargspec
不能处理部分函数:
In [36]: getargspec(pfunc)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-36-3fb5eaea7c94> in <module>()
----> 1 getargspec(pfunc)
/Users/warren/anaconda/python.app/Contents/lib/python2.7/inspect.pyc in getargspec(func)
814 func = func.im_func
815 if not isfunction(func):
--> 816 raise TypeError('{!r} is not a Python function'.format(func))
817 args, varargs, varkw = getargs(func.func_code)
818 return ArgSpec(args, varargs, varkw, func.func_defaults)
TypeError: <functools.partial object at 0x107ec6d08> is not a Python function