Python日记(9)——曲线拟合
每天做一个Python小练习,顺便记录一些小技巧。
曲线拟合
应用方法:
最小二乘法
原理:
函数解析式未知,通过实验观测得到的一组数据,即在某个区间[a,b]上给出
一系列点的函数值yi = f(xi)。节点上的函数值是由实验或观测得到的数据,不可避免地带有测量误差,如果要求所得的近似函数曲线精确无误地通过所有的点(xi,yi)就会使曲线保留着一切测试误差。当个别数据的误差较大时,插值效果显然是不理想的。由实验或观测提供的数据个数往往很多,如果用插值法,势必得到次数较高的插值多项式,这样是不可行的。求一条曲线,使数据点均在离此曲线的上方或下方不远处,所求的曲线称为拟合曲线,它既能反映数据的总体分布,又不至于出现局部较大的波动,更能反映被逼近函数的特性,使求得的逼近函数与已知函数从总体上来说其偏差按某种方法度量达到最小。与函数插值问题不同,曲线拟合不要求曲线通过所有己知点,而是要求得到的近似函数能反映数据的基本关系。在某种意义上,曲线拟合更有实用价值。
对于线性拟合,就是要找到一条直线,y=a+bx,使得残差Q最小,残差Q的定义为
经过推导可知
x和y两个变量之间的相关性,可用相关函数表示
其中R方称为判定系数,表示y的离散性中回归的成分的大小,越接近1说明回归的贡献越大,线性相关性的程度越高。实现过程:
1.定义模型:
线性回归的目标就是找到一组a和b是的ε(误差)最小。
y = ax + b + ε
y_hat = ax + b
ε (误差)= y - y_hat(误差)
2.方差——损失函数
损失函数用的是:0.5倍的方差
3.优化方法
a和b是一维变量,判断方向找到损失函数的最小值
所以就对Q(a, b)求对a和对b的偏导,通过对a和对b找到最小的值。
定义一个超参α=0.01
通过损失函数的变化,判断随着a或b的变化,变化量的正负值,找到损失函数的最小值。
程序步骤
1.初始值
a=0, b=0
2.计算模型
y_hat = ax + b
3.计算a和b的微分
4.更新a和b
5.判断是否为损失函数的最小值
否则重复2和3
6.极少数程序
算法步骤
1.a 和b的初始值设置为0
2.通过模型y_hat,算出y_hat
3.有了y_hat, 用优化方法算出,更新参数
4.重复2和3,直到找到损失函数的最小值
代码
模型
def model(a, b, x):
return a*x + b
损失函数
def cost_function(a, b, x, y, n):
return 0.5/n * (np.square(y-a*x-b)).sum()
优化函数
def optimize(a, b, x, y, n):
alpha = 1e-1
y_hat = model(a, b, x)
da = (n**(-1)*((y_hat-y)*x).sum()
db = (n**(-1)*(y_hay-y).sum()
a = a - alpha*da
b = b - alpha*db
return a, b
迭代
def iterate(a,b,x,y,times):
for i in range(times):
a,b = optimize(a, b, x, y)
y_hat = model(a, b, x)
cost = cost_function(a,b,x,y)
print(a, b, cost)
plt.scatter(x, y)
plt.plot(x, y_hat)
return a, b
模型评价
y_hat = model(a, b, x)
y_bar = y.mean()
SST = np.square(y - y_hat).sum()
SSR = np.square(y_hat - y_bar).sum()
SSE = np.square(y_hat - y).sum
R_square = SSR/SST
Sklearn库中的linear_model模型
在Sklearn库中有现用的模型,可以直接拿出调用。
# 调用模型
lr = LinearRegression()
# 训练模型
lr.fit(x, y)
# 计算R的平方
R_square = lr.score(x, y)
# 截距
a = lr.intercept_
# 斜率
b = lr.coef_
# 预测
y_hat = lr.predict(x)
# 判定系数
R_square = lr.score(x, y)