Datawhale组队学习第27期:集成学习
本次学习的指导老师萌弟的教学视频
本贴为学习记录帖,有任何问题欢迎随时交流~
部分内容可能还不完整,后期随着知识积累逐步完善。
开始时间:2021年7月13日
最新更新:2021年7月15日(Task2回归问题)
一、基本建模步骤
- 明确项目任务
- 收集数据集并选取合适的特征
- 选择度量模型性能的指标
- 选择具体的模型并进行训练以优化模型
- 评估模型并调参
二、以Boston房价为例
-
Boston房价预测,显然是一个回归问题。
-
数据集已有,这里默认选定所有的特征。
-
度量模型性能的指标(n为样本量),具体可以看sklearn的官方文档
-
MSE均方误差
M S E ( y , y ^ ) = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE(y,\hat y) = \frac{1}{n}\sum\limits_{i=1}^{n}(y_i - \hat y_i)^2 MSE(y,y^)=n1i=1∑n(yi−y^i)2 -
MAE平均绝对误差
M A E ( y , y ^ ) = 1 n ∣ y i − y ^ i ∣ MAE(y, \hat y) = \frac{1}{n}|y_i - \hat y_i| MAE(y,y^)=n1∣yi−y^i∣ -
R-Square
R 2 ( y , y ^ ) = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ˉ i ) 2 R^2(y, \hat y) = 1 - \frac{\sum\limits_{i=1}^{n}(y_i - \hat y_i)^2} {\sum\limits_{i=1}^{n}(y_i - \bar y_i)^2} R2(y,y^)=1−i=1∑n(yi−yˉi)2i=1∑n(yi−y^i)2 -
解释方程得分
E x p l a t i n e d V a r i a n c e ( y , y ^ ) = 1 − V a r ( y − y ^ ) V a r ( y ) Explatined \ V ariance(y, \hat y) = 1 - \frac{Var(y-\hat y)}{Var(y)} Explatined Variance(y,y^)=1−Var(y)Var(y−y^)
-
-
选择具体的模型
- 线性回归(
linear_model
) - 多项式回归(
PolynomialFeatures
) - 广义可加模型GAM(
LinearGAM
) - 回归树(
DecisionTreeRegressor
) - 支持向量回归SVR(
SVR
)
- 线性回归(
-
评估模型并调参(这部分是后续进行)
三、线性回归模型推导
在前几个月,本人写过一篇关于线性回归的简单应用,文章主要介绍了线性回归在Python中的实现,主要应用的是
sklearn
包的内容。本次学习中,Datawhale安排的作业中要求使用numpy
库实现,因此本文主要给出线性回归模型的相关推导和基于numpy
实现。
1. 数据基础
- 数据集: D = { ( x 1 , y 1 ) , . . . , ( x N , y N ) } D=\{ (x_1, y_1),...,(x_N,y_N) \} D={ (x1,y1),...,(xN,yN)}
- 单样本向量: x i ∈ R n x_i \in R^n xi∈Rn表示 x i x_i xi有 n n n个特征,即 x i = [ x i ( j ) ] n × 1 x_i = [x^{(j)}_i]_{n \times 1} xi=[xi(j)]n×1
- 所有样本组成的数值矩阵: X = [ x i ( j ) ] n × N X = [x_i^{(j)}]_{n\times N} X=[xi(j)]n×N
- 参数: w = [ w j ] n × 1 w = [w_j]_{n \times 1} w=[wj]n×1
- 预测值: Y ^ = [ y ^ i ] N × 1 \hat Y = [\hat y_i]_{N \times 1} Y^=[y^i]N×1
- 实际值: Y = [ y i ] N × 1 Y = [y_i]_{N \times 1} Y=[yi]N×1
2. 基本模型
y ^ i = w T x i Y ^ = [ y ^ i ] N × 1 = [ w T x i ] N × 1 = X T ⋅ w \begin{aligned} \hat y_i &= w^Tx_i \\ \hat Y &= [\hat y_i]_{N \times 1} = [w^Tx_i]_{N \times 1} = X^T \cdot w \\ \end{aligned} y^iY^=wTxi=[y^i]N×1=[wTxi]N×1=XT⋅w
3. 损失函数
- 这里的损失函数其实就是均方误差 M S E MSE MSE,回归问题中比较常用。
- 首先先计算预测值与真实值之差的 L 2 L_2 L2范数,可以理解为两个向量的模长:
∣ ∣ Y ^ − Y ∣ ∣ 2 = ( X T ⋅ w − Y ) T ( X T ⋅ w − Y ) = w T X X T w − w T X Y − Y T X T w + Y T Y \begin{aligned} ||\hat Y - Y||_2 &= (X^T \cdot w - Y)^T(X^T \cdot w - Y) \\ &= w^TXX^Tw - w^TXY-Y^TX^Tw+Y^TY \end{aligned} ∣∣Y^−Y∣∣2=(XT⋅w−Y)T(XT⋅w−Y)=wTXXTw−wTXY−YTXTw+YTY - 实际上,对于我们获取的数据集一般是行代表样本数,列代表特征数,可以将上面的数值矩阵改为 X = [ x i ( j ) ] N × n X = [x_i^{(j)}]_{N \times n} X=[xi(j)]N×n。由于中间项都是常数,转置等于它本身,有 w T X T Y = Y T X w w^T X^TY =Y^TXw wTXTY=YTXw,因此上述等式改为:
∣ ∣ Y ^ − Y ∣ ∣ 2 = ( X ⋅ w − Y ) T ( X ⋅ w − Y ) = w T X T X w − 2 w T X T Y + Y T Y \begin{aligned} ||\hat Y - Y||_2 &= (X \cdot w - Y)^T(X \cdot w - Y) \\ &= w^TX^TXw - 2w^TX^TY + Y^TY \end{aligned} ∣∣Y^−Y∣∣2=(X⋅w−Y)T(X⋅w−Y)=wTXTXw−2wTXTY+YTY
4. 优化问题
- 目标函数:(这里加入 1 2 \frac{1}{2} 21是方便后面消去)
L ( w ) = 1 2 ∣ ∣ Y ^ − Y ∣ ∣ 2 = w T X T X w − 2 w T X T Y + Y T Y L(w) = \frac{1}{2} ||\hat Y - Y||_2 = w^TX^TXw - 2w^TX^TY + Y^TY L(w)=21∣∣Y^−Y∣∣2=wTXTXw−2wTXTY+YTY - 优化任务:
w = argmin w L ( w ) w = \mathop{\text{argmin}}_{w} L(w) w=argminwL(w)
5. 优化算法(梯度下降法)
-
初始化参数 w ( 0 ) = [ w 0 ( 0 ) , w 1 ( 0 ) , . . . , w n ( n ) ] w^{(0)} = [w_0^{(0)}, w_1^{(0)},..., w_n^{(n)}] w(0)=[w0(0),w1(0),...,wn(n)] ,这里是把截距项也放进去了。
-
设定学习率 α \alpha α,最大迭代次数 l o o p s loops loops,可接受误差 ϵ \epsilon ϵ
-
修改数值矩阵 X = [ x i ( j ) ] N × ( n + 1 ) X = [x_i^{(j)}]_{N \times (n+1)} X=[xi(j)]N×(n+1):多出来的一列放于首列,全设置为1
-
计算当前梯度:
- w T X T X w w^TX^TXw wTXTXw可以视为 w T A w w^TAw wTAw,并由于 A A A是实对称矩阵,即: X T X = ( X T X ) T X^TX = (X^TX)^T XTX=(XTX)T,可以得到:
∂ ( w T X T X w ) ∂ w = ( X T X + X T X ) w = 2 X T X w \frac{\partial (w^TX^TXw)}{\partial w} = (X^TX + X^TX)w = 2X^TXw \\ ∂w∂(wTXTXw)=(XTX+XTX)w=2XTXw
-
w T X T Y w^TX^TY wTXTY 看成是关于 w T w^T wT的函数,即 f ( w T ) = w T X T Y f(w^T) = w^TX^TY f(wT)=wTXTY,则有:
∂ ( 2 w T X T Y ) ∂ w = 2 X T Y \frac{\partial (2w^TX^TY)}{\partial w} = 2X^TY ∂w∂(2wTXTY)=2XTY -
参数梯度为(矩阵运算时一般是采用这个):
∂ L ( w ) ∂ w = X T X w − X T Y = X T ( Y ^ − Y ) \frac{\partial L(w)}{\partial w} = X^TXw - X^TY = X^T(\hat Y - Y) ∂w∂L(w)=XTXw−XTY=XT(Y^−Y)
- 数值矩阵 X = [ x i ( j ) ] N × ( n + 1 ) X = [x_i^{(j)}]_{N \times (n+1)} X=[xi(j)]N×(n+1),对 X T Y w X^TYw XTYw和 X T X X^TX XTX进行分解,每个参数 w j w_j wj的当前梯度为:
∂ L ( w ) ∂ w j = ∑ k = 0 n ∑ i = 1 N x i j x i k w k − ∑ i = 1 N x i j ⋅ y i \frac{\partial L(w)}{\partial w_j} = \sum\limits_{k=0}^{n}\sum\limits_{i=1}^{N}x^j_ix_i^kw_k - \sum\limits_{i=1}^{N}x_i^{j}\cdot y_i ∂wj∂L(w)=k=0∑ni=1∑Nxijxikwk−i=1∑Nxij⋅yi
-
若 ∂ L ( w ) ∂ w ≥ ϵ \frac{\partial L(w)}{\partial w} \ge \epsilon ∂w∂L(w)≥ϵ,则更新参数,再按上述计算方式更新梯度:
w ( k + 1 ) : = w ( k ) − α ⋅ ∂ L ( w ) ∂ w w^{(k+1)} := w^{(k)} - \alpha \cdot \frac{\partial L(w)}{\partial w} w(k+1):=w(k)−α⋅∂w∂L(w) -
当 ∂ L ( w ) ∂ w < ϵ \frac{\partial L(w)}{\partial w} < \epsilon ∂w∂L(w)<ϵ 或超过最大迭代次数时,返回最新更新的参数 w ( k ) w^{(k)} w(k)。
6. 代码实现
# 导入包
import numpy as np
import os
from sklearn.datasets import load_boston
import time
os.chdir('D:/NewProject/datawhale/ensemble/task2')
# 定义梯度
def grad(x_, y_, w_):
g = np.dot(x_.T, (np.dot(x_, w_) - y_)) / len(x_)
return g
# 定义梯度下降
def sgd(x_, y_t, w_, lr, error, loops):
num = 0
g = grad(x_, y_t, w_)
while num < loops:
theta_ = w_ - lr * g
g = grad(x_, y_t, theta_)
if np.all(np.abs(g) < error):
print('已找到最优参数!\n总共迭代的次数为{}'.format(num))
print('最优参数为:{}'.format(np.round(w_, 3)))
break
w_ = theta_
num += 1
if num == loops:
print('以达到最大迭代次数!\n最终参数为:{}'.format(np.round(w_, 3)))
return w_
if __name__ == '__main__':
# 载入数据集
data = load_boston()
# 设定随机种子(后面用于生成随机参数)
np.random.seed(2021)
np.set_printoptions(suppress=True)
# 选取变量
x = data['data']
y = data['target']
# 对数据预处理(标准化)
x = (x - np.mean(x, axis=0)) / np.std(x, axis=0)
# 加入偏置项
x0 = np.ones(len(x)).reshape(-1, 1)
x = np.concatenate((x0, x), axis=1) # 合并列
# 初始化参数
theta = np.random.randn(len(x[0]))
# 设定参数
alpha = 0.01
err = 0.00001
max_loops = 100000
# 求解参数
start = time.time()
best_theta = sgd(x, y, theta, alpha, err, max_loops)
end = time.time()
print('总共运行时长为:{}s'.format(np.round(end - start, 4)))
- 结果如下(输出参数保留了三位小数):