一、什么是线性回归
线性回归(或者叫做线性拟合)是最简单的拟合分析方法,概念很简单,先看张图:
通俗的说就是在一系列点中间画一条线,这条线能够代表所有点的特征(或者称之为,关系、发展趋势等等),,目的很明确就是对线性问题进行估计(预测),,当然线性问题也是最简单的规律。
注意:线性不一定是二维空间内的线性问题,可以是N维的
二、线性回归可以用最小二乘法来实现
原理简单的来说就是保证所有点都能到直线最近(x不变,将x带入拟合直线求得长度L1),引用知乎中的一张插图其中红色线长度和最小,及最小二乘法所求的目的。
推到过程如下(参考原文):(可略过)
1 写出拟合方程
y=a+bxy=a+bx2 现有样本(x1,y1),(x2,y2)...(xn,yn)(x1,y1),(x2,y2)...(xn,yn)
3 设didi为样本点到拟合线的距离,即误差
di=yi−(a+bxi)di=yi−(a+bxi)
4 设DD为差方和(为什么要取平方前面已说,防止正负相互抵消)
D=∑i=1nd2i=∑i=1n(yi−a−bxi)D=∑i=1ndi2=∑i=1n(yi−a−bxi)
5 根据一阶导数等于0,二阶大于等于0(证明略)求出未知参数
对a求一阶偏导
∂D∂a=∑i=1n2(yi−a−bxi)(−1) =−2∑i=1n(yi−a−bxi) ∂D∂a=∑i=1n2(yi−a−bxi)(−1) =−2∑i=1n(yi−a−bxi)
=−2(∑i=1nyi−∑i=1na−b∑i=1nxi) =−2(ny¯−na−nbx¯)=−2(∑i=1nyi−∑i=1na−b∑i=1nxi) =−2(ny¯−na−nbx¯)
对b求一阶偏导
∂D∂b=∑i=1n2(yi−a−bxi)(−xi) =−2∑i=1n(xiyi−axi−bx2i) ∂D∂b=∑i=1n2(yi−a−bxi)(−xi) =−2∑i=1n(xiyi−axi−bxi2)
=−2(∑i=1nxiyi−a∑i=1nxi−b∑i=1nx2i) =−2(∑i=1nxiyi−nax¯−b∑i=1nx2i)=−2(∑i=1nxiyi−a∑i=1nxi−b∑i=1nxi2) =−2(∑i=1nxiyi−nax¯−b∑i=1nxi2)
令偏导等于0得
−2(ny¯−na−nbx¯)=0−2(ny¯−na−nbx¯)=0
=>a=y¯−bx¯=>a=y¯−bx¯
−2(∑i=1nxiyi−nax¯−b∑i=1nx2i)=0−2(∑i=1nxiyi−nax¯−b∑i=1nxi2)=0并将a=y¯−bx¯a=y¯−bx¯带入化简得
=>∑i=1nxiyi−nx¯y¯+nbx¯2−b∑i=1nx2i=0=>∑i=1nxiyi−nx¯y¯+nbx¯2−b∑i=1nxi2=0
=>∑i=1nxiyi−nx¯y¯=b(∑i=1nx2i−nx¯2)=>∑i=1nxiyi−nx¯y¯=b(∑i=1nxi2−nx¯2)
=>b=∑i=1nxiyi−nx¯y¯∑i=1nx2i−nx¯2=>b=∑i=1nxiyi−nx¯y¯∑i=1nxi2−nx¯2
因为∑i=1n(xi−x¯)(yi−y¯)=∑i−1n(xiyi−x¯yi−xiy¯+x¯y¯)=∑i=1nxiyi−nx¯y¯−nx¯y¯+nx¯y¯∑i=1n(xi−x¯)(yi−y¯)=∑i−1n(xiyi−x¯yi−xiy¯+x¯y¯)=∑i=1nxiyi−nx¯y¯−nx¯y¯+nx¯y¯
∑i=1n(xi−x¯)2=∑i−1n(x2i−2x¯xi+x¯2)=∑i=1nx2i−2nx¯2+nx¯2=∑i=1nx2i−nx¯2∑i=1n(xi−x¯)2=∑i−1n(xi2−2x¯xi+x¯2)=∑i=1nxi2−2nx¯2+nx¯2=∑i=1nxi2−nx¯2
所以将其带入上式得b=∑i=1n(xi−x¯)(yi−y¯)∑i=1n(xi−x¯)2
代码实现:
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt
#生成模拟数据,进行测试
X = np.array(np.arange(100) ,dtype=np.float32)
Y = np.array(np.arange(100) ,dtype=np.float32)#此时X和Y其实是相等的,后面加入随机值,尽可能真实模拟实际情况
Y +=(np.random.random_sample(100) * 20)# *20指的是,上波动10
Y -=20 #下降20,,,y = x+b --> y = x - 10
print(Y[:20])#查看前20列
#最小二乘计算
def residuals(p):
"计算以p为参数的直线和原始数据之间的误差"
k,b = p
return Y - (k*X + b)#这其实是 y=kx+b的变形,,y-kx+b = 0
r = optimize.leastsq(residuals,[1,0])#引用最小二成计算,
k,b = r[0]
print(k,b)
#图像展示
plt.figure(figsize=(6,6))
plt.plot(X,Y,'ro',label="point")
# 拟合直线
x = np.arange(0,100,0.1)
y = x*k+b
plt.plot(x,y,"b")
plt.show()