【机器学习】线性回归(最小二乘法实现)

版权声明:本文为博主原创文章,转载请注明出处!!!(●'◡'●) https://blog.csdn.net/Small_Mouse0/article/details/79755619

一、什么是线性回归

线性回归(或者叫做线性拟合)是最简单的拟合分析方法,概念很简单,先看张图:


通俗的说就是在一系列点中间画一条线,这条线能够代表所有点的特征(或者称之为,关系、发展趋势等等),,目的很明确就是对线性问题进行估计(预测),,当然线性问题也是最简单的规律。

注意:线性不一定是二维空间内的线性问题,可以是N维的


二、线性回归可以用最小二乘法来实现

        原理简单的来说就是保证所有点都能到直线最近(x不变,将x带入拟合直线求得长度L1),引用知乎中的一张插图



其中红色线长度和最小,及最小二乘法所求的目的。害羞

推到过程如下(参考原文):(可略过)

1 写出拟合方程

y=a+bxy=a+bx

2 现有样本(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(yiabxi)D=∑i=1ndi2=∑i=1n(yi−a−bxi)

5 根据一阶导数等于0,二阶大于等于0(证明略)求出未知参数
对a求一阶偏导
Da=i=1n2(yiabxi)(1) =2i=1n(yiabxi) ∂D∂a=∑i=1n2(yi−a−bxi)(−1) =−2∑i=1n(yi−a−bxi) 
=2(i=1nyii=1nabi=1nxi) =2(ny¯nanbx¯)=−2(∑i=1nyi−∑i=1na−b∑i=1nxi) =−2(ny¯−na−nbx¯)

对b求一阶偏导
Db=i=1n2(yiabxi)(xi) =2i=1n(xiyiaxibx2i) ∂D∂b=∑i=1n2(yi−a−bxi)(−xi) =−2∑i=1n(xiyi−axi−bxi2) 
=2(i=1nxiyiai=1nxibi=1nx2i) =2(i=1nxiyinax¯bi=1nx2i)=−2(∑i=1nxiyi−a∑i=1nxi−b∑i=1nxi2) =−2(∑i=1nxiyi−nax¯−b∑i=1nxi2)

令偏导等于0得
2(ny¯nanbx¯)=0−2(ny¯−na−nbx¯)=0
=>a=y¯bx¯=>a=y¯−bx¯

2(i=1nxiyinax¯bi=1nx2i)=0−2(∑i=1nxiyi−nax¯−b∑i=1nxi2)=0并将a=y¯bx¯a=y¯−bx¯带入化简得
=>i=1nxiyinx¯y¯+nbx¯2bi=1nx2i=0=>∑i=1nxiyi−nx¯y¯+nbx¯2−b∑i=1nxi2=0
=>i=1nxiyinx¯y¯=b(i=1nx2inx¯2)=>∑i=1nxiyi−nx¯y¯=b(∑i=1nxi2−nx¯2)
=>b=i=1nxiyinx¯y¯i=1nx2inx¯2=>b=∑i=1nxiyi−nx¯y¯∑i=1nxi2−nx¯2

因为i=1n(xix¯)(yiy¯)=i1n(xiyix¯yixiy¯+x¯y¯)=i=1nxiyinx¯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(xix¯)2=i1n(x2i2x¯xi+x¯2)=i=1nx2i2nx¯2+nx¯2=i=1nx2inx¯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(xix¯)(yiy¯)i=1n(xix¯)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()

完整代码码云超链接

猜你喜欢

转载自blog.csdn.net/Small_Mouse0/article/details/79755619