Datawhale组队学习第27期:集成学习 本次学习的指导老师萌弟的教学视频 本贴为学习记录帖,有任何问题欢迎随时交流~ 部分内容可能还不完整,后期随着知识积累逐步完善。 开始时间:2021年7月13日 最新更新:2021年7月15日(Task2回归问题)
一、基本建模步骤
- 明确项目任务
- 收集数据集并选取合适的特征
- 选择度量模型性能的指标
- 选择具体的模型并进行训练以优化模型
- 评估模型并调参
二、以Boston房价为例
三、线性回归模型推导
在前几个月,本人写过一篇关于线性回归的简单应用,文章主要介绍了线性回归在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^?i?Y^?=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
N
∣
∣
Y
^
?
Y
∣
∣
2
=
w
T
X
T
X
w
?
2
w
T
X
T
Y
+
Y
T
Y
L(w) = \frac{1}{2N} ||\hat Y - Y||_2 = w^TX^TXw - 2w^TX^TY + Y^TY
L(w)=2N1?∣∣Y^?Y∣∣2?=wTXTXw?2wTXTY+YTY - 优化任务:
w
=
argmin
w
L
(
w
)
w = \mathop{\text{argmin}}_{w} L(w)
w=argminw?L(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
?
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∑n?i=1∑N?xij?xik?wk??i=1∑N?xij??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)))
- 结果如下(输出参数保留了三位小数):
四、参考资料
- https://github.com/datawhalechina/ensemble-learning
- https://www.bilibili.com/video/BV1Mb4y1o7ck?t=470
|