Linear Regression
回归是能为一个或多个自变量与因变量之间关系建模的一类方法,在机器学习中,回归和分类并列为重点研究对象,当我们想预测一个数值时,就会涉及到回归问题。
给定数据集
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
}
D=\{(x1, y1), (x2, y2), ... \}
D={(x1,y1),(x2,y2),...},我们试图从此数据集中学习得到一个线性模型,这个模型尽可能准确地反应
x
(
i
)
x(i)
x(i)和
y
(
i
)
y(i)
y(i)的对应关系。这里的线性模型,就是属性
x
x
x的线性组合的函数,可表示为:
f
(
x
)
=
w
1
x
1
+
w
2
x
2
+
.
.
.
+
w
d
x
d
+
b
f(x) = w_1x_1 + w_2x_2 + ... + w_dx_d + b
f(x)=w1x1+w2x2+...+wdxd+b
向量形式表示为:
f
(
x
)
=
w
T
x
+
b
f(x) = w^Tx + b
f(x)=wTx+b
这里的
w
w
w表示权重,权重越大,说明对应的变量对结果的影响越大。
为了量化目标的实际值与预测值之间的差距,我们需要一个函数来表示这二者之间的关系,这就是为什么我们需要损失函数,损失函数的数值越小,其损失越小。在回归问题中最常见的损失函数是MSE (Mean Square Error),当样本
i
i
i的预测值为
y
^
(
i
)
\hat{y}^{(i)}
y^(i),其相应的真实标签为
y
(
i
)
y^{(i)}
y(i)时, 平方误差可以定义为以下公式:
l
(
i
)
(
w
,
b
)
=
1
2
(
y
^
(
i
)
−
y
(
i
)
)
2
l^{(i)}(\mathbf{w}, b) = \frac{1}{2} \left(\hat{y}^{(i)} - y^{(i)}\right)^2
l(i)(w,b)=21(y^(i)−y(i))2
为了度量模型在整个数据集上的质量,我们需计算在训练集
n
n
n个样本上的损失均值(也等价于求和)。
L
(
w
,
b
)
=
1
n
∑
i
=
1
n
l
(
i
)
(
w
,
b
)
=
1
n
∑
i
=
1
n
1
2
(
w
⊤
x
(
i
)
+
b
−
y
(
i
)
)
2
L(\mathbf{w}, b) =\frac{1}{n}\sum_{i=1}^n l^{(i)}(\mathbf{w}, b) =\frac{1}{n} \sum_{i=1}^n \frac{1}{2}\left(\mathbf{w}^\top \mathbf{x}^{(i)} + b - y^{(i)}\right)^2
L(w,b)=n1i=1∑nl(i)(w,b)=n1i=1∑n21(w⊤x(i)+b−y(i))2
在训练模型时,我们希望寻找一组参数
(
w
∗
,
b
∗
)
(\mathbf{w}^*, b^*)
(w∗,b∗), 这组参数能最小化在所有训练样本上的总损失。如下式:
w
∗
,
b
∗
=
argmin
w
,
b
L
(
w
,
b
)
\mathbf{w}^*, b^* = \operatorname*{argmin}_{\mathbf{w}, b}\ L(\mathbf{w}, b)
w∗,b∗=w,bargmin L(w,b)
The Multilayer Perceptron and Back Propagation
一个标准的多层感知机由三部分组成:一个输入层、一个隐藏层和一个输出层。
1986年,David Rumelhart, Geoffrey Hinton, Ronald Williams发表了一篇极其重要的文章,引入了back propagation算法。简单来说,这是一种利用梯度下降自动计算梯度的技巧,仅仅需要对网络作出两次遍历:一次向前,一次向后。BP算法能够计算出网络的误差相对于每一个模型参数的梯度。换句话说,它能够找到模型参数应该如何变化才能减小误差的方法。一旦我们获得这些梯度,就可以应用一次梯度下降,不断重复这一过程直到收敛。
在这里我们不给出精确的数学推导(因为推完之后也会忘),而是给出比较直观的理解。
- 一次处理一个小批量(例如每次包含 32 或64个实例),如此,多次传入完整的训练集。每次完整的一次训练集数据传递称为一个epoch。
- 每个小批量都传递到网络的输入层,输入层将其发送到第一个隐藏层。该算法然后计算该层中所有神经元的输出(对于小批量中的每个实例)。结果被传递到下一层,它的输出被计算并传递到下一层,依此类推,直到我们得到最后一层的输出,即输出层。这就是前向传递:它与进行预测完全一样,但是所有中间结果都被保留,因为我们需要这些数据用于反向传递。
- 接下来,该算法测量网络的输出误差(即它使用损失函数比较期望输出和网络的实际输出,并返回误差测量值)。
- 计算每个输出连接对误差的贡献。这是通过应用链式法完成的,这使得这一步快速而精确。
- 然后,再次使用链式法则测量这些错误贡献中有多少来自下层中的每个连接,向后工作直到算法到达输入层。如前所述,这种反向传递通过在网络中向后传播误差梯度,有效地测量了网络中所有连接权重的误差梯度。
- 最后,执行梯度下降来调整网络中的所有连接权重,使用它刚刚计算的误差梯度。
Optimizer
SGD
对于一个损失函数:
J
(
θ
)
=
1
2
∑
i
=
1
m
(
h
θ
(
x
)
−
y
)
2
J(\theta)=\frac{1}{2} \sum_{i=1}^m\left(h_\theta(x)-y\right)^2
J(θ)=21∑i=1m(hθ(x)−y)2
曲面上方向导数的最大值的方向就代表了梯度的方向,因此我们在做梯度下降的时候,应该是沿着梯度的反方向进行权重的更新,可以有效的找到全局的最优解:
θ
j
:
=
θ
j
−
α
∂
∂
θ
j
J
(
θ
)
∂
∂
θ
j
J
(
θ
)
=
∂
∂
θ
j
1
2
(
h
θ
(
x
)
−
y
)
2
=
2
⋅
1
2
(
h
θ
(
x
)
−
y
)
⋅
∂
∂
θ
j
(
h
θ
(
x
)
−
y
)
=
(
h
θ
(
x
)
−
y
)
⋅
∂
∂
θ
j
(
∑
i
=
0
n
θ
i
x
i
−
y
)
=
(
h
θ
(
x
)
−
y
)
x
j
\begin{aligned} \theta_j:=\theta_j & -\alpha \frac{\partial}{\partial \theta_j} J(\theta) \\ \frac{\partial}{\partial \theta_j} J(\theta) & =\frac{\partial}{\partial \theta_j} \frac{1}{2}\left(h_\theta(x)-y\right)^2 \\ & =2 \cdot \frac{1}{2}\left(h_\theta(x)-y\right) \cdot \frac{\partial}{\partial \theta_j}\left(h_\theta(x)-y\right) \\ & =\left(h_\theta(x)-y\right) \cdot \frac{\partial}{\partial \theta_j}\left(\sum_{i=0}^n \theta_i x_i-y\right) \\ & =\left(h_\theta(x)-y\right) x_j \end{aligned}
θj:=θj∂θj∂J(θ)−α∂θj∂J(θ)=∂θj∂21(hθ(x)−y)2=2⋅21(hθ(x)−y)⋅∂θj∂(hθ(x)−y)=(hθ(x)−y)⋅∂θj∂(i=0∑nθixi−y)=(hθ(x)−y)xj
那么随机二字从何而来呢?随机也就是说我们用样本中的一个例子来近似我所有的样本,来调整
θ
θ
θ,因而随机梯度下降是会带来一定的问题,因为计算得到的并不是准确的一个梯度,对于最优化问题,凸问题,虽然不是每次迭代得到的损失函数都向着全局最优方向, 但是大的整体的方向是向全局最优解的,最终的结果往往是在全局最优解附近。但是相比于批量梯度,这样的方法更快,更快收敛,虽然不是全局最优,但很多时候是我们可以接受的,所以这个方法用的也比上面的多。
θ
j
:
=
θ
j
+
α
(
y
(
i
)
−
h
θ
(
x
(
i
)
)
)
x
j
(
i
)
(
for every
j
)
\theta_j:=\theta_j+\alpha\left(y^{(i)}-h_\theta\left(x^{(i)}\right)\right) x_j^{(i)} \quad(\text { for every } j)
θj:=θj+α(y(i)−hθ(x(i)))xj(i)( for every j)
Adam
Adam是现今被广泛使用的主流优化器之一,其算法大致思路如下:
计算t时间步的梯度:
g
t
=
∇
θ
J
(
θ
t
−
1
)
g_t=\nabla_\theta J\left(\theta_{\mathrm{t}-1}\right)
gt=∇θJ(θt−1)
首先,计算梯度的指数移动平均数,
m
0
m_0
m0 初始化为0。
类似于Momentum算法,综合考虑之前时间步的梯度动量。
β
1
β_1
β1 系数为指数衰减率,控制权重分配(动量与当前梯度),通常取接近于1的值,默认为0.9。
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
g
t
m_t=\beta_1 m_{t-1}+\left(1-\beta_1\right) g_t
mt=β1mt−1+(1−β1)gt
其次,计算梯度平方的指数移动平均数,
v
0
v_0
v0初始化为0。
β
2
β_2
β2 系数为指数衰减率,控制之前的梯度平方的影响情况。
类似于RMSProp算法,对梯度平方进行加权均值,默认为0.999。
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
g
t
2
v_t=\beta_2 v_{t-1}+\left(1-\beta_2\right) g_t^2
vt=β2vt−1+(1−β2)gt2
第三,由于
m
0
m_0
m0初始化为0,会导致
m
t
m_t
mt偏向于0,尤其在训练初期阶段。
所以,此处需要对梯度均值
m
t
m_t
mt进行偏差纠正,降低偏差对训练初期的影响。
m
^
t
=
m
t
/
(
1
−
β
1
t
)
\hat{m}_t=m_t /\left(1-\beta_1^t\right)
m^t=mt/(1−β1t)
第四,与
m
0
m_0
m0类似,因为
v
0
v_0
v0初始化为0导致训练初始阶段
v
t
v_t
vt偏向0,对其进行纠正。
v
^
t
=
v
t
/
(
1
−
β
2
t
)
\hat{v}_t=v_t /\left(1-\beta_2^t\right)
v^t=vt/(1−β2t)
第五,更新参数,初始的学习率
α
α
α乘以梯度均值与梯度方差的平方根之比。
其中默认学习率
α
=
0.001
α=0.001
α=0.001
ε
=
1
0
−
8
ε=10^{-8}
ε=10−8,避免除数变为0。
由表达式可以看出,对更新的步长计算,能够从梯度均值及梯度平方两个角度进行自适应地调节,而不是直接由当前梯度决定。
θ
t
=
θ
t
−
1
−
α
∗
m
^
t
/
(
v
^
t
+
ε
)
\theta_{\mathrm{t}}=\theta_{t-1}-\alpha^* \hat{m}_t /\left(\sqrt{\hat{v}_t}+\varepsilon\right)
θt=θt−1−α∗m^t/(v^t+ε)