第2章 深度学习
2.1 深度学习的原理
深度学习(Deep Learning)是深度神经网络(Deep Neural Networks)的另一个名称。深度学习的核心是深度神经网络的设计与训练,采用层级更深、参数规模更大的神经网络。
神经网络可以看作是对人脑的智能原理的一个数学抽象,包括神经元的结构和神经元的连接结构。其中,神经元的一个建模是逻辑回归单元。
深度学习通过单一的算法学习特征表示。逻辑回归是最常用的分类算法,也是深度学习的基本组成单元。
2.1.1 人工神经元
人工神经元可以理解为一组输入加权叠加,再经过一个连续可导的非线性变换进行输出。为了叙述方便,以下人工神经元简称神经元。
1.逻辑斯提回归单元
逻辑斯提回归单元(Logistic Regression Unit)是最简单的人工神经元结构。单个逻辑斯提回归单元可以进行二类分类,多个逻辑斯提回归单元的组合,就可以完成复杂的分类工作。多层逻辑斯提回归单元在实际中表现出更好的性能。
单个逻辑斯提回归单元的数学表达式如下:
其中,wi与xi分别为权重与输入,y为输出结果。f()函数采用逻辑斯提函数或逻辑曲线(Logistic Function)。f()函数的数学表达式和形状(见图2-1)如下:
图2-1 f()函数的形状
其图形是一条S形曲线(Sigmoid Curve)。逻辑函数因其曲线形状为S形,所以,也被称为S()函数或Sigmoid()函数。Sigmoid()函数的取值为(0,1)。
2.激活函数
f()函数也称为人工神经元的激活函数(Activation Function or Trigger Function)。当f()函数采用逻辑斯提函数时,则人工神经元就是逻辑斯提回归单元。除了逻辑斯提回归单元的形式,人工神经元还有其他形式。例如,f()函数可以是tanh()函数、Softmax()函数和ReLU()函数(Rectified Linear Units)等。
双曲正切函数tanh(),其数学表达式如下:
tanh()函数和Sigmoid()函数是同类的,只是取值变为(-1,1)。
ReLU()函数的数学表达式如下:
ReLU(x)=max(x,0)
ReLU()还有其推广形式,称为PReLU(Parametric ReLU)。PReLU()的数学表达式如下,其中α≈0.01:
Softmax()函数(又称为归一化指数函数)多用于输出一个识别对象的概率分布。Softmax()函数的数学表达式如下:
2.1.2 多层人工神经网络
将多个人工神经元排列连接起来,就形成了多层人工神经网络。图2-2给出了一个二层神经网络结构的例子。
图2-2 二层神经网络
该神经网络分为输入层、隐藏层和输出层。输入层有3个输入(x0,x1,x2),中间有一个隐藏层,输出层有2个输出(y1,y2),共有5个神经元。
该网络的连接结构采用多层全连接(Fully Connected Network,FCN)的模式,是人工神经网络中最简单的连接方式。
为了叙述方便,以下人工神经网络简称神经网络。
2.1.3 神经网络训练
如果激活函数f(x)是一个连续可导函数,如Sigmoid()函数,那么神经网络本质上是一个由输入和内部权重作为变量的连续可导函数。
神经网络的训练过程属于机器学习的监督学习(Supervise Learning),即训练数据上都有相应的标签(Label)。神经网络对具有标签的训练样本进行学习,从而确定网络的权重参数,然后用训练得到网络,对训练样本集外的数据进行标签的预测。
神经网络训练的本质,就是找到相应的内部权重,使得在训练数据(样本)输入到网络后,网络的实际输出与预期输出(即标签)之间差异最小。
1.损失函数最小化
神经网络的输出结果会与实际所对应的标签之间存在差别,可以引入相似度度量函数,来表示这种差异,称为损失函数(Loss())、成本函数(Cost())或代价函数。
神经网络训练的目标是使损失函数最小,所以,训练过程是损失函数的求最小化过程。损失函数可以通过交叉熵的方式,来计算损失。其他的损失函数形式还有均方求和、均方根等度量函数,但是这类函数作为损失函数的缺点是它们属于非凸函数,存在很多极小值点。
交叉熵形式的损失函数表示如下:
其中,y′表示训练样本对应的标签,y表示神经网络的输出。
实际中还会在损失函数中加上一些正则项(Regularizer)或惩罚项(Penalty Term),该过程称为正则化(Regularization)。目的是为了防止过学习(Over-fitting)。常见的惩罚项是。
2.反向传播算法
这里给出多层神经网络的一种更加抽象表示,这种表示抽象了每层的基本特征,如图2-3所示。
根据损失函数的性质和链式求导法则,可以反向逐层计算损失函数对权重的导数,调整权重最小化损失函数。这个方法称为反向传播算法(Back-Propagation Algorithm)。多层神经网络的反向传播的过程如图2-4所示。
图2-3 多层神经网络
图2-4 多层神经网络的反向传播方法
3.随机梯度下降法
随机梯度下降方法(Stochastic Gradient Descent,SGD)是最常用的权重调节方法,基本方法如下。
步骤1:随机初始化每个神经元的输入权重和偏差(Weights and Bias)。
步骤2:选取一个随机样本(Samples)。
步骤3:根据神经网络的输出结果,从最后一层开始,逐层计算每层权重的偏导数。
步骤4:逐层调整每层的权重,产生新的权重值。
返回到步骤2,继续随机选取下一个样本。
4.实际训练过程
多层神经网络的实际训练过程是将样本数据“分批训练”,同时采用随机梯度下降法和反向传播方法,逐层调整权重参数。
训练过程中的一些术语解释如下。
(1)先将整个训练集分成多个同样大小的子集,每个子集称为一个批次(Batch),子集的大小(即样本数目)由参数批次大小(Batch Size)控制。
(2)使用随机梯度下降法,其中每一步可以使用不止一个样本,这称为迷你批次(Minibatch)。每次迭代所用的样本数目称为迷你批次大小(Minibatch Size)。当迷你批次大小为1时,就是普通的随机梯度下降。
(3)每个批次的数据被依次送入网络进行训练,训练完一个批次,被称为一次迭代(Iteration)。
(4)训练集的所有训练样本都被送入网络训练,完成一次训练的过程,称为一个时代(Epoch)。
(5)时代记录了整个训练集被反复训练的次数,而迭代记录网络权重参数的调整次数。
迭代和时代之间的数量关系由批次大小和训练集大小决定。
5.自编码器
1)自编码器初始化权重
自编码器(Autoencoder)主要用于多层神经网络参数的初始化。采用随机化网络参数的方法,会导致网络收敛慢的问题。而采用自编码器方法,在一些训练过程中证明是有效的。自编码器的结构如图2-5所示。
图2-5 自编码器的结构
自编码器的功能是神经网络的输出尽可能地还原输入的特征。这样可以对多层神经网络的每一层逐层去构造自编码器,用训练出来的权重作为多层神经网络每一层的初始权重。
自编码器初始化多层神经网络的参数方法描述如下。
(1)预训练:使用无监督的数据,对每一层进行预训练。
(2)微调步骤1:对最后的输出层用监督学习的标记数据,进行训练。
(3)微调步骤2:使用标记数据,对整个网络进行反向传播训练。
2)降噪自编码器
降噪自编码器(Denoising Autoencoder,DA)的原理是人工破坏或者屏蔽部分输入,输入到自编码器进行训练,让自编码器学到数据间的关联性。实际操作中,屏蔽是随机进行的,所以,神经网络最终学到的是通过部分数据联想到缺失数据的能力。
举个例子,输入一个9维的数据,通过屏蔽最后一维,比如将第9维数据(置零),得到一个8维+0的9维数据。将此数据经过一个9-3-9的神经网络处理,得到新的9维数据。训练要求新的9维数据和没被屏蔽前的输入数据一样。这样,自编码器至少完成了这样一件事:给定前8维,推测最后一维。
这种推测不是简单的“线性插值”,因为神经网络的每层输出,都要通过激活函数,进行了一次非线性函数变化。所以,这种推测肯定不是线性插值的,而是一种更复杂的数值插值方法。
具体参考链接http://deeplearning.net/tutorial/dA.html。
6.训练的小技巧
这些神经网络训练调试的小技巧源于Le Quoc V的教程。因为当时还没有完整成熟的深度学习框架,很多情况下需要自己去调整优化。有了成熟的框架后,有些问题就不用太关心了。
(1)用数值近似的方法检查反向传播算法的梯度计算的正确性(依赖选择的框架)。
(2)随机初始化参数是很重要的。一个好的方法是参数初始化采用高斯分布或均匀分布。有时调整一下初始化的协方差又会有帮助(依赖选择的框架)。
(3)确保随机初始化不要“饱和”网络。这意味着绝大多数时间,神经元的输出为0.2~0.8。如果神经元输出太多的0或1,梯度值会比较小,训练时间会比较长。
(4)能够有效地监控训练过程(依赖选择的框架)。
(5)选取好的学习率。建议学习率为0.1或0.0 1。学习率过大,参数值改变过于激进;学习率过小,参数值改变过于保守。
(6)选取好的超参数(如层数、每层神经元数目)是一个当前研究的问题。一种好的方法是采用交叉验证(Cross Validation)。选取一个验证集,与训练集完全无关。如果超参数在训练集上表现好,而在验证集上表现不佳,这个模型就是过拟合(Overfits):模型有太多的自由度并记住了训练集的特征,但是无法推广。如果模型的超参数在训练集上表现极差,这就是欠拟合(Underfits):模型没有足够的自由度,应该增加隐藏层数或者神经元的数目。另外,在训练集上表现不佳,也可能是学习率选取不好(比较重要)。
(7)选取好的超参数,也可以使用Gridsearch方法,随机搜索或贝叶斯优化。在Gridsearch方法中,所有的组合都会尝试,并用验证集进行交叉检验。如果Gridsearch成本太高,可以用随机搜索来产生配置。贝叶斯优化检查先前的超参数的网络组合,找出一个拟合函数,然后选择一个最大化效用函数的超参数组合。
(8)神经网络需要长时间训练,需要花费时间去优化代码速度。例如,用快速矩阵矢量库、后向传播算法的矢量化版本(依赖选择的框架)。
(9)可以采用单精度而不是用双精度来存放参数。这可以减少一半的存储空间,而不会损害神经网络的性能。缺点是用数值近似做梯度正确性的检查会复杂些。
(10)神经网络的一个不方便之处是目标函数一般不是非凸函数。这意味着我们获得的最小值,很可能是局部最小而非全局最小。所以,神经网络对随机初始化比较敏感。学习过程的其他随机化方面也会影响结果。例如,学习率的选择,迭代样本的不同顺序会产生不同的优化参数。
(11)在许多情况中,使用较大的迷你批次是一个好方法,因为可以降低样本的噪声(计算多个样本的平均值的例子)。另外,速度更快,因为矩阵向量库用更大的矩阵工作会更好。