我有以下数据点,我想曲线拟合:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
t = np.array([15474.6, 15475.6, 15476.6, 15477.6, 15478.6, 15479.6, 15480.6,
15481.6, 15482.6, 15483.6, 15484.6, 15485.6, 15486.6, 15487.6,
15488.6, 15489.6, 15490.6, 15491.6, 15492.6, 15493.6, 15494.6,
15495.6, 15496.6, 15497.6, 15498.6, 15499.6, 15500.6, 15501.6,
15502.6, 15503.6, 15504.6, 15505.6, 15506.6, 15507.6, 15508.6,
15509.6, 15510.6, 15511.6, 15512.6, 15513.6])
v = np.array([4.082, 4.133, 4.136, 4.138, 4.139, 4.14, 4.141, 4.142, 4.143,
4.144, 4.144, 4.145, 4.145, 4.147, 4.146, 4.147, 4.148, 4.148,
4.149, 4.149, 4.149, 4.15, 4.15, 4.15, 4.151, 4.151, 4.152,
4.152, 4.152, 4.153, 4.153, 4.153, 4.153, 4.154, 4.154, 4.154,
4.154, 4.154, 4.155, 4.155])
我想要适合数据的指数函数是:
表示上述公式的Python函数以及与数据拟合的相关曲线详述如下:
def func(t, a, b, alpha):
return a - b * np.exp(-alpha * t)
# scale vector to start at zero otherwise exponent is too large
t_scale = t - t[0]
# initial guess for curve fit coefficients
a0 = v[-1]
b0 = v[0]
alpha0 = 1/t_scale[-1]
# coefficients and curve fit for curve
popt4, pcov4 = curve_fit(func, t_scale, v, p0=(a0, b0, alpha0))
a, b, alpha = popt4
v_fit = func(t_scale, a, b, alpha)
ss_res = np.sum((v - v_fit) ** 2) # residual sum of squares
ss_tot = np.sum((v - np.mean(v)) ** 2) # total sum of squares
r2 = 1 - (ss_res / ss_tot) # R squared fit, R^2
与曲线拟合相比较的数据如下所示。还提供了参数和R平方值。
a0 = 4.1550 b0 = 4.0820 alpha0 = 0.0256
a = 4.1490 b = 0.0645 alpha = 0.9246
R² = 0.8473
是否有可能使用上述方法更好地拟合数据,还是需要使用不同形式的指数方程?
我也不确定用于初始值的内容(a0
,b0
,alpha0
)。在示例中,我从数据中选择了点,但这可能不是最好的方法。关于什么用于曲线拟合系数的初始猜测的任何建议?
答案 0 :(得分:4)
对我来说,这看起来更适合多个组件,而不是单个指数。
def func(t, a, b, c, d, e):
return a*np.exp(-t/b) + c*np.exp(-t/d) + e
# scale vector to start at zero otherwise exponent is too large
t_scale = t - t[0]
# initial guess for curve fit coefficients
guess = [1, 1, 1, 1, 0]
# coefficients and curve fit for curve
popt, pcov = curve_fit(func, t_scale, v, p0=guess)
v_fit = func(t_scale, *popt)
答案 1 :(得分:2)
我能找到的最好的单个3参数方程,R平方= 0.9952,是x偏移幂函数:
$query = "SELECT num, count(num) FROM tab group by num
order by count(num) desc";
带参数:
y = pow((a + x), b) + Offset
答案 2 :(得分:1)
如果删除第一个数据点,您将获得更好的适应性。
使用lmfit(https://lmfit.github.io/lmfit-py),它为曲线拟合提供了更高级别且更易于使用的界面,您的拟合脚本将如下所示:
import matplotlib.pyplot as plt
import numpy as np
from lmfit import Model
t = np.array([15474.6, 15475.6, 15476.6, 15477.6, 15478.6, 15479.6, 15480.6,
15481.6, 15482.6, 15483.6, 15484.6, 15485.6, 15486.6, 15487.6,
15488.6, 15489.6, 15490.6, 15491.6, 15492.6, 15493.6, 15494.6,
15495.6, 15496.6, 15497.6, 15498.6, 15499.6, 15500.6, 15501.6,
15502.6, 15503.6, 15504.6, 15505.6, 15506.6, 15507.6, 15508.6,
15509.6, 15510.6, 15511.6, 15512.6, 15513.6])
v = np.array([4.082, 4.133, 4.136, 4.138, 4.139, 4.14, 4.141, 4.142, 4.143,
4.144, 4.144, 4.145, 4.145, 4.147, 4.146, 4.147, 4.148, 4.148,
4.149, 4.149, 4.149, 4.15, 4.15, 4.15, 4.151, 4.151, 4.152,
4.152, 4.152, 4.153, 4.153, 4.153, 4.153, 4.154, 4.154, 4.154,
4.154, 4.154, 4.155, 4.155])
def func(t, a, b, alpha):
return a + b * np.exp(-alpha * t)
# remove first data point, take offset from t
tx = t[1:] - t[0]
vx = v[1:]
# turn your model function into a Model
amodel = Model(func)
# create parameters with initial values. Note that parameters
# are named from the arguments of your model function.
params = amodel.make_params(a=v[0], b=0, alpha=1.0/(t[-1]-t[0]))
# fit the data to the model with the parameters
result = amodel.fit(vx, params, t=tx)
# print the fit statistics and resulting parameters
print(result.fit_report())
# plot data and fit
plt.plot(t, v, 'o', label='data')
plt.plot(t, result.eval(result.params, t=(t-t[0])), '--', label='fit')
plt.legend()
plt.show()
这将打印出这些结果
[[Model]]
Model(func)
[[Fit Statistics]]
# fitting method = leastsq
# function evals = 44
# data points = 39
# variables = 3
chi-square = 1.1389e-05
reduced chi-square = 3.1635e-07
Akaike info crit = -580.811568
Bayesian info crit = -575.820883
[[Variables]]
a: 4.15668660 +/- 5.0662e-04 (0.01%) (init = 4.082)
b: -0.02312772 +/- 4.1930e-04 (1.81%) (init = 0)
alpha: 0.06004740 +/- 0.00360126 (6.00%) (init = 0.02564103)
[[Correlations]] (unreported correlations are < 0.100)
C(a, alpha) = -0.945
C(a, b) = -0.682
C(b, alpha) = 0.465
并显示适合的情节: