Hi I'm attempting to produce a fit for each of my three exponential decays. I am not successful with producing a satisfactory fit. This is what I get: http://i.imgur.com/Nx44wsS.jpg

Any help is greatly appreciated. My code is below.

import pylab as plb
import matplotlib.pyplot as plt
import matplotlib.axes as ax
import scipy as sp
from scipy.optimize import curve_fit
from matplotlib import rc
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
## for Palatino and other serif fonts use:
#rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)

data = plb.loadtxt('data.csv',skiprows=2)
yp = data[:,4]
yr = data[:,5]
yl = data[:,6]
x = data[:,0]

def func(x,a,b,c):
    return a*np.exp(-b*x) + c

popt, pcov = curve_fit(func, x, yl,maxfev=20000)
a = popt[0]
b = popt[1]
c = popt[2]
print a
print b
print c
print func(x,a,b,c)

xf = np.linspace(0,70,100)
yf = a*np.exp(-b*x) + c

plt.clf()
plt.plot(x,yf,'r-', label="Fitted Curve")
plt.plot(x,func(x,*popt))

plt.plot(x,yp,'bo',label='Polished')
plt.plot(x,yr,'ro',label='Rough')
plt.plot(x,yl,'go',label='Lacquered')

plt.legend()
plt.ylabel("Temperature (K)")
plt.xlabel("Time (min)")
plt.show()
有帮助吗?

解决方案

Nonlinear fits are difficult and the trick is that you have to provide a reasonable initial guess.

Here is a version of your code which does two fits, one with an approximate initial guess and one with the default initial guess:

import pylab as plb
import matplotlib.pyplot as plt
import matplotlib.axes as ax
import scipy as sp
from scipy.optimize import curve_fit
from matplotlib import rc
import numpy as np
rc('font', **{'family':'sans-serif', 'sans-serif':['Helvetica']})
rc('text', usetex=True)

# Fake data
x = np.arange(0, 70., 2.)
yl = 300 + 63*np.exp(-x/35.)

def func(x, a, b, c):
    return a*np.exp(-b*x) + c

popt, pcov = curve_fit(func, x, yl, p0=(40, 0.012, 250), maxfev=20000)
a, b, c = popt
print 'a=', a, 'b=', b, 'c=', c
print 'func=', func(x, a, b, c)

popt2, pcov2 = curve_fit(func, x, yl, p0=None, maxfev=20000)
a2, b2, c2 = popt2
print 'a2=', a2, 'b2=', b2, 'c2=', c2
print 'func=', func(x, a2, b2, c2)

xf = np.linspace(0, 70, 100)
yf = a*np.exp(-b*x) + c

plt.clf()
plt.plot(x, yf, 'r-', label="Fitted Curve")
plt.plot(x, func(x, *popt))
plt.plot(x, func(x, *popt2), 'b-', label='Fit w/o guess')

plt.plot(x, yl, 'go', label='Lacquered')

plt.legend()
plt.ylabel("Temperature (K)")
plt.xlabel("Time (min)")
plt.show()

And here are the resulting fits:

enter image description here

As you can see, the fit with a reasonable initial guess does very well (red line). If you don't provide an initial guess, scipy assumes 1 for all parameters and that works poorly (blue line).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top