通常不带常数项的指数函数()可以通过两边取对数转化成线性函数,然后再通过最小二乘法拟合求解,但是带常数的指数函数是非线性的,所以该方法就失效了。所以只能用如下方法,以下方法是在一个国外的一个论坛上找到的,先求导,再进行线性回归。
以下是python实现的代码
from cmath import exp
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize as op
# 需要拟合的数据组
x = np.array([0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12])
y = np.array([302.37, 276.29, 257.62, 242.03, 231.04, 215.03, 203.59, 195.18, 188.67, 178.68, 174.98, 169.79])
def regress_exponential_with_offset(x, y):
# sort values
ind = np.argsort(x)
x = x[ind]
y = y[ind]
# decaying exponentials need special treatment
# since we can't take the log of negative numbers.
neg = -1 if y[0] > y[-1] else 1
dx = np.diff(x)
dy = np.diff(y)
dy_dx = dy / dx
# filter any remaining negative numbers.
v = x[:-1]
u = neg * dy_dx
ind = np.where(u > 0)[0]
v = v[ind]
u = u[ind]
# perform regression
u = np.log(u)
s, t = np.polyfit(v, u, 1)
a = s
b = neg * np.exp(t) / a
yy = np.exp(a * x) * b
c = np.median(y - yy)
return a, b, c
# 得到返回的A,B值
t = regress_exponential_with_offset(x,y)
a = t[0]
b = t[1]
c = t[2]
print(a)
# 数据点与原先的进行画图比较
plt.scatter(x, y, marker='o',label='real')
x = np.arange(0, 0.15, 0.01)
y = b*np.exp(a*x) + c
plt.plot(x, y,color='red',label='curve_fit')
plt.legend()
plt.show()
拟合后的效果,如下图