用 curvefit 拟合双曲函数和谐波函数
fitting hyperbolic and harmonic functions with curvefit
我在使用曲线拟合函数时遇到问题。
这里我有一个包含两个函数的代码。
第一个是双曲函数。
第二个是相同的,但有一个参数 = 1。
我的问题是,用 curvefit 拟合第一个函数的结果很好,但用第二个函数就不行了。
我有一个商业程序,可以分别为两者生成正确的解决方案。所以有可能找到第二个功能的解决方案(我上面提到的第一个的特殊情况)
有没有人可以让我知道我做错了什么?
谢谢!
这是运行的代码:
def hypRegress(ptp,pir):
xData = np.arange(len(ptp))
yData = pir
xData = np.array(xData, dtype=float)
yData = np.array(yData, dtype= float)
def funcHyp(x, qi, exp, di):
return qi*(1+exp*di*x)**(-1/exp)
def errfuncHyp(p):
return funcHyp(xData, p[0], p[1], p[2]) - yData
#print(xData.min(), xData.max())
#print(yData.min(), yData.max())
trialX = np.linspace(xData[0], xData[-1], 1000)
# Fit an hyperbolic
popt, pcov = optimize.curve_fit(funcHyp, xData, yData)
print 'popt'
#print(popt)
yHYP = funcHyp(trialX, *popt)
#optimization
# initial values
p1, success = optimize.leastsq(errfuncHyp, popt,maxfev=10000)
print p1
aaaa = funcHyp(trialX, *p1)
plt.figure()
plt.plot(xData, yData, 'r+', label='Data', marker='o')
plt.plot(trialX, yHYP, 'r-',ls='--', label="Hyp Fit")
plt.plot(trialX, aaaa, 'y', label = 'Optimized')
plt.legend()
plt.show(block=False)
return p1
def harRegress(ptp,pir):
xData = np.arange(len(ptp))
yData = pir
xData = np.array(xData, dtype=float)
yData = np.array(yData, dtype=float)
def funcHar(x, qi, di):
return qi*(1+di*x)**(-1)
def errfuncHar(p):
return funcHar(xData, p[0], p[1]) - yData
#print(xData.min(), xData.max())
#print(yData.min(), yData.max())
trialX = np.linspace(xData[0], xData[-1], 1000)
# Fit an harmonic
popt, pcov = optimize.curve_fit(funcHar, xData, yData)
print 'popt'
print(popt)
yHAR = funcHar(trialX, *popt)
#optimization
# initial values
p1, success = optimize.leastsq(errfuncHar, popt,maxfev=1000)
print p1
aaaa = funcHar(trialX, *p1)
plt.figure()
plt.plot(xData, yData, 'r+', label='Data', marker='o')
plt.plot(trialX, yHAR, 'r-',ls='--', label="Har Fit")
plt.plot(trialX, aaaa, 'y', label = 'Optimized')
plt.legend()
plt.show(block=False)
return p1
ptp = ([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14])
pir = ([150,85,90,50,45,60,60,40,40,30,28,30,38,30,26])
hypRegress(ptp,pir)
harRegress(ptp,pir)
input('pause')
这是一道经典题。 curve_fit
算法从对要优化的参数的初始猜测开始,如果未提供,则只是所有参数。
也就是说,当你调用
popt, pcov = optimize.curve_fit(funcHar, xData, yData)
拟合例程的第一次尝试将假设
funcHar(xData, qi=1, di=1)
如果您没有指定任何其他选项,拟合会很差,参数估计值的大方差证明了这一点(检查 pcov
的对角线并将其与实际值进行比较返回 popt
).
在许多情况下,提供智能猜测可以解决这种情况。从您的 HAR 模型中,我了解到 x==0
周围的值与 qi
的大小相同。因此,您可以提供 p0 = (pir[0], 1)
的初始猜测,这将导致令人满意的解决方案。你也可以用
来称呼它
popt, pcov = optimize.curve_fit(funcHar, ptp, pir, p0=(0, 1))
这导致相同的结果。所以问题只是算法找到了局部最小值。
替代方案是提供不同的 factor
,"parameter determining the initial step bound":
popt, pcov = optimize.curve_fit(funcHar, ptp, pir, p0=(1, 1), factor=1)
在这种情况下,即使使用 p0=(1,1)
的(默认)初始猜测,它也会给出相同的结果拟合。
记住:试衣是一门艺术,而不是一门科学。通常,通过分析您想要拟合的模型,您已经可以提供一个很好的初始猜测。
我不能代表商业程序中使用的算法。如果它是开源的(不太可能),你可以看看他们做了什么。
我在使用曲线拟合函数时遇到问题。 这里我有一个包含两个函数的代码。 第一个是双曲函数。 第二个是相同的,但有一个参数 = 1。 我的问题是,用 curvefit 拟合第一个函数的结果很好,但用第二个函数就不行了。 我有一个商业程序,可以分别为两者生成正确的解决方案。所以有可能找到第二个功能的解决方案(我上面提到的第一个的特殊情况) 有没有人可以让我知道我做错了什么? 谢谢!
这是运行的代码:
def hypRegress(ptp,pir):
xData = np.arange(len(ptp))
yData = pir
xData = np.array(xData, dtype=float)
yData = np.array(yData, dtype= float)
def funcHyp(x, qi, exp, di):
return qi*(1+exp*di*x)**(-1/exp)
def errfuncHyp(p):
return funcHyp(xData, p[0], p[1], p[2]) - yData
#print(xData.min(), xData.max())
#print(yData.min(), yData.max())
trialX = np.linspace(xData[0], xData[-1], 1000)
# Fit an hyperbolic
popt, pcov = optimize.curve_fit(funcHyp, xData, yData)
print 'popt'
#print(popt)
yHYP = funcHyp(trialX, *popt)
#optimization
# initial values
p1, success = optimize.leastsq(errfuncHyp, popt,maxfev=10000)
print p1
aaaa = funcHyp(trialX, *p1)
plt.figure()
plt.plot(xData, yData, 'r+', label='Data', marker='o')
plt.plot(trialX, yHYP, 'r-',ls='--', label="Hyp Fit")
plt.plot(trialX, aaaa, 'y', label = 'Optimized')
plt.legend()
plt.show(block=False)
return p1
def harRegress(ptp,pir):
xData = np.arange(len(ptp))
yData = pir
xData = np.array(xData, dtype=float)
yData = np.array(yData, dtype=float)
def funcHar(x, qi, di):
return qi*(1+di*x)**(-1)
def errfuncHar(p):
return funcHar(xData, p[0], p[1]) - yData
#print(xData.min(), xData.max())
#print(yData.min(), yData.max())
trialX = np.linspace(xData[0], xData[-1], 1000)
# Fit an harmonic
popt, pcov = optimize.curve_fit(funcHar, xData, yData)
print 'popt'
print(popt)
yHAR = funcHar(trialX, *popt)
#optimization
# initial values
p1, success = optimize.leastsq(errfuncHar, popt,maxfev=1000)
print p1
aaaa = funcHar(trialX, *p1)
plt.figure()
plt.plot(xData, yData, 'r+', label='Data', marker='o')
plt.plot(trialX, yHAR, 'r-',ls='--', label="Har Fit")
plt.plot(trialX, aaaa, 'y', label = 'Optimized')
plt.legend()
plt.show(block=False)
return p1
ptp = ([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14])
pir = ([150,85,90,50,45,60,60,40,40,30,28,30,38,30,26])
hypRegress(ptp,pir)
harRegress(ptp,pir)
input('pause')
这是一道经典题。 curve_fit
算法从对要优化的参数的初始猜测开始,如果未提供,则只是所有参数。
也就是说,当你调用
popt, pcov = optimize.curve_fit(funcHar, xData, yData)
拟合例程的第一次尝试将假设
funcHar(xData, qi=1, di=1)
如果您没有指定任何其他选项,拟合会很差,参数估计值的大方差证明了这一点(检查 pcov
的对角线并将其与实际值进行比较返回 popt
).
在许多情况下,提供智能猜测可以解决这种情况。从您的 HAR 模型中,我了解到 x==0
周围的值与 qi
的大小相同。因此,您可以提供 p0 = (pir[0], 1)
的初始猜测,这将导致令人满意的解决方案。你也可以用
popt, pcov = optimize.curve_fit(funcHar, ptp, pir, p0=(0, 1))
这导致相同的结果。所以问题只是算法找到了局部最小值。
替代方案是提供不同的 factor
,"parameter determining the initial step bound":
popt, pcov = optimize.curve_fit(funcHar, ptp, pir, p0=(1, 1), factor=1)
在这种情况下,即使使用 p0=(1,1)
的(默认)初始猜测,它也会给出相同的结果拟合。
记住:试衣是一门艺术,而不是一门科学。通常,通过分析您想要拟合的模型,您已经可以提供一个很好的初始猜测。
我不能代表商业程序中使用的算法。如果它是开源的(不太可能),你可以看看他们做了什么。