【问题标题】:scipy.optimize.curvefit fails when using boundsscipy.optimize.curvefit 使用边界时失败
【发布时间】:2017-09-19 07:53:22
【问题描述】:

我正在尝试使用scipy.optimize.curvefit 将一组数据与一个函数(参见下面的示例)相匹配, 但是当我使用边界(documentation)时,拟合失败了,我只是得到 初始猜测参数作为输出。 一旦我将-np.inf 广告np.inf 替换为第二个参数的界限 (函数中的dt),适合的作品。 我做错了什么?

import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as opt

#Generate data
crc=np.array([-1.4e-14, 7.3e-14, 1.9e-13, 3.9e-13, 6.e-13, 8.0e-13, 9.2e-13, 9.9e-13, 
              1.e-12, 1.e-12, 1.e-12, 1.0e-12, 1.1e-12, 1.1e-12, 1.1e-12, 1.0e-12, 1.1e-12])
time=np.array([0., 368., 648., 960., 1520.,1864., 2248., 2655., 3031., 
                3384., 3688., 4048., 4680., 5343., 6055.,  6928.,  8120.])

#Define the function for the fit
def testcurve(x, Dp, dt):
    k = -Dp*(x+dt)*2e11
    curve = 1e-12 * (1+2*(-np.exp(k) + np.exp(4*k) - np.exp(9*k) + np.exp(16*k)))
    curve[0]= 0
    return curve

#Set fit bounds 
dtmax=time[2]
param_bounds = ((-np.inf, -dtmax),(np.inf, dtmax))

#Perform fit
(par, par_cov) = opt.curve_fit(testcurve, time, crc, p0 = (5e-15, 0), bounds = param_bounds)

#Print and plot output
print(par)       
plt.plot(time, crc, 'o')
plt.plot(time, testcurve(time, par[0], par[1]), 'r-')
plt.show()

【问题讨论】:

  • 没有inf时你的界限是什么?
  • 他们就是例子中的那些,+/-time[2],即-648.648. 但是我也试过手动输入不同的值,还是不行。跨度>
  • 我也有同样的问题,没有界限,我所有的拟合都失败了(使用curve_fit、least_squares,甚至最小化和直接定义的损失函数),但是有界限,它们都失败了。跨度>

标签: python numpy scipy


【解决方案1】:

我今天在不同的拟合问题中遇到了相同的行为。在网上搜索了一下,发现这个链接很有帮助:Why does scipy.optimize.curve_fit not fit to the data?

简短的回答是:在数值拟合中使用极小(或大)的数字并不可靠,缩放它们会导致更好的拟合。


在您的情况下,crcDp 都是可以放大的极小数字。您可以使用比例因子,并且在一定范围内,拟合看起来非常健壮。完整示例:

import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize as opt

#Generate data
crc=np.array([-1.4e-14, 7.3e-14, 1.9e-13, 3.9e-13, 6.e-13, 8.0e-13, 9.2e-13, 9.9e-13, 
              1.e-12, 1.e-12, 1.e-12, 1.0e-12, 1.1e-12, 1.1e-12, 1.1e-12, 1.0e-12, 1.1e-12])
time=np.array([0., 368., 648., 960., 1520.,1864., 2248., 2655., 3031., 
                3384., 3688., 4048., 4680., 5343., 6055.,  6928.,  8120.])

# add scale factors to the data as well as the fitting parameter
scale_factor_1 = 1e12 # 1./np.mean(crc) also works if you don't want to set the scale factor manually
scale_factor_2 = 1./2e11

#Define the function for the fit
def testcurve(x, Dp, dt):
    k = -Dp*(x+dt)*2e11 * scale_factor_2
    curve = 1e-12 * (1+2*(-np.exp(k) + np.exp(4*k) - np.exp(9*k) + np.exp(16*k))) * scale_factor_1
    curve[0]= 0
    return curve

#Set fit bounds 
dtmax=time[2]
param_bounds = ((-np.inf, -dtmax),(np.inf, dtmax))

#Perform fit
(par, par_cov) = opt.curve_fit(testcurve, time, crc*scale_factor_1, p0 = (5e-15/scale_factor_2, 0), bounds = param_bounds)

#Print and plot output
print(par[0]*scale_factor_2, par[1])

plt.plot(time, crc*scale_factor_1, 'o')
plt.plot(time, testcurve(time, par[0], par[1]), 'r-')
plt.show()

拟合结果:[6.273102923176595e-15, -21.12202697564494],它给出了一个合理的拟合,并且非常接近没有任何界限的结果:[6.27312512e-15, -2.11307470e+01]

【讨论】:

  • 但这不应该与是否有界限无关吗?就我而言,我和海报有同样的问题;没有界限,我得到了预期的正常拟合,有界限它失败了。你知道是什么让这些“小数问题”突然出现吗?
  • 同样在您的解决方案中,funcscale_factor_22e11 抵消,与 scale_factor_1 相同。这似乎不对?那里应该发生什么?
猜你喜欢
  • 2012-09-24
  • 2017-09-17
  • 2011-02-15
  • 2014-04-05
  • 2019-11-18
  • 2012-04-27
  • 1970-01-01
  • 2020-06-05
相关资源
最近更新 更多