01_线性回归

线性回归简单介绍

  • 求解线性方程的过程叫做线性回归

  • 线性回归方程:

    • f ( x ) = w x + b f(x)=wx+b f(x)=wx+b

      • 一个未知数,一个系数,一个截距(偏差、坐标的原点)
    • f ( x , y ) = w 1 x + w 2 y + b f(x,y)=w_1x+w_2y+b f(x,y)=w1x+w2y+b

      • 两个未知数,两个系数,两个截距(偏差、坐标的原点)
    • f ( X ) = ( ∑ i = 1 N w i X i ) − b f(X)=(\sum_{i=1}^Nw_iX_i)-b f(X)=(i=1NwiXi)b

      • N N N个未知数, N N N个系数, N N N个截距(偏差、坐标的原点)

最小二乘法简单介绍

  • 最小二乘法公式: min ⁡ w ∣ ∣ X w − y ∣ ∣ 2 2 \min\limits_w||Xw - y||_2^2 wminXwy22
    • X , w , y X,w,y X,w,y都是矩阵
    • 4个竖线表示这是一个矩阵
    • 右上角的2表示平方
    • 右下角的2表示向量二范数
      • 向量2范数表示每个元素的平方和在开平方根

        • ∣ ∣ X ∣ ∣ 2 = ∑ i = 1 n x i 2 ||X||_2=\sqrt {\sum_{i=1}^{n}x_i^2} X2=i=1nxi2
      • 向量二范数使用矩阵进行运算

        • ∣ ∣ X ∣ ∣ 2 = X T X ||X||_2=X^TX X2=XTX

线性回归求解方式:正规方程

正规方程简单介绍

  • 正规方程公式: w = ( X T X ) − 1 X T y w = (X^TX)^{-1}X^Ty w=(XTX)1XTy
  • 正规方程是由最小二乘法推导而来
  • 正规方程就是矩阵运算的求解方式

正规方程推导过程

  • 正规方程: w = ( X T X ) − 1 X T y w = (X^TX)^{-1}X^Ty w=(XTX)1XTy
  • 最小二乘法: m i n w ∣ ∣ X w − y ∣ ∣ 2 2 min_w||Xw-y||_2^2 minwXwy22
  • f ( x ) = ∣ ∣ X w − y ∣ ∣ 2 2 f(x)=||Xw-y||_2^2 f(x)=Xwy22
    • f ( w ) = ( X w − y ) T ( X w − y ) f(w)=(Xw-y)^T(Xw-y) f(w)=(Xwy)T(Xwy), 向量二范数展开,由 ∣ ∣ X ∣ ∣ 2 = X T X ||X||_2=X^TX X2=XTX推导在这里插入代码片
    • f ( w ) = ( w T X T − y T ) ( X w − y ) f(w)=(w^TX^T-y^T)(Xw-y) f(w)=(wTXTyT)(Xwy), ( A B ) T = B T A T (AB)^T=B^TA^T (AB)T=BTAT推导
    • f ( w ) = w T X T X w − w T X T y − y T X w + y T y f(w)=w^TX^TXw-w^TX^Ty-y^TXw+y^Ty f(w)=wTXTXwwTXTyyTXw+yTy
    • f ( w ) = w T X T X w − y T X w − y T X w + y T y f(w)=w^TX^TXw-y^TXw-y^TXw+y^Ty f(w)=wTXTXwyTXwyTXw+yTy矩阵乘法形式的变换
    • f ( w ) = w T X T X w − 2 y T X w + y T y f(w)=w^TX^TXw-2y^TXw+y^Ty f(w)=wTXTXw2yTXw+yTy
    • f ( w ) f(w) f(w)进行求导:
      • f ′ ( w ) = 2 X T X w − 2 X T y f'(w)=2X^TXw-2X^Ty f(w)=2XTXw2XTy
        • 1) y T y y^Ty yTy是一个常数项,直接约掉
        • 2) 2 y T X w 2y^TXw 2yTXw可以根据公式 d A X d X = A T \frac{dAX}{dX} = A^T dXdAX=AT进行求导
          • d ( 2 y T X ) w w = ( 2 y T X ) T = 2 X T y \frac{d(2y^TX)w}{w}=(2y^TX)^T=2X^Ty wd(2yTX)w=(2yTX)T=2XTy
        • 3) w T X T X w w^TX^TXw wTXTXw这个比较复杂, w T w^T wT w w w都是未知数,
          • 先根据 d A X d X = A T \frac{dAX}{dX} = A^T dXdAX=AT w w w的 导数
            • d ( w T X T X ) w w = ( w T X T X ) T = X T X w \frac{d(w^TX^TX)w}{w}=(w^TX^TX)^T=X^TXw wd(wTXTX)w=(wTXTX)T=XTXw
          • 再根据 d X T A d X = A \frac{dX^TA}{dX} = A dXdXTA=A w T w^T wT的导数
            • d w T ( X T X w ) w = X T X w \frac{dw^T(X^TXw)}{w}=X^TXw wdwT(XTXw)=XTXw
      • f ′ ( x ) = 0 f'(x)=0 f(x)=0
      • 2 X T X w − 2 X T y = 0 2X^TXw-2X^Ty=0 2XTXw2XTy=0
      • X T X w = X T y X^TXw=X^Ty XTXw=XTy
      • ( X T X ) − 1 ( X T X ) w = ( X T X ) − 1 X T y (X^TX)^{-1}(X^TX)w=(X^TX)^{-1}X^Ty (XTX)1(XTX)w=(XTX)1XTy
        • 矩阵没有除法,我们要将 X T X X^TX XTX挪到右边就需要使用逆矩阵
        • ( X T X ) − 1 ( X T X ) (X^TX)^{-1}(X^TX) (XTX)1(XTX)得到一个单位矩阵(逆矩阵和自己相乘)
      • 即: I w = ( X T X ) − 1 X T y I_w=(X^TX)^{-1}X^Ty Iw=(XTX)1XTy

线性回归的使用

1.波士顿房价预测

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn import datasets

boston = datasets.load_boston()
boston

# 影响房价的特征,属性
data = boston['data']
# 目标值
target = boston['target']

# 506:样本,13:特征(属性)
data.shape

# 506:目标值
target.shape

index = np.arange(0, 506)
np.random.shuffle(index)
train = index[:406] # 索引,训练数据
test = index[406:] # 测试数据

# 根据索引取出测试数据和目标值
X_train = data[train]
y_train = target[train]

# 根据索引取出预测数据和目标值
X_test = data[test]
y_test = target[test]

model = LinearRegression()
# 训练数据
model.fit(X_train, y_train)
y_pred = model.predict(X_test).round(2)
# 预测价格
y_pred
使用正规方程进行计算
# 我们在最后一列添加数字1作为正规方程的截距
X = np.concatenate([X_train, np.ones(shape=(406, 1))], axis=1)
X.shape

# 使用正规方程的公式进行计算,
# 会返回正规方程的截距和斜率
np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y_train)

# 我们打印模型计算出的斜率和截距就会发现他们是一致的,
model.coef_
model.intercept_

在这里插入图片描述

  • 我们通过正规方程公式求得的斜率和截距与我们使用模型得到的斜率和截距是一致的。由此我们可以得出结论:线性回归是基于正规方程的,它内部封装的就是正规方程

2.天猫双十一销量预测


线性回归求解方式:梯度下降

梯度下降简单介绍

  • 梯度下降算法比正规方程使用的更加广泛,基本生什么问题都可以解决
  • 梯度下降
    • 梯度:梯度就是导数,导数就是函数的变化率
    • 下降:涉及到优化问题,最小二乘法
    • 梯度下降:梯度方向下降,速度最快的

梯度下降使用

import numpy as np
# 原函数
f = lambda w : (w - 3.5)**2 -4.5*w + 10
# 导函数
d = lambda w :2*(w - 3.5) - 4.5 # 梯度 == 导数
# 梯度下降的步幅,比例,(学习率,幅度)
step = 0.3
# 我们给定一个初始值,方法会进行求解
# w = np.random.randint(0,12,size = 1)[0]
w = 50000
# 避免第一次就直接停止,大于万分之一即可,但也不可太大,太大容易步幅爆炸
last_w = w + 0.0002 
# 精确率,自己定义
precision = 1e-4
while True:
	# 退出条件,如果差异很小(万分之一),退出循环
    if np.abs(w - last_w) < precision:
        break     
	# 更新
    last_w = w
    # 梯度下降,每下降一步,每走一步,目标值,都会更新。
    w -= step*d(w)

封装梯度下降

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# 构造数据
X = np.linspace(-2,12,40).reshape(-1,1)
w = np.random.randint(1,9,size = 1)
b = np.random.randint(-5,5,size = 1)
# 增加了噪声
y = w*X + b + np.random.randn(40,1)*2
plt.scatter(X,y)

# 使用线性回归计算斜率和截距
linear = LinearRegression()
linear.fit(X,y)
# 测试数据,算法是否准确,线性回归,拟合出一个线性方程,绘制一下
X_test = np.linspace(-2,12,256).reshape(-1,1)
y_ = linear.predict(X_test)
print('真实斜率和截距是:',w,b)
print('算法计算的斜率和截距是:',linear.coef_,linear.intercept_)
plt.plot(X_test,y_,color = 'green')
plt.scatter(X,y,c = 'red')

# 封装梯度下降
class LinearModel(object):
	'''没有使用矩阵,实数'''
    def __init__(self):
    	'''初始化,随机给定斜率和截距'''
        self.w = np.random.randn(1)[0]
        self.b = np.random.randn(1)[0]
        
    def model(self,x):
    	'''模型:一元一次方程'''
        return self.w*x + self.b
    
    def loss(self,x,y):
    	'''损失函数:最小二乘法'''
    	# 损失函数越小越好
        cost = (self.model(x) - y)**2 
        # 斜率w的偏导
        d_w = 2*(self.model(x) - y)*x 
        # 截距b的偏导
        d_b = 2*(self.model(x) - y)*1 
        return cost,d_w,d_b
    
    def gradient_descent(self,step,d_w,d_b):
    	'''梯度下降'''
    	# 根据梯度,更新斜率
        self.w -= step*d_w 
        # 根据梯度,更细截距
        self.b -= step*d_b 
        
    def fit(self,X,y):
    	'''训练模型,将数据交给模型,寻找规律'''
    	# 精确度
        precision = 1e-4 
        last_w = self.w + 0.01
        last_b = self.b + 0.01
        while True:
            if (np.abs(self.w - last_w) < precision) & (np.abs(self.b - last_b) < precision):
                break
			# 更新斜率和截距
            last_w = self.w # 更新之前,先保留,记录
            last_b = self.b
            cost_ = 0
            dw_ = 0
            db_ = 0
            for i in range(40):#计算40个,返回40个偏导数,求平均值
                cost,dw,db = self.loss(X[i,0],y[i,0])
                cost_ += cost/40
                dw_ += dw/40
                db_ += db/40
            self.gradient_descent(0.02,dw_,db_)
            
    def predict(self,X):
    	'''使用模型'''
        return self.model(X)

model = LinearModel()
model.fit(X,y)
y_ = model.predict(X_test)

plt.plot(X_test,y_,color = 'green')
plt.scatter(X,y,color = 'red')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值