数值算法往往更好地工作时,没有饲料非常小(或
(大)数字。
在本例中,图表显示数据的x和y值非常小。如果
如果缩放它们,拟合效果会更好:
xData = np.load('xData.npy')*10**5yData = np.load('yData.npy')*10**5from __future__ import divisionimport osos.chdir(os.path.expanduser('~/tmp'))import numpy as npimport scipy.optimize as optimizeimport matplotlib.pyplot as pltdef func(x,a,b,c): return a*np.exp(-b*x)-cxData = np.load('xData.npy')*10**5yData = np.load('yData.npy')*10**5print(xData.min(), xData.max())print(yData.min(), yData.max())trialX = np.linspace(xData[0], xData[-1], 1000)# Fit a polynomial fitted = np.polyfit(xData, yData, 10)[::-1]y = np.zeros(len(trialX))for i in range(len(fitted)): y += fitted[i]*trialX**i# Fit an exponentialpopt, pcov = optimize.curve_fit(func, xData, yData)print(popt)yEXP = func(trialX, *popt)plt.figure()plt.plot(xData, yData, label='Data', marker='o')plt.plot(trialX, yEXP, 'r-',ls='--', label="Exp Fit")plt.plot(trialX, y, label = '10 Deg Poly')plt.legend()plt.show()Note that after rescaling
xDataand
yData, the parameters returned by
curve_fitmust also be rescaled. In this case,
a,
band
ceach must be
divided by 10**5 to obtain fitted parameters for the original data.
One objection you might have to the above is that the scaling has to be chosen
rather “carefully”. (Read: Not every reasonable choice of scale works!)
You can improve the robustness of
curve_fitby providing a reasonable
initial guess for the parameters. Usually you have some a priori knowledge
about the data which can motivate ballpark / back-of-the envelope type guesses
for reasonable parameter values.
For example, calling
curve_fitwith
guess = (-1, 0.1, 0)popt, pcov = optimize.curve_fit(func, xData, yData, guess)
helps improve the range of scales on which
curve_fitsucceeds in this case.



