我一直在尝试使用 scipy.optimize.curve_fit 拟合一些直方图数据,但到目前为止,我还没有能够生成与我的猜测参数显着不同的拟合参数。
如果发现我的拟合中更多神秘的参数陷入局部最小值,我不会感到非常惊讶,但即使是线性系数也不会偏离我最初的猜测!
如果您以前见过类似的事情,我希望得到一些建议。最小二乘最小化例程不适用于某些类型的函数吗?
我试试这个,
import numpy as np
from matplotlib.pyplot import *
from scipy.optimize import curve_fit
def grating_hist(x,frac,xmax,x0):
# model data to be turned into a histogram
dx = x[1]-x[0]
z = np.linspace(0,1,20000,endpoint=True)
grating = np.cos(frac*np.pi*z)
norm_grating = xmax*(grating-grating[-1])/(1-grating[-1])+x0
# produce the histogram
bin_edges = np.append(x,x[-1]+x[1]-x[0])
hist,bin_edges = np.histogram(norm_grating,bins=bin_edges)
return hist
x = np.linspace(0,5,512)
p_data = [0.7,1.1,0.8]
pct = grating_hist(x,*p_data)
p_guess = [1,1,1]
p_fit,pcov = curve_fit(grating_hist,x,pct,p0=p_guess)
plot(x,pct,label='Data')
plot(x,grating_hist(x,*p_fit),label='Fit')
legend()
show()
print 'Data Parameters:', p_data
print 'Guess Parameters:', p_guess
print 'Fit Parameters:', p_fit
print 'Covariance:',pcov
我看到这个:/image/GwXzJ.png (我是新来的,所以不能发布图片)
Data Parameters: [0.7, 1.1, 0.8]
Guess Parameters: [1, 1, 1]
Fit Parameters: [ 0.97600854 0.99458336 1.00366634]
Covariance: [[ 3.50047574e-06 -5.34574971e-07 2.99306123e-07]
[ -5.34574971e-07 9.78688795e-07 -6.94780671e-07]
[ 2.99306123e-07 -6.94780671e-07 7.17068753e-07]]
哇啊?我很确定这不是 xmax 和 x0 变化的局部最小值,而且距离全局最小值最佳拟合还有很长的路要走。即使有更好的猜测,拟合参数仍然不会改变。曲线函数的不同选择(例如两个正态分布的总和)确实会为相同的数据产生新的参数,所以我知道这不是数据本身。我也对 scipy.optimize.leastsq 本身尝试了同样的操作,以防万一,但没有骰子;参数还是没动。如果您对此有任何想法,我很想听听!
最佳答案
您面临的问题实际上不是由curve_fit
(或leastsq
)引起的。这是由于优化问题的目标情况所致。在您的情况下,目标是残差平方和,您试图将其最小化。现在,如果您在初始条件的附近仔细观察您的目标,例如使用下面的代码,该代码仅关注第一个参数:
p_ind = 0
eps = 1e-6
n_points = 100
frac_surroundings = np.linspace(p_guess[p_ind] - eps, p_guess[p_ind] + eps, n_points)
obj = []
temp_guess = p_guess.copy()
for p in frac_surroundings:
temp_guess[0] = p
obj.append(((grating_hist(x, *p_data) - grating_hist(x, *temp_guess))**2.0).sum())
py.plot(frac_surroundings, obj)
py.show()
你会注意到景观是分段常数(你可以很容易地检查其他参数的情况是否相同。问题是这些片段的数量级为 10^-6,而初始步骤拟合过程约为 10^-8,因此该过程很快结束,得出的结论是您无法从给定的初始条件进行改进。您可以尝试通过更改 curve_fit< 中的
,但你很快就会注意到,除了分段常数之外,景观也非常“崎岖”。换句话说,epsfcn
参数来修复它curve_fit
根本不适合解决这样的问题,对于基于梯度的方法来说,这是很困难的,因为它是高度非凸的。也许,一些随机优化方法可以做得更好。然而,这是一个不同的问题。
关于python - 为什么 scipy.optimize.curve_fit 产生的参数与猜测几乎没有什么不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17356793/