我不能让这个棚车适合工作......我得到“OptimizeWarning:无法估计参数的协方差 category = OptimizeWarning)“,并且输出系数不会超出起始猜测。
import numpy as np
from scipy.optimize import curve_fit
def box(x, *p):
height, center, width = p
return height*(center-width/2 < x)*(x < center+width/2)
x = np.linspace(-5,5)
y = (-2.5<x)*(x<2.5) + np.random.random(len(x))*.1
coeff, var_matrix = curve_fit(box, x, y, p0=[1,0,2])
输出系数是[1.04499699,0。,2。],而不是第三个甚至没有改变。
我怀疑这个函数形式不适合curve_fit使用的levenberg-marquardt算法,这有点烦人,因为我喜欢这个函数。在mathematica中,指定monte carlo优化将是微不足道的。
答案 0 :(得分:3)
我怀疑这种功能形式不适合curve_fit使用的levenberg-marquardt算法
你是对的。通常,基于梯度的优化不适合具有锐边的函数。通过稍微调整函数参数并观察拟合质量的变化来估计梯度。但是,如果不跨越数据点,则仅移动边缘会导致零梯度:
使用随机方法应该更好。 Scipy具有differential_evolution功能,它使用遗传算法,因此与蒙特卡罗方法有关。但是,使用它比curve_fit
更简单。您需要指定参数的成本函数和范围:
res = differential_evolution(lambda p: np.sum((box(x, *p) - y)**2), # quadratic cost function
[[0, 2], [-5, 5], [0.1, 10]]) # parameter bounds
它仍然是一个单行:)
coeff, var_matrix = curve_fit(box, x, y, p0=[1,0,2])
res = differential_evolution(lambda p: np.sum((box(x, *p) - y)**2), [[0, 2], [-5, 5], [0.1, 10]])
plt.step(x, box(x, *coeff), where='mid', label='curve_fit')
plt.step(x, box(x, *res.x), where='mid', label='diff-ev')
plt.plot(x, y, '.')
plt.legend()