Python中使用scipy.optimize.curve_fit得到的拟合结果完全错误

3
更新:问题已解决! 现在它能够生成带有正确符号的参数,并且它们确实适合曲线。问题在于定义了func(a,b,c,x),但是curve_fit需要先读取x: func(x,a,b,c)。感谢大家的帮助!今天我和老板会有定量分析 :) 这里是一些新拟合:http://imgur.com/NHnzR2A (我仍然会得到运行时错误:
RuntimeWarning: overflow encountered in power
return a*(math.e**(b*(math.e**(c*x))))

)


有人能帮我找出这段代码的问题吗?我是scipy的新手。 我试图使用Gompertz方程模拟细菌生长,但我的代码产生了完全错误的curve_fit。您可以在this imgur album中看到我的真实数据、模型方程和此代码生成的拟合图形。 谢谢!


修复后的代码:

#!/usr/bin/python
from numpy import *
from scipy.optimize import curve_fit

values = numpy.asarray(values)  
y = values[:2000//5].astype(numpy.float)
y - y[0] #subtracting blank value
x = numpy.arange(len(y))*5

def Function(x,a,b,c):
  #a = upper asymptote
  #b = negative = x axis displacement
  #c = negative = growth rate
  return a*(math.e**(b*(math.e**(c*x))))

parameters, pcov = curve_fit(Function, x, y, p0=[0.1,-1300,-0.0077])

#Graph data and fit to compare
yaj = Function(  numpy.asarray(x), parameters[0], parameters[1], parameters[2] )
figure(1, figsize=(8.5,11))
subplot(211)
plot(x,y,'g-')
xlim(min(x),max(x))
ylim(min(y),max(y))
subplot(212)
plot(x,yaj,'r-')
xlim(min(x),max(x))
ylim(min(yaj),max(yaj))
savefig('tempgraph.pdf')

return parameters

1
它是一个非线性求解器,因此对初始猜测非常敏感。您是否尝试过提供更好的初始猜测?此外,如果您的模型参数差异超过几个数量级(例如 a=0.0001,b=-20,c=40000000),则需要进行归一化处理。否则,通过有限差分计算雅可比矩阵会非常不准确,并且解决方案将无法正确收敛。此外,如果您可以在某个地方发布您的数据样本(例如 pastebin 等),则可以帮助诊断问题(例如每 100 个样本一个,如果它非常大)。 - Joe Kington
我该如何做出初始猜测呢?目前,a、b和c都未定义。模型参数应该处于相同的数量级。它们的符号与预期值相反。 - user1539097
curve_fit 接受一个初始猜测作为参数 (p0)。默认情况下,它是全 1。如果 a=1, b=1, c=1 与 a、b 和 c 的实际值相差甚远,则需要提供更合理的值。 - Joe Kington
这是我的一个数据集之一:http://pastebin.com/YfJXaNB9 - user1539097
2
docs: 模型函数f(x, ...)。它必须将自变量作为第一个参数,将要拟合的参数作为单独的剩余参数。 - Martin
显示剩余2条评论
1个回答

3

导入:

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

示例数值:

values = np.array('0.400    0.400   0.397   0.395   0.396   0.394   0.392   0.390   0.395   0.393   0.392   0.392   0.390   0.388   0.390   0.388   0.385   0.383   0.388   0.387   0.387   0.387   0.385   0.386   0.387   0.379   0.379   0.378   0.375   0.376   0.374   0.373   0.372   0.368   0.373   0.370   0.371   0.370   0.370   0.370   0.367   0.368   0.368   0.365   0.365   0.366   0.364   0.361   0.361   0.356   0.355   0.357   0.354   0.353   0.350   0.351   0.353   0.355   0.350   0.354   0.352   0.351   0.348   0.348   0.347   0.345   0.346   0.343   0.348   0.346   0.344   0.343   0.342   0.341   0.346   0.346   0.345   0.343   0.348   0.345   0.346   0.342   0.344   0.344   0.340   0.341   0.345   0.345   0.343   0.339   0.343   0.344   0.343   0.346   0.344   0.344   0.345   0.347   0.344   0.344   0.338   0.340   0.343   0.340   0.342   0.336   0.334   0.336   0.337   0.338   0.338   0.343   0.342   0.342   0.336   0.334   0.336   0.330   0.325   0.324   0.323   0.319   0.323   0.322   0.318   0.314   0.314   0.319   0.315   0.316   0.313   0.315   0.314   0.314   0.315   0.313   0.308   0.312   0.311   0.310   0.312   0.311'
                  ' 0.311   0.309   0.309   0.316   0.317   0.312   0.309   0.311   0.308   0.310   0.312'.split('\t'), dtype=float)

旧的数据准备:

x=[]
y=[]
x_val = 0
for i in values: #values is a list of several thousand experimental data points
  if x_val < 100:
    x.append(float(x_val))
    y.append(float(i))
  x_val += 5
x = np.asarray(x)
y = np.asarray(y)

更轻松的数据准备:

y1 = values[:100//5]
x1 = np.arange(len(y1))*5

请确认它们是否相同:

print np.allclose(y, y1)
print np.allclose(x, x1)

使用 numpy 定义拟合函数:
def function(x, a,b,c):
    #a = upper asymptote
    #b = negative = x axis displacement
    #c = negative = growth rate
    return a*(np.exp(b*(np.exp(c*x))))

使用起始点p0进行拟合:

pars, pcov = opt.curve_fit(function, x1, y1, p0=[0.1, -10, 0.1])

绘图:

yaj = function(x1, *pars)
plt.figure(1, figsize=(8.5, 11))
plt.plot(x1, y1, 'g-', x1, yaj, 'r-')
plt.xlim(min(x1), max(x1))
plt.ylim(min(y1), max(y1))
plt.show()

嗨,感谢您的帮助!问题在于我定义了函数(a,b,c,x),而对于curve_fit工作,x必须首先出现。 - user1539097
是的,那就是我在评论中写的 :-) - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接