Python 曲线拟合以指数形式失败,但zunzun做对了

Python 曲线拟合以指数形式失败,但zunzun做对了,python,scipy,curve-fitting,Python,Scipy,Curve Fitting,我正试图计算某个x,y数据的两种指数形式的最佳拟合(数据文件可从下载) 代码如下: from scipy.optimize import curve_fit import numpy as np # Get x,y data data = np.loadtxt('data.txt', unpack=True) xdata, ydata = data[0], data[1] # Define first exponential function def func(x, a, b, c):

我正试图计算某个
x,y
数据的两种指数形式的最佳拟合(数据文件可从下载)

代码如下:

from scipy.optimize import curve_fit
import numpy as np

# Get x,y data
data = np.loadtxt('data.txt', unpack=True)
xdata, ydata = data[0], data[1]

# Define first exponential function
def func(x, a, b, c):
    return a * np.exp(b * x) + c

# Get parameters estimate
popt, pcov = curve_fit(func, xdata, ydata)

print popt

# Define second exponential function (one more parameter)
def func2(x, a, b, c, d):
    return a * np.exp(b * x + c) + d

# Get parameters estimate
popt2, pcov2 = curve_fit(func2, xdata, ydata)

print popt2
第一个指数给出了与zunzun.com()完全相同的
popt

[  7.67760545e-15   1.52175476e+00   2.15705939e-02]
但是第二个给出的值对于
popt2
,显然是错误的:

[ -1.26136676e+02  -8.13233297e-01  -6.66772692e+01   3.63133641e-02]
这是同一第二个函数的zunzun.com值():

a = 6.2426224704624871E-15
b = 1.5217697532005228E+00
c = 2.0660424037614489E-01
d = 2.1570805929514186E-02
我尝试将列表数组设置为此处推荐的数组,但没有任何帮助。我做错了什么


加1 我猜这个问题与我输入函数时缺少初始值有关(如这里所解释的:)

如果我像这样将第一个指数的估计值输入第二个指数(使新参数
d
最初为零):

我得到的结果非常合理,但与zunzun.com相比仍然是错误的:

[  1.22560853e-14   1.52176160e+00  -4.67859961e-01   2.15706930e-02]

现在问题变成了:我怎样才能自动为第二个函数提供更合理的参数?

请注意,在zunzun的估算和您的第一个模型中,
a=0
。所以他们只是在估计一个常数。因此,在第一种情况下,
b
,在第二种情况下,
b
c
是不相关的,也不确定

Zunzun还使用差异进化作为全局解算器,这是我最后一次研究它。Scipy现在有basinhopping作为全局优化器,它看起来相当不错,在可能出现局部极小值的情况下值得一试

我的“便宜”方法,因为在您的示例中参数的范围不大:尝试随机起始值

np.random.seed(1)
err_last = 20
best = None

for i in range(10):
    start = np.random.uniform(-10, 10, size=4)
    # Get parameters estimate
    try:
        popt2, pcov2 = curve_fit(func2, xdata, ydata, p0=start)
    except RuntimeError:
        continue
    err = ((ydata - func2(xdata, *popt2))**2).sum()
    if err < err_last:
        err_last = err
        print err
        best = popt2


za = 6.2426224704624871E-15
zb = 1.5217697532005228E+00
zc = 2.0660424037614489E-01
zd = 2.1570805929514186E-02

zz = np.array([za,zb,zc,zd])
print 'zz', zz
print 'cf', best

print 'zz', ((ydata - func2(xdata, *zz))**2).sum()
print 'cf', err_last
对于
b
c
,参数与尊尊尊不同,但剩余平方和相同

添加

a*np.exp(b*x+c)+d=np.exp(b*x+(c+np.log(a))+d

a*np.exp(b*x+c)+d=(a*np.exp(c))*np.exp(b*x)+d


第二个函数与第一个函数没有什么不同<代码>a和
c
没有单独标识。因此,使用导数信息的优化器也会有问题,因为雅可比矩阵在某些方向上是奇异的,如果我看得正确的话。

请注意,在zunzun的估计和您的第一个模型中,
a=0
。所以他们只是在估计一个常数。因此,在第一种情况下,
b
,在第二种情况下,
b
c
是不相关的,也不确定

Zunzun还使用差异进化作为全局解算器,这是我最后一次研究它。Scipy现在有basinhopping作为全局优化器,它看起来相当不错,在可能出现局部极小值的情况下值得一试

我的“便宜”方法,因为在您的示例中参数的范围不大:尝试随机起始值

np.random.seed(1)
err_last = 20
best = None

for i in range(10):
    start = np.random.uniform(-10, 10, size=4)
    # Get parameters estimate
    try:
        popt2, pcov2 = curve_fit(func2, xdata, ydata, p0=start)
    except RuntimeError:
        continue
    err = ((ydata - func2(xdata, *popt2))**2).sum()
    if err < err_last:
        err_last = err
        print err
        best = popt2


za = 6.2426224704624871E-15
zb = 1.5217697532005228E+00
zc = 2.0660424037614489E-01
zd = 2.1570805929514186E-02

zz = np.array([za,zb,zc,zd])
print 'zz', zz
print 'cf', best

print 'zz', ((ydata - func2(xdata, *zz))**2).sum()
print 'cf', err_last
对于
b
c
,参数与尊尊尊不同,但剩余平方和相同

添加

a*np.exp(b*x+c)+d=np.exp(b*x+(c+np.log(a))+d

a*np.exp(b*x+c)+d=(a*np.exp(c))*np.exp(b*x)+d


第二个函数与第一个函数没有什么不同<代码>a和
c
没有单独标识。因此,使用导数信息的优化器也会有问题,因为雅可比矩阵在某些方向上是奇异的,如果我看得没错的话。

Zunzun.com使用差分进化遗传算法(DE)找到初始参数估计,然后将其传递给scipy中的Levenberg-Marquardt解算器。DE本身并不是一个全局优化器,而是一个“初始参数猜测器”

您可以在任何网站的网页底部找到针对zunzun.com fitter的BSD许可Python源代码的链接—它有许多全面的示例—因此无需立即自己编写代码。如果你有任何问题,请告诉我,我会尽力帮助你

詹姆斯·菲利普斯
zunzun@zunzun.comZunzun.com使用差分进化遗传算法(DE)找到初始参数估计值,然后将其传递给scipy中的Levenberg-Marquardt解算器。DE本身并不是一个全局优化器,而是一个“初始参数猜测器”

您可以在任何网站的网页底部找到针对zunzun.com fitter的BSD许可Python源代码的链接—它有许多全面的示例—因此无需立即自己编写代码。如果你有任何问题,请告诉我,我会尽力帮助你

詹姆斯·菲利普斯
zunzun@zunzun.com

是的,我想一些随机初始化可能是一种方法(顺便说一句,我从这里得到了它:)谢谢!是的,我想一些随机初始化可能是方法(我从这里得到的顺便说一句:)谢谢!我不知道为什么我从来没有感谢过你的评论,詹姆斯,但这里是:谢谢你!迟做总比不做强:)(不过我对你的答案投了赞成票)我不知道为什么我从来没有感谢你的评论,詹姆斯,但这就是:谢谢你!迟做总比不做强:)(不过我对你的答案投了反对票)
zz [  6.24262247e-15   1.52176975e+00   2.06604240e-01   2.15708059e-02]
cf [  1.24791299e-16   1.52176944e+00   4.11911831e+00   2.15708019e-02]
zz 9.52135153898
cf 9.52135153904