【机器学习】线性回归理论和实践

线性回归代码详解

1. 理论:

模型:线性模型;策略:均方误差最小化;算法:梯度下降算法

定义:给定数据集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , ⋯   , ( x n , y n ) } D=\{(\bm{x}_1,y_1),(\bm{x}_2, y_2),\cdots,(\bm{x}_n,y_n)\} D={(x1,y1),(x2,y2),,(xn,yn)},其中 x i = ( x i 1 ; x i 2 ; ⋯   ; x i d ) \bm{x}_i=(x_{i1};x_{i2};\cdots;x_{id}) xi=(xi1;xi2;;xid) d d d 是特征维度, y ∈ R y\in{\mathbb{R}} yR. 线性回归就是寻找函数 f ( x i ) = y i f(\bm{x}_i) = y_i f(xi)=yi,即使得预测值等于输出值. 对于某一个样本 x i \bm{x}_i xi的模型输出表示.

模型
f ( x i ) = b + ∑ i d w i x i (1) f(\bm{x}_i)=b+\sum_{i}^dw_i\bm{x}_i\tag{1} f(xi)=b+idwixi(1)

策略
f ∗ = arg ⁡ min ⁡ f L ( f ) (2) f^*=\arg\min_{f}L(f)\tag{2} f=argfminL(f)(2)

w ∗ , b ∗ = arg ⁡ min ⁡ w , b L ( w , b ) = arg ⁡ min ⁡ w , b ∑ i = 1 n ( y i − ( b + w x i ) ) 2 (3) \bm{w}^*, b^*=\arg\min _{\bm{w},b}L(\bm{w},b)=\arg\min_{\bm{w},b}\sum_{i=1}^n\big(y_i-(b+\bm{w}\bm{x}_i)\big)^2\tag{3} w,b=argw,bminL(w,b)=argw,bmini=1n(yi(b+wxi))2(3)

2. 代码实现

2.1 梯度下降算法求解

算法(Gradient Descent)—前提L是可微分的

流程:参数 w \mathbf{w} w,学习率为 η \eta η

  1. 随机初始化 w 0 \mathbf{w}^0 w0;
  2. 计算梯度 d L d w ∣ w = w 0 \frac{dL}{d\mathbf{w}}|_{\mathbf{w}=\mathbf{w}^0} dwdLw=w0;
  3. 更新梯度 w 1 ← w 0 − η d L d w ∣ w = w 1 \mathbf{w}^1\leftarrow \mathbf{w}^0-\eta\frac{dL}{d\mathbf{w}}|_{\mathbf{w}=\mathbf{w}^1} w1w0ηdwdLw=w1;
  4. 重复步骤2~3更新参数

每个参数都进行GD寻找 local optimal,对于 Linear Regression 可以得到最优解,因为 L 是 convex.

求解:

∂ L ∂ w = 1 N ∑ i = 1 n 2 ( y i − ( b + w ⋅ x i ) ) ( − x i ) (4) \frac{\partial{L}}{\partial{w}}=\frac{1}{N}\sum_{i=1}^{n}2(y_i-(b+w\cdot{x_i}))(-x_i) \tag{4} wL=N1i=1n2(yi(b+wxi))(xi)(4)

∂ L ∂ b = 1 N ∑ i = 1 n 2 ( y i − ( b + w ⋅ x i ) ) ( − 1 ) (5) \frac{\partial{L}}{\partial{b}}=\frac{1}{N}\sum_{i=1}^{n}2\big(y_i-(b+w\cdot{x_i})\big)(-1)\tag{5} bL=N1i=1n2(yi(b+wxi))(1)(5)

选择模型的时候,可以选择其他模型,比如引入 x x x 高次项,即选择更加复杂的模型,可能会造成过拟合,因为模型比较复杂,训练集强行拟合使得测试集效果并不好.

多个线性组合:引入 δ \delta δ,针对不同类型设置不同的线性模型。

正则化: L = ∑ n ( y i − ( b + ∑ w i x i ) ) 2 + λ ∑ ( w i ) 2 L=\sum_n\big(y_i-(b+\sum{w_ix_i})\big)^2+\lambda\sum(w_i)^2 L=n(yi(b+wixi))2+λ(wi)2,加上正则项使得函数更加平滑,不考虑bias,bias对bias平滑程度没有影响

import numpy as np

def stepGradient(bias, weight, data, learning_rate, iterations):
    """
    Args:
        b_current: (1, 1)
        w_current: (1, d)
        data: (n, d)
        learning_rate: R
    """
    # 梯度清零
    w_grad = np.zeros(data.shape[1]-1)          # (m, 1)
    b_grad = 0.0
    # 得到样本数据
    bias = np.mat(bias)                         # (1, 1)
    weight = np.mat(weight)                     # (1, m)
    x = np.mat(data[:, 0:-1])                   # (n, m)
    y = np.mat(data[:, -1].reshape([-1, 1]))    # (n, 1)
    # 样本数
    N = float(len(data))

    for j in range(iterations):
        f_x = x * weight.T + bias     # [n, 1]
        
        loss = (y - f_x).T * (y - f_x) / N
        w_grad = - (2/N) * ((y - f_x).T * x)
        b_grad = - (2/N) * ((y - f_x).T * np.ones(shape=[x.shape[0],1]))
        # for i in range(len(data)):
        #     # 计算梯度之和
        #     w_grad = w_grad - (2.0/N) * (y[i]- bias - weight * x[i].T) * x[i]
        #     b_grad = b_grad - (2.0/N) * (y[i]- bias - weight * x[i].T)

        # 更新梯度
        weight = weight - learning_rate * w_grad
        bias = bias - learning_rate * b_grad
        # if j % 50 == 0:
            # print(loss)

    return bias, weight

# 数据准备
x_train = np.mat(np.random.normal(0,10,[5,3]))
Weights=np.mat(np.array([[3,4,6]]))
y_train = np.dot(x_train, Weights.T)+5
data = np.concatenate((x_train, y_train), axis=1)              # data: [n, m] 

# 参数
b = np.mat(0.0)                                                 # (1, 1)
w = np.mat(np.zeros(data.shape[1]-1))                           # (1, m)        # 使用行向量
lr = 0.001
iterations = 10000

b, w = stepGradient(b, w, data, lr, iterations)                 
pred = b + x_train * w.T                                       # 预测结果

print(w)
print(y_train)
print(pred)

线性回归需清楚推导的损失对参数的偏导数,得到梯度后进行参数的更新,注意矩阵乘法中的细节,w的形状是什么,b的形状是什么,在整个算法中,一行为一个样本,一列为一个特征随机变量。清楚了这些后便可以得到使用梯度下降算法进行求解

2.2 最小二乘法求解

参考西瓜书,数据集D: n x (m+1)矩阵 X \bf{X} X,输入输出对于单个样本都是列向量格式,优化函数是:

w ^ ∗ = arg min ⁡ w ^ ( y − X w ^ ) T ( y − X w ^ ) (1) \hat{\bm{w}}^*=\argmin_{\hat{w}}(\bm{y}-\bf{X}\hat{\bm{w}})^{\rm{T}}(\bm{y}-\bf{X}\hat{\bm{w}}) \tag{1} w^=w^argmin(yXw^)T(yXw^)(1)

注意这里数据矩阵,n为样本数,m为样本特征维度,与西瓜书表达有所区别,为了方便学习,都将一行作为一个样本,一列作为一个特征维度。

E w ^ = ( y − X w ^ ) T ( y − X w ^ ) E_{\hat{\bm{w}}}=(\bm{y}-\bf{X}\hat{\bm{w}})^{\rm{T}}(\bm{y}-\bf{X}\hat{\bm{w}}) Ew^=(yXw^)T(yXw^),对 w ^ \hat{\bm{w}} w^ 求导得到

∂ E w ^ ∂ w ^ = 2 X T ( X w ^ − y ) (2) \frac{\partial E_{\hat{\bm{w}}}}{\partial{\hat{\bm{w}}}} = 2 \bf{X}^{\rm{T}}(\bf{X}\hat{\bm{w}}-\bm{y}) \tag{2} w^Ew^=2XT(Xw^y)(2)

X T X \bf{X}^{\rm{T}}\bf{X} XTX 为满秩矩阵或正定矩阵时,令上式为零可得

w ∗ ^ = ( X T X ) − 1 X T y (3) \hat{\bm{w}^*}=(\bf{X}^{\rm{T}}X)^{-1}X^T\bm{y}\tag{3} w^=(XTX)1XTy(3)

最后线性回归矩阵为

f ( x i ^ ) = x ^ i T ( X T X ) − 1 X T y (4) f(\hat{\bm{x}_i})=\hat{\bm{x}}_i^{\rm{T}}(\bf{X}^{\rm{T}}\bf{X})^{-1}X^{\rm{}T}\bm{y}\tag{4} f(xi^)=x^iT(XTX)1XTy(4)

import numpy as np

# 准备数据
x_train = np.random.normal(0,10,[5,3])               # [n, m]
# print(x_train.shape)
Weights = np.array([[3,4,6]])                        # [1, m]
y_train = np.dot(x_train, Weights.T).squeeze()+5     # [1, n]

b = np.ones((x_train.shape[0], 1))                   # [n, 1]
X = np.concatenate([x_train, b], axis=1)             # [n, m]

# 检查矩阵是否满秩
rank = np.linalg.matrix_rank(X)
print(rank)

# 直接求解闭式解得到参数结果
w_ = (np.mat(X).T*np.mat(X)).I*(np.mat(X).T)*(np.mat(y_train).T)

# 预测输出
pred = X*w_
print(w_)
print(y_train)
print(pred)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值