我正在尝试找到x0
参数,该参数尽可能地匹配绿色曲线上的蓝色模型(x0
控制垛口的宽度;见下文)。
这是我的尝试:
from pylab import *
from scipy.optimize import curve_fit
x=linspace(0,2*pi,1000)
def crenel(x):return sign(sin(x))
def inverter(x,x0): return (crenel(x-x0)+crenel(x+x0))/2
p,e = curve_fit(inverter,x,sin(x),1)
plot(x,inverter(x,*p),x,sin(x))
ylim(-1.5,1.5)
手动,最佳值为x0 = arcsin(1/2) # 0.523598
,但curve_fit并未估算任何值("优化警告:无法估计参数的协方差" )。我怀疑模型的刚度。 docs通知:
该算法通过leastsq使用Levenberg-Marquardt算法。其他关键字参数将直接传递给该算法。
所以我的问题是:在这种情况下,是否有关键字参数可以帮助curve_fit
估计参数?或另一种方法?
感谢您的任何建议。
答案 0 :(得分:1)
问题是curve_fit
试图最小化的目标函数不是连续的。 x0
控制inverter
函数中不连续点的位置。当不连续性穿过x
中的一个网格点时,目标函数会跳跃。在这些点之间,目标函数是不变的。 curve_fit
(实际上,leastsq
,curve_fit
使用的函数)并非旨在处理此类函数。
以下函数sse
(实际上)curve_fit
尝试最小化的函数,x
与示例中定义的x
相同,y = sin(x)
1}}:
def sse(x0, x, y):
f = inverter(x, x0)
diff = y - f
s = (diff**2).sum()
return s
如果使用代码(例如
)在精细网格上绘制此函数xx = np.linspace(0, 1, 10000)
yy = [sse(x0, x, y) for x0 in xx]
plot(xx, yy)
并放大,你会看到
要使用scipy
找到最佳值,您可以使用fmin
平滑的目标函数。例如,这里是连续目标函数,仅使用区间[0,pi / 2](quad
是scipy.integrate.quad
):
def func(x0):
s0, e0 = quad(lambda x: np.sin(x)**2, 0, x0)
s1, e0 = quad(lambda x: (1 - np.sin(x))**2, x0, 0.5*np.pi)
return s0 + s1
scipy.optimize.fmin
可用于查找该函数的最小值,如ipython会话中的此片段所示:
In [202]: fmin(func, 0.3, xtol=1e-8)
Optimization terminated successfully.
Current function value: 0.100545
Iterations: 28
Function evaluations: 56
Out[202]: array([ 0.52359878])
In [203]: np.arcsin(0.5)
Out[203]: 0.52359877559829882