Skip to content

第4讲 深度学习

4.1 深度学习概述

浅层学习(Shallow Learning):传统机器学习和信号处理仅含单层非线性变换,称为浅层学习结构。例如感知器模型,线性判别分析,支持向量机,隐马尔可夫模型,条件随机场。它们对复杂函数表示能力有限,对复杂分类问题性能受限。

深度学习(Deep Learning):受大脑的分层结构启发,利用多个隐层的人工神经网络赋予特征学习能力;通过学习深层非线性网络结构,实现复杂函数的逼近,从数据中学习本质特征。

深度学习强调模型结构的深度,通常有5层以上的隐层节点。深度学习通过逐层特征变换,将样本从原特征空间变换到新的特征空间,从而使分类预测更加容易;利用大数据来学习特征,实现对模式本质特征的自动学习。

深度学习的发展历史:神经网络概念及人工神经元的数学模型(1943),神经集合体假设(1949),感知器模型 Perceptron (1957),BP 神经网络算法,Neocognitron 模型(1980),卷积神经网络 CNN,长短时记忆网络 LSTM (1997),深度置信网络 DBN (2006),自编码器 Auto encoder (2006),生成式对抗网络 GAN (2014),Self-attention & Transformer (2017)。

4.2 人工神经元模型

回顾机器学习中的感知机 Perception,感知机一种最简单形式的前馈神经网络,可应用于二元线性分类。逻辑回归 Logistic Regression 是解决二分类问题的机器学习方法,用于估计某种事物的可能性。

人工神经元模型(Neuron):神经网络的基本单元

  1. 输入:接受外界或者前层输入。
  2. 连接:根据权重对输入加权。
  3. 激活函数:连接层输出的非线性映射。
  4. 输出:输出至下个隐含层。

关于 激活函数 的总结,可见 第3讲 机器学习-感知机-激活函数

损失函数(Loss Function),衡量模型预测值和真实值之间的差异,以评价模型优劣。损失函数一般是非负的,有下界。

多分类问题中的损失函数: Softmax 激活 + 负对数似然损失

\[ L=-\sum_{i} \log\left(\frac{\exp(z_{i,j})}{\sum_{k} \exp(z_{i,k})}\right) \]

上式中 \(j\) 为第 \(i\) 个样本 \(x_i\) 的真实类别标签, \(z_{i,k}\) 为输出的预测向量。

假设有 \(K\) 个类别,某样本输出 \(K\) 维向量 \(\mathbf{z}_i = [z_{i,1}, z_{i,2}, \cdots, z_{i,K}]^T\),则其属于第 \(j\) 类的概率为 \(\hat{y}_{i,j} = \exp(z_{i,j}) \bigg/ \displaystyle\sum_{k=1}^{K} \exp(z_{i,k})\);若样本的真实类别标签为第 \(j\) 类,则 \(\hat{y}_{i,j}\) 越大越接近于 1 则损失越小越接近于 0;反之损失越大。

回归问题中的损失函数:

(1)均方损失 \(L=\dfrac{1}{2} \displaystyle\sum_{i}\|y_i - \hat{y}_i\|^2,\;\hat{y}_i=h(\boldsymbol{x}_i)\),其中 \(y_i\) 为真实值,\(\hat{y}_i\) 为预测值。

(2)L1 损失 \(L=\displaystyle\sum_{i}\|y_i - \hat{y}_i\|\),其中 \(y_i\) 为真实值,\(\hat{y}_i\) 为预测值。

(3)Smooth-L1 损失:

\[ L_i=\begin{cases} \dfrac{1}{2}(y_i - \hat{y}_i)^2 & \text{if } |y_i - \hat{y}_i| < 1 \\ |y_i - \hat{y}_i| - \frac{1}{2} & \text{otherwise} \end{cases},\quad L=\sum_{i} L_i \]

4.3 全连接前馈神经网络

全连接前馈神经网络(Fully-connected FeedForward Networks, FFN)。

在网络结构中,每个神经元有对应权重和偏置参数,所有神经元的权重和偏置定义为网络参数。

若相邻两层的神经元的数量分别为 \(n_1,n_2\) ,则两层神经元之间的网络,权重的参数量为 \(n_1n_2\) ,偏置的参数量为 \(n_2\) ,因此两层神经元之间的参数量为 \(n_1n_2+n_2\)。整个神经网络的参数量为所有层之间的参数量之和,有 \(N\) 层则求和 \(N-1\) 次。

这很好理解,因为单层网络的输出形如 \(\mathbb{R}^{n_1}\to\mathbb{R}^{n_2}:\;\boldsymbol{y}=\boldsymbol{w}^T\boldsymbol{x}+\boldsymbol{b},\;\boldsymbol{w}\in\mathbb{R}^{n_1\times n_2},\;\boldsymbol{b}\in\mathbb{R}^{n_2}\)

4.3.1 BP

Back Propagation (BP) 学习算法

最常用的神经网络的监督学习算法,其数学基础是链式求导法则。BP 学习算法由前向传播和误差反向传播组成:

前向传播是输入信号从输入层经隐含层,传向输出层。若输出层得到了期望的输出,则学习算法结束;否则,转至反向传播。

反向传播是将误差(样本输出与网络输出之差)按原联接通路反向计算,由梯度下降法调整各层节点的权值和阈值,使误差减小。

说明

前传和反传、梯度的计算过程需要结合具体的神经网络图像才能较好讲解,因此此处略过。

对于简单的网络,例如考试题,可以对参数逐个手动计算,也可以利用矩阵形式计算,但是要注意矩阵的求导的方法。

前向传播:

\[ \boldsymbol{z}^{(l)} = \boldsymbol{W}^{(l)}\boldsymbol{a}^{(l-1)} + \boldsymbol{b}^{(l)},\quad \boldsymbol{a}^{(l)} = f(\boldsymbol{z}^{(l)}) \\ \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{W}^{(l)}} = \boldsymbol{a}^{(l-1)},\quad \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} = 1 \]

反向传播(递推表达式):

\[ \frac{\partial L}{\partial \boldsymbol{z}^{(l)}}=\delta^{(l)} = (\boldsymbol{W}^{(l+1)})^T \odot f'(\boldsymbol{z}^{(l)}) \delta^{(l+1)} \\ \frac{\partial L}{\partial \boldsymbol{W}^{(l)}} = \delta^{(l)}(\boldsymbol{a}^{(l-1)})^T,\quad \frac{\partial L}{\partial \boldsymbol{b}^{(l)}} = \delta^{(l)} \]

则损失函数 对 第 \(l\) 层权重矩阵 \(\boldsymbol{W}^{(l)}\) 中第 \((i,j)\) 个权重 \(\boldsymbol{W}_{ij}^{(l)}\) 的梯度为:

\[ \frac{\partial L}{\partial \boldsymbol{W}_{ij}^{(l)}} = \frac{\partial L}{\partial z_i^{(l)}} \cdot \frac{\partial z_i^{(l)}}{\partial \boldsymbol{W}_{ij}^{(l)}} = \delta_i^{(l)} \cdot a_j^{(l-1)} \]

训练方法:梯度下降

神经网络全部参数 \(\theta=\{\boldsymbol{W}_1,\dots,\boldsymbol{b}_1,\dots\}\) ,训练目标是学习获取使损失函数最小化的网络参数 \(\theta^*\) ,参数更新规则为:

\[ w \leftarrow w - \eta \frac{\partial L}{\partial w},\quad b \leftarrow b - \eta \frac{\partial L}{\partial b} \\ \theta \leftarrow \theta - \eta \nabla_\theta L(\theta) \]

批次梯度下降 BGD (Batch Gradient Descent),所有样本都参与计算梯度: \(\theta \leftarrow \theta - \eta \nabla_\theta L(\theta)\) ,缺点是速度慢,数据量大时内存不足。

随机梯度下降 SGD (Stochastic Gradient Descent),每次只用一个样本参与计算梯度: \(\theta \leftarrow \theta - \eta \nabla_\theta L(\theta,x_i,y_i)\) ,优点是速度快,缺点是方差大,损失函数震荡严重。

小批次梯度下降 Mini-batch Gradient Descent (M-SGD),介于 BGD 和 SGD 之间,每次随机选取 \(M\) 个样本参与计算梯度: \(\theta \leftarrow \theta - \eta\left[\dfrac{1}{M}\displaystyle\sum_{i=1}^M\nabla_\theta L(\theta,x_i,y_i)\right]\)

3种方法的比较:

特性 BGD SGD M-SGD
单次迭代样本数 整个数据集 单个样本 整个数据集的一个子集
算法复杂度 一般
时效性 一般 一般
收敛性 稳定 不稳定 较稳定

训练流程:

  1. 初始化神经网络,初始化设置网络参数。
  2. 前向传播,计算梯度,反向传播。
  3. 重复,直到梯度的更新非常小。

4.3.2 Optimization

梯度下降可能存在的问题:能找到局部最优,但是无法保证找到全局最优。因为可能遇到鞍点 (Saddle Point)。改进方法有:

(1)动量 Momentum

避免随机梯度下降陷入局部最优。维护一个“状态变量” \(\beta\) 记录之前的梯度,每次更新参数时不仅考虑当前的梯度,也考虑之前存下来的动量,从而帮助模型越过上面的局部最小值。

\[ \beta_{t+1} = \mu \beta_t - \eta \nabla_{\theta} L(\theta_t), \quad \theta_{t+1} = \theta_t + \beta_{t+1} \]

其中 \(\beta_t\) 即为动量, \(\mu\in[0,1]\) 为对应的常系数。参数中梯度方向不大的维度加速更新,同时减少在梯度方向变化大的维度上的更新幅度。

(2)权重衰减 Weight Decay 在损失函数中加入正则化项(增加对较大系数的惩罚项),防止过拟合。常用的正则化方法有 L1 正则化和 L2 正则化。例如 L2 正则化:

\[ \tilde{L}(w)=L(w) + \frac{1}{2}\lambda \|w\|^2 \\ w \leftarrow w - \eta \left(\frac{\partial L}{\partial w} + \lambda w\right) \]

(3)AdaGrad: Adaptive Gradient

利用梯度平方累加和的平方根。不同的参数使用不同的学习率:

\[ c_t = \sum_{j=1}^{t} \left( \nabla_\theta L(\theta_j) \right)^2 \\ \theta_{t+1} = \theta_t - \eta \frac{\nabla_\theta L(\theta_t)}{\sqrt{c_t} + \varepsilon} \]

不同参数的学习率依赖于 \(c_t\) 。对低频参数做较大的更新,对高频参数做较小的更新,提升了 SGD 的鲁棒性,对于稀疏数据表现好。

(4)RMSprop: Root-Mean-Square Prop

与 AdaGrad 思想类似,利用梯度平方加权取倒数对梯度进行加权。定义 RMS 梯度:

\[ s_t = \gamma s_{t-1} + (1 - \gamma) \left( \nabla_\theta L(\theta_t) \right)^2 \\ \theta_{t+1} = \theta_t - \eta \frac{\nabla_\theta L(\theta_t)}{\sqrt{s_t} + \varepsilon} \]

保证各维度导数在一个量级,减少摆动。Hinton 建议 \(\gamma=0.9,\mu=0.001\)

(5)Adam: Adaptive Moment Optimization

Adam 是 RMSprop 和 Momentum 的结合。计算梯度和梯度平方的平滑平均,利用梯度的一阶矩和二阶矩的指数加权平均。这也是目前主流的优化器。

\[ v_t = \beta_1 v_{t-1} + (1 - \beta_1) \nabla_\theta L(\theta_t) \\ s_t = \beta_2 s_{t-1} + (1 - \beta_2) \left( \nabla_\theta L(\theta_t) \right)^2 \\ \theta_{t+1} = \theta_t - \eta \frac{v_t}{\sqrt{s_t} + \varepsilon} \]

参数设置: \(\beta_1 = 0.9\)\(\beta_2\) 接近于 1,例如 0.9999。


参数初始化方法

一般 偏置 初始化为0,而 权重 的初始化方法有:

随机初始化:权重初始化为0,标准差为 \(\sigma\) ,则 \(w_i^l \sim \mathcal{N}(0, \sigma^2)\)

Xavier 初始化:

\[ w_i^l \sim \mathcal{N} \left( 0, \frac{2}{n_l + n_{l-1}} \right) ,\quad w_i^l \sim \mathcal{U} \left[ -\sqrt{\frac{6}{n_l + n_{l-1}}}, \sqrt{\frac{6}{n_l + n_{l-1}}} \right] \]

Kaiming 初始化:

\[ w_i^l \sim \mathcal{N} \left( 0, \frac{2}{n_l} \right) ,\quad w_i^l \sim \mathcal{U} \left[ -\sqrt{\frac{6}{n_l}}, \sqrt{\frac{6}{n_l}} \right] \]

动态学习率:在训练过程中根据迭代次数逐步调整学习率。在训练初期,离目标损失远,设置较大学习率。训练一段时间后,已到达目标损失附近,距离最优点近,选择较小学习率。


梯度消失问题

以 Sigmoid 函数为例:

\[ \sigma'(z) = \frac{e^{-z}}{(1 + e^{-z})^2} = \sigma(z)(1 - \sigma(z)) \in \left(0, \frac{1}{4}\right] \\ \frac{\partial L}{\partial b_1}\leqslant \left(\frac{1}{4}\right)^n w_2 w_3 \cdots w_n \frac{\partial L}{\partial b_n} \]

随着网络深度的加深,梯度衰减非常严重,梯度趋于0导致无法继续训练。

如何缓解梯度消失:

  1. 分层预训练:Hinton 于2006年提出,利用无监督数据进行分层预训练,再利用有监督数据调整网络参数。
  2. ReLU 激活函数。缓解 Sigmoid 和 tanh 激活函数存在较严重的梯度消失问题。
  3. Batch Normalization:逐层对数据进行尺度归一化。
  4. 辅助损失函数:对浅层神经元输出建立辅助损失函数,直接传递梯度。在 GoogleNet 中使用到。

梯度爆炸问题

\[ \frac{\partial L}{\partial b_1} = \sigma'(b_1) w_2 \sigma'(b_2) w_3 \cdots \sigma'(b_{N-1}) w_N \frac{\partial L}{\partial b_N} \\ \left| w_j \sigma'(b_j)\right| > 1 \]

如何缓解梯度爆炸:

  1. 重新设计网络模型/更换激活函数。
  2. RNN 中使用 ReLU 激活函数可减少梯度爆炸。
  3. 使用梯度截断(gradient clipping)。
  4. 权重正则化,增加 L1/L2 正则惩罚项。

Comments