一、表示学习 #
1、机器学习 #
传统机器学习解决模式识别任务时,一般流程是:
数据预处理:对数据的原始形式进行初步的数据清理(比如去掉一些有缺失特征的样本,或去掉一些冗余的数据特征等)和加工(对数值特征进行缩 放和归一化等),并构建成可用于训练机器学习模型的数据集;
特征提取:从数据的原始特征中提取一些对特定机器学习任务有用的高质量特征。比如在图像分类中提取边缘、尺度不变特征变换(ScaleInvariant Feature Transform,SIFT)特征,在文本分类中去除停用词等;
特征转换:对特征进行进一步的加工,比如降维和升维。降维包括特征抽取(Feature Extraction)和特征选择(Feature Selection)两种途径。常用的特征转换方法有主成分分析 (PrincipalComponents Analysis,PCA)、 线性判别分析 (LinearDiscriminant Analysis,LDA)等;
预测:机器学习的核心部分,学习一个函数并进行预测。
浅层学习通常不涉及自动特征学习 ,特征主要依赖人工经验或特征转换方法,这一过程称为特征工程 。
语义鸿沟 :表示学习的关键是解决语义鸿沟(SemanticGap)问题。语义鸿沟问题是指输入数据的底层特征和高层语义信息之间的不一致性和差异性。比如给定一些关于“车”的图片,由于图片中每辆车的颜色和形状等属性都不尽相同,因此不同图片在像素级别上的表示(即底层特征)差异性也会非常大。但是我们理解这些图片是建立在比较抽象的高层语义概念上的。如果一个预测模型直接建立在底层特征之上,会导致对预测模型的能力要求过高。如果可以有一个好的表示在某种程度上能够反映出数据的高层语义特征,那么我们就能相对容易地构建后续的机器学习模型。
表示学习研究的是:如何自动从数据中学习好的表示 。好的表示通常具有三点:表示能力强 、能让后续任务更简单 、具有较强的一般性与任务独立性 。学习到的特征应该能捕捉数据中有用的变化因素,而不是仅仅记住表面形式。
2、数据表示:局部表示与分布式表示 #
局部表示也叫符号表示、离散表示。典型例子是One-Hot 向量 :
A = [1, 0, 0, 0]
B = [0, 1, 0, 0]
C = [0, 0, 1, 0]
局部表示有两个优点:
这种离散的表示方式具有很好的解释性,有利于人工归纳和总结特征,并通过特征组合进行高效的特征工程;
通过多种特征组合得到的表示向量通常是稀疏的二值向量,当用于线性模型时计算效率非常高。
但局部表示有两个不足之处:
one-hot向量的维数很高,且不能扩展。如果有一种新的颜色,我们就需要增加一维来表示;
不同类别之间的相似度都为 0,例如我们无法知道“红色”和“中国红”的相似度要高于“红色”和“黑色”的相似度。
分布式表示使用低维、稠密、连续向量 表示对象。分布式表示可以用较少参数表达更多语义组合。
例如:
A = [0.25, 0.50]
B = [0.20, 0.90]
C = [0.80, 0.20]
和局部表示相比,分布式表示的表示能力要强很多,分布式表示的向量维度 一般都比较低。我们只需要用一个三维的稠密向量就可以表示所有颜色。并且, 分布式表示也很容易表示新的颜色名。此外,不同颜色之间的相似度也很容易计算。
3、表示学习 #
要学习到一种好的高层语义表示(一般为分布式表示),通常需要从底层特征开始,经过多步非线性转换才能得到。深层结构的优点是可以增加特征的重用性,从而指数级地增加表示能力。因此,表示学习的关键是构建具有一定深度的多层次特征表示。
在传统的机器学习中,也有很多有关特征学习的方法,比如主成分分析、线性判别分析、独立成分分析等。但是,传统的特征学习一般是通过人为地设计一 些准则,然后根据这些准则来选取有效的特征。特征的学习是和最终预测模型的学习分开进行 的,因此学习到的特征不一定可以提升最终模型的性能。
二、深度学习 #
1、深度学习 #
为了学习一种好的表示,需要构建具有一定“深度”的模型,并通过学习算法来让模型自动学习出好的特征表示 (从底层特征,到中层特征,再到高层特征), 从而最终提升预测模型的准确率。所谓“深度”是指原始数据进行非线性特征转换的次数。如果把一个表示学习系统看作一个有向图结构,深度也可以看作从输入节点到输出节点所经过的最长路径的长度。这样我们就需要一种学习方法可以从数据中学习一个“深度模型”,这就是深度学习(DeepLearning,DL)。深度学习是机器学习的一个子问题,其主要目的是从数据中自动学习到有效的特征表示。
2、贡献度分配问题 #
和“浅层学习“不同,深度学习需要解决的关键问题是贡献度分配问题 (CreditAssignment Problem,CAP),即一个系统中不同的组件(component)或其参数对最终系统输出结果的贡献或影响。如何判断每一步棋的贡献就是贡献度分配问题,这是一个非常困难的问题。每个内部组件并不能直接得到监督信息,需要通过整个模型的最终监督信息(奖励) 得到,并且有一定的延时性。
目前,深度学习采用的模型主要是神经网络模型,其主要原因是神经网络模型可以使用误差反向传播算法 ,从而可以比较好地解决贡献度分配问题。只要是超过一层的神经网络都会存在贡献度分配问题,因此可以将超过一层的神经网络都看作深度学习模型。随着深度学习的快速发展,模型深度也从早期的5∼10层增加到目前的数百层。随着模型深度的不断增加,其特征表示的能力也越来越强,从而使后续的预测更加容易。
端到端学习 ,也称端到端训练,是指在学习过程中不进行分模块或分阶段训练,直接优化任务的总体目标。在端到端学习中,一般不需要明确地给出不同模块或阶段的功能,中间过程不需要人为干预。端到端学习的训练数据为“输入-输出”对的形式,无须提供其他额外信息。因此,端到端学习和深度学习一样,都是要解决贡献度分配问题。目前,大部分采用神经网络模型的深度学习也可以看作一种端到端的学习。
三、人工神经网络 #
“当神经元A的一个轴突和神经元B很近,足以对它产生影响,并且持续地、重复地参与了对神经元B的兴奋,那么在这两个神经元或其中之一会发生某种生长过程或新陈代谢变化,以致神经元A作为能使神经元B兴奋的细胞之一,它的效能加强了。”
这个机制称为赫布理论(Hebbian Theory)。如果两个神经元总是相关联地受到刺激,它们之间的突触强度增加。这样的学习方法被称为赫布型学习。
人工神经网络是为模拟人脑神经网络而设计的一种计算模型,由多个节点互相连接而成,可以用来对数据之间的复杂关系进行建模。不同节点之间的连接被赋予了不同的权重,每个权重代表了一个节点对另一个节点的影响大小。每个节点代表一种特定函数,来自其他节点的信息经过其相应的权重综合计算,输入到一个激活函数中并得到一个新的活性值(兴奋或抑制)。
1、神经元 #
假设一个神经元接收 D D D 个输入 x 1 , x 2 , ⋯ , x D x_{1}, x_{2}, \cdots, x_{D} x 1 , x 2 , ⋯ , x D ,令向量 x = [ x 1 ; x 2 ; ⋯ ; x D ] \boldsymbol{x}=\left[x_{1} ; x_{2} ; \cdots ; x_{D}\right] x = [ x 1 ; x 2 ; ⋯ ; x D ] 来表示这组输入,并用净输入(Net Input) z ∈ R z \in \mathbb{R} z ∈ R 表示一个神经元所获得的输入信号 x \boldsymbol{x} x 的加权和。
z = ∑ d = 1 D w d x d + b = w ⊤ x + b \begin{aligned}
z & =\sum_{d=1}^{D} w_{d} x_{d}+b \\
& =\boldsymbol{w}^{\top} \boldsymbol{x}+b
\end{aligned} z = d = 1 ∑ D w d x d + b = w ⊤ x + b
其中 ω = [ w 1 ; w 2 ; ⋯ ; w D ] ∈ R D \boldsymbol{\omega}=\left[w_{1} ; w_{2} ; \cdots ; w_{D}\right] \in \mathbb{R}^{D} ω = [ w 1 ; w 2 ; ⋯ ; w D ] ∈ R D 是 D D D 维的权重向量, b ∈ R b \in \mathbb{R} b ∈ R 是偏置.
净输入 z z z 在经过一个非线性函数 f ( ⋅ ) f(\cdot) f ( ⋅ ) 后,得到神经元的活性值(Activation) a = f ( z ) a=f(z) a = f ( z ) 。其中非线性函数 f ( ⋅ ) f(\cdot) f ( ⋅ ) 称为激活函数(Activation Function)。
2、激活函数 #
激活函数在神经元中非常重要的。为了增强网络的表示能力和学习能力,激活函数需要具备以下几点性质:
连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以直接利用数值优化的方法来学习网络参数;
激活函数及其导函数要尽可能的简单,有利于提高网络计算效率;
激活函数的导函数的值域要在一个合适的区间内,不能太大也不能太小,否则会影响训练的效率和稳定性。
Sigmoid型函数 :Sigmoid型函数是指一类S型曲线函数,为两端饱和函数。常用的Sigmoid型函数有Logistic函数和Tanh函数。
Logistic函数 :
σ ( x ) = 1 1 + exp ( − x ) \sigma(x)=\frac{1}{1+\exp (-x)} σ ( x ) = 1 + exp ( − x ) 1
因为Logistic函数的性质,使用Logistic激活函数的神经元具有两点性质:
其输出直接可以看作概率分布,使得神经网络可以更好地和统计学习模型进行结合;
其可以看作一个软性门(SoftGate),用来控制其他神经元输出信息的数量。
Tanh 函数 :
tanh ( x ) = exp ( x ) − exp ( − x ) exp ( x ) + exp ( − x ) \tanh (x)=\frac{\exp (x)-\exp (-x)}{\exp (x)+\exp (-x)} tanh ( x ) = exp ( x ) + exp ( − x ) exp ( x ) − exp ( − x )
Tanh 函数可以看作放大并平移的 Logistic 函数,其值域是 ( − 1 , 1 ) (-1,1) ( − 1 , 1 ) 。tanh ( x ) = 2 σ ( 2 x ) − 1 \tanh (x)=2 \sigma(2 x)-1 tanh ( x ) = 2 σ ( 2 x ) − 1
下图给出了 Logistic 函数和 Tanh 函数的形状.Tanh 函数的输出是零中心化的(Zero-Centered),而 Logistic 函数的输出恒大于 0 。非零中心化的输出会使得其后一层的神经元的输入发生偏置偏移(Bias Shift),并进一步使得梯度下降的收敛速度变慢。
ReLU函数 :
ReLU(Rectified Linear Unit,修正线性单元)是目前深度神经网络中经常使用的激活函数. ReLU 实际上是一个斜坡(ramp)函数,定义为
ReLU ( x ) = { x x ≥ 0 0 x < 0 = max ( 0 , x ) \begin{aligned}
\operatorname{ReLU}(x) & =\left\{\begin{array}{ll}
x & x \geq 0 \\
0 & x<0
\end{array}\right. \\
& =\max (0, x)
\end{aligned} ReLU ( x ) = { x 0 x ≥ 0 x < 0 = max ( 0 , x )
优点:采用 ReLU 的神经元只需要进行加、乘和比较的操作,计算上更加高效。Sigmoid型激活函数会导致一个非稀疏的神经网络,而 ReLU 却具有很好的稀疏性,大约 50 % 50 \% 50% 的神经元会处于激活状态;在优化方面,相比于 Sigmoid 型函数的两端饱和,ReLU 函数为左饱和函数,且在 x>0 时导数为 1 ,在一定程度上缓解了神经网络的梯度消失问题 ,加速梯度下降的收敛速度.
缺点:ReLU 函数的输出是非零中心化的,给后一层的神经网络引入偏置偏移,会影响梯度下降的效率。此外,ReLU 神经元在训练时比较容易"死亡"。在训练时,如果参数在一次不恰当的更新后,第一个隐藏层中的某个 ReLU 神经元在所有的训练数据上都不能被激活,那么这个神经元自身参数的梯度永远都会是 0 ,在以后的训练过程中永远不能被激活。这种现象称为死亡 ReLU 问题 ,并且也有可能会发生在其他隐藏层。
在实际使用中,为了避免上述情况,有几种 ReLU 的变种也会被广泛使用。
LeakyReLU :
LeakyReLU ( x ) = { x if x > 0 γ x if x ≤ 0 = max ( 0 , x ) + γ min ( 0 , x ) \begin{aligned}
\operatorname{LeakyReLU}(x) & =\left\{\begin{array}{ll}
x & \text { if } x>0 \\
\gamma x & \text { if } x \leq 0
\end{array}\right. \\
& =\max (0, x)+\gamma \min (0, x)
\end{aligned} LeakyReLU ( x ) = { x γ x if x > 0 if x ≤ 0 = max ( 0 , x ) + γ min ( 0 , x )
PReLU :
PReLU i ( x ) = { x if x > 0 γ i x if x ≤ 0 = max ( 0 , x ) + γ i min ( 0 , x ) \begin{aligned}
\operatorname{PReLU}_{i}(x) & =\left\{\begin{array}{ll}
x & \text { if } x>0 \\
\gamma_{i} x & \text { if } x \leq 0
\end{array}\right. \\
& =\max (0, x)+\gamma_{i} \min (0, x)
\end{aligned} PReLU i ( x ) = { x γ i x if x > 0 if x ≤ 0 = max ( 0 , x ) + γ i min ( 0 , x )
ELU :
ELU ( x ) = { x if x > 0 γ ( exp ( x ) − 1 ) if x ≤ 0 = max ( 0 , x ) + min ( 0 , γ ( exp ( x ) − 1 ) ) \begin{aligned}
\operatorname{ELU}(x) & =\left\{\begin{array}{ll}
x & \text { if } x>0 \\
\gamma(\exp (x)-1) & \text { if } x \leq 0
\end{array}\right. \\
& =\max (0, x)+\min (0, \gamma(\exp (x)-1))
\end{aligned} ELU ( x ) = { x γ ( exp ( x ) − 1 ) if x > 0 if x ≤ 0 = max ( 0 , x ) + min ( 0 , γ ( exp ( x ) − 1 ))
Softplus :
Softplus ( x ) = log ( 1 + exp ( x ) ) \operatorname{Softplus}(x)=\log (1+\exp (x)) Softplus ( x ) = log ( 1 + exp ( x ))
激活函数 公式 优点 缺点 常见应用场景 Logistic σ ( x ) = 1 1 + e − x \sigma(x)=\frac{1}{1+e^{-x}} σ ( x ) = 1 + e − x 1 输出范围为 ( 0 , 1 ) (0,1) ( 0 , 1 ) ,可解释为概率;函数平滑、可导;早期神经网络中使用广泛 容易饱和,导致梯度消失;输出非零中心化,可能造成 bias shift,使梯度下降收敛变慢;指数运算相对较慢 二分类输出层;浅层分类器;需要概率解释的场景 Tanh tanh ( x ) = e x − e − x e x + e − x \tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}} tanh ( x ) = e x + e − x e x − e − x 输出范围为 ( − 1 , 1 ) (-1,1) ( − 1 , 1 ) ;零中心化,比 Sigmoid 更适合隐藏层;平滑、可导 仍然是饱和函数,输入绝对值较大时梯度接近 0;深层网络中仍可能梯度消失 早期神经网络隐藏层;RNN 中部分门控或状态计算;希望输出零中心化的场景 ReLU f ( x ) = max ( 0 , x ) f(x)=\max(0,x) f ( x ) = max ( 0 , x ) 计算简单高效;正区间梯度恒为 1,一定程度缓解梯度消失;收敛通常较快;生物学解释较直观 负区间梯度为 0,可能出现死亡 ReLU 问题;输出非零中心化;只能在隐藏层中使用,不适合作为概率输出层 深度神经网络隐藏层默认选择;CNN、MLP 等大多数网络的基础激活函数 Leaky ReLU f ( x ) = max ( 0 , x ) + γ min ( 0 , x ) f(x)=\max(0,x)+\gamma\min(0,x) f ( x ) = max ( 0 , x ) + γ min ( 0 , x ) 负区间保留小梯度,缓解死亡 ReLU;计算仍然简单;比 ReLU 更稳定 需要人为设定 γ \gamma γ ;负区间斜率固定,表达能力有限;实际效果不一定总优于 ReLU 出现死亡 ReLU 时的替代选择;深层网络隐藏层 PReLU f i ( x ) = max ( 0 , x ) + γ i min ( 0 , x ) f_i(x)=\max(0,x)+\gamma_i\min(0,x) f i ( x ) = max ( 0 , x ) + γ i min ( 0 , x ) 负区间斜率 γ i \gamma_i γ i 可学习,比 Leaky ReLU 更灵活;可缓解死亡 ReLU;可能提升模型表达能力 增加额外参数;小数据集上可能增加过拟合风险;实现和调参比 ReLU 稍复杂 深层 CNN;当 ReLU 死亡神经元较多时;需要让模型自动学习负区间斜率的场景 ELU f ( x ) = max ( 0 , x ) + min ( 0 , γ ( e x − 1 ) ) f(x)=\max(0,x)+\min(0,\gamma(e^x-1)) f ( x ) = max ( 0 , x ) + min ( 0 , γ ( e x − 1 )) 负区间输出为负,有助于输出接近零中心化;负区间非零梯度,缓解死亡 ReLU;函数较平滑 包含指数运算,计算成本高于 ReLU;需要设置超参数 γ \gamma γ ;负区间可能饱和 深层网络隐藏层;希望缓解 ReLU 非零中心化和死亡 ReLU 的场景 SoftPlus f ( x ) = log ( 1 + e x ) f(x)=\log(1+e^x) f ( x ) = log ( 1 + e x ) ReLU 的平滑近似;处处可导;导数为 Sigmoid,即 f ′ ( x ) = 1 1 + e − x f'(x)=\frac{1}{1+e^{-x}} f ′ ( x ) = 1 + e − x 1 计算比 ReLU 慢;负区间容易接近 0,仍可能有较小梯度;实际中常被 ReLU 替代 需要平滑激活函数的场景;理论分析;部分概率模型或需要正值输出的结构 Swish f ( x ) = x σ ( β x ) f(x)=x\sigma(\beta x) f ( x ) = x σ ( β x ) 自门控激活函数;非单调性可能增强表达能力;当门接近 1 时输出近似 x x x ,门接近 0 时输出近似 0;β \beta β 可固定或可学习 计算比 ReLU 复杂;包含 Sigmoid;超参数或可学习参数增加复杂度 深层网络隐藏层;需要替代 ReLU 的高性能模型;部分 CNN 和自动搜索得到的网络结构 GELU G E L U ( x ) = x P ( X ≤ x ) GELU(x)=xP(X\le x) GE LU ( x ) = x P ( X ≤ x ) ,常用近似:G E L U ( x ) ≈ 0.5 x ( 1 + tanh ( 2 π ( x + 0.044715 x 3 ) ) ) GELU(x)\approx0.5x\left(1+\tanh\left(\sqrt{\frac{2}{\pi}}(x+0.044715x^3)\right)\right) GE LU ( x ) ≈ 0.5 x ( 1 + tanh ( π 2 ( x + 0.044715 x 3 ) ) ) ,或 G E L U ( x ) ≈ x σ ( 1.702 x ) GELU(x)\approx x\sigma(1.702x) GE LU ( x ) ≈ x σ ( 1.702 x ) 平滑;负区间保留非零梯度;相比 ReLU 更柔和地根据输入大小进行门控;在 Transformer 类模型中表现好 计算复杂度高于 ReLU;公式较复杂;不如 ReLU 简单直观 Transformer、BERT、GPT 等模型中的隐藏层激活函数;现代深度学习模型
四、前馈神经网络 #
到目前为止,研究者已经发明了各种各样的神经网络结构。目前常用的神经网络结构有以下三种:
前馈网络中各个神经元按接收信息的先后分为不同的神经层。每一层中的神经元接收前一层神经元的输出,并输出到下一层神经元。整个网络中的信息是朝一个方向传播,没有反向的信息传播,可以用一个有向无环路图表示。前馈网络包括全连接前馈网络和卷积神经网络等。
记忆网络,也称为反馈网络,网络中的神经元不但可以接收其他神经元的信息,也可以接收自己的历史信息。和前馈网络相比,记忆网络中的神经元具有记忆功能,在不同的时刻具有不同的状态。记忆神经网络中的信息传播可以是单向或双向传递,因此可用一个有向循环图或无向图来表示。记忆网络包括循环神经网络、Hopfield网络、玻尔兹曼机、受限玻尔兹曼机等。
图网络是定义在图结构数据上的神经网络。图中每个节点都由一个或一组神经元构成。节点之间的连接可以是有向的,也可以是无向的。每个节点可以收到来自相邻节点或自身的信息。
1、网络结构 #
前馈神经网络(Feedforward Neural Network,FNN)是最早发明的简单人工神经网络.前馈神经网络也经常称为多层感知器(Multi-LayerPerceptron,MLP)。在前馈神经网络中,各神经元分别属于不同的层.每一层的神经元可以接收前一层神经元的信号,并产生信号输出到下一层。第0层称为输入层,最后一层称为输出层,其他中间层称为隐藏层。整个网络中无反馈,信号从输入层向输出层单向传播,可用一个有向无环图表示。
符号 含义 L L L 网络层数 M l M_l M l 第 l l l 层神经元个数 f l ( ⋅ ) f_l(\cdot) f l ( ⋅ ) 第 l l l 层激活函数 W ( l ) W^{(l)} W ( l ) 第 l − 1 l-1 l − 1 层到第 l l l 层权重矩阵 b ( l ) b^{(l)} b ( l ) 第 l − 1 l-1 l − 1 层到第 l l l 层偏置 z ( l ) z^{(l)} z ( l ) 第 l l l 层净输入 a ( l ) a^{(l)} a ( l ) 第 l l l 层输出 / 激活值 令 a ( 0 ) = x \boldsymbol{a}^{(0)}=\boldsymbol{x} a ( 0 ) = x , 前馈神经网络通过不断迭代下面公式进行信息传播:
z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) , a ( l ) = f l ( z ( l ) ) . \begin{array}{l}
\boldsymbol{z}^{(l)}=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)}, \\
\boldsymbol{a}^{(l)}=f_{l}\left(\boldsymbol{z}^{(l)}\right) .
\end{array} z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) , a ( l ) = f l ( z ( l ) ) .
首先根据第 l − 1 l-1 l − 1 层神经元的活性值 a ( l − 1 ) \boldsymbol{a}^{(l-1)} a ( l − 1 ) 计算出第 l l l 层神经元的净活性值 z ( l ) \boldsymbol{z}^{(l)} z ( l ) ,然后经过一个激活函数得到第 l l l 层神经元的活性值。因此,我们也可以把每个神经层看作一个仿射变换(Affine Transformation)和一个非线性变换。
这样,前馈神经网络可以通过逐层的信息传递,得到网络最后的输出 a ( L ) \boldsymbol{a}^{(L)} a ( L ) 。整个网络可以看作一个复合函数 ϕ ( x ; W , b ) \phi(\boldsymbol{x} ; \boldsymbol{W}, \boldsymbol{b}) ϕ ( x ; W , b ) ,将向量 x \boldsymbol{x} x 作为第1层的输入 a ( 0 ) \boldsymbol{a}^{(0)} a ( 0 ) ,将第 L 层的输出 a ( L ) \boldsymbol{a}^{(L)} a ( L ) 作为整个函数的输出。
x = a ( 0 ) → z ( 1 ) → a ( 1 ) → z ( 2 ) → ⋯ → a ( L − 1 ) → z ( L ) → a ( L ) = ϕ ( x ; W , b ) , \boldsymbol{x}=\boldsymbol{a}^{(0)} \rightarrow \boldsymbol{z}^{(1)} \rightarrow \boldsymbol{a}^{(1)} \rightarrow \boldsymbol{z}^{(2)} \rightarrow \cdots \rightarrow \boldsymbol{a}^{(L-1)} \rightarrow \boldsymbol{z}^{(L)} \rightarrow \boldsymbol{a}^{(L)}=\phi(\boldsymbol{x} ; \boldsymbol{W}, \boldsymbol{b}), x = a ( 0 ) → z ( 1 ) → a ( 1 ) → z ( 2 ) → ⋯ → a ( L − 1 ) → z ( L ) → a ( L ) = ϕ ( x ; W , b ) ,
其中 W \boldsymbol{W} W ,b \boldsymbol{b} b 表示网络中所有层的连接权重和偏置。
前馈神经网络具有很强的拟合能力,常见的连续非线性函数都可以用前馈神经网络来近似。根据通用近似定理 ,对于具有线性输出层和至少一个满足“挤压”性质激活函数的隐藏层组成的前馈神经网络,只要隐藏层神经元数量足够,它可以以任意精度逼近定义在有界闭集上的任意连续函数。
2、FNN在机器学习中的作用 #
根据通用近似定理,神经网络在某种程度上可以作为一个"万能"函数来使用,可以用来进行复杂的特征转换,或逼近一个复杂的条件分布。
在机器学习中,输入样本的特征对分类器的影响很大。以监督学习为例,好的特征可以极大提高分类器的性能。因此,要取得好的分类效果,需要将样本的原始特征向量 x \boldsymbol{x} x 转换到更有效的特征向量 ϕ ( x ) \boldsymbol{\phi}(\boldsymbol{x}) ϕ ( x ) ,这个过程叫作特征抽取 。
多层前馈神经网络可以看作一个非线性复合函数 ϕ : R D → R D ′ \phi: \mathbb{R}^{D} \rightarrow \mathbb{R}^{D^{\prime}} ϕ : R D → R D ′ ,将输入 x ∈ R D \boldsymbol{x} \in \mathbb{R}^{D} x ∈ R D 映射到输出 ϕ ( x ) ∈ R D ′ \phi(\boldsymbol{x}) \in \mathbb{R}^{D^{\prime}} ϕ ( x ) ∈ R D ′ 。因此,多层前馈神经网络也可以看成是一种特征转换方法 ,其输出 ϕ ( x ) \phi(\boldsymbol{x}) ϕ ( x ) 作为分类器的输入进行分类。
五、参数学习 #
1、参数优化 #
如果采用交叉熵损失函数,对于样本 ( x , y ) (\boldsymbol{x}, y) ( x , y ) ,其损失函数为
L ( y , y ^ ) = − y ⊤ log y ^ \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})=-\boldsymbol{y}^{\top} \log \hat{\boldsymbol{y}} L ( y , y ^ ) = − y ⊤ log y ^
其中 y ∈ { 0 , 1 } C \boldsymbol{y} \in\{0,1\}^{C} y ∈ { 0 , 1 } C 为标签 y y y 对应的 one-hot 向量表示。
给定训练集为 D = { ( x ( n ) , y ( n ) ) } n = 1 N \mathcal{D}=\left\{\left(\boldsymbol{x}^{(n)}, y^{(n)}\right)\right\}_{n=1}^{N} D = { ( x ( n ) , y ( n ) ) } n = 1 N ,将每个样本 x ( n ) \boldsymbol{x}^{(n)} x ( n ) 输入给前馈神经网络,得到网络输出为 y ^ ( n ) \hat{\boldsymbol{y}}^{(n)} y ^ ( n ) ,其在数据集 D \mathcal{D} D 上的结构化风险函数(包括平均损失函数和正则化项)为
R ( W , b ) = 1 N ∑ n = 1 N L ( y ( n ) , y ^ ( n ) ) + 1 2 λ ∥ W ∥ F 2 \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})=\frac{1}{N} \sum_{n=1}^{N} \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)+\frac{1}{2} \lambda\|\boldsymbol{W}\|_{F}^{2} R ( W , b ) = N 1 n = 1 ∑ N L ( y ( n ) , y ^ ( n ) ) + 2 1 λ ∥ W ∥ F 2
其中 W \boldsymbol{W} W 和 b \boldsymbol{b} b 分别表示网络中所有的权重矩阵和偏置向量; ∥ W ∥ F 2 \|\boldsymbol{W}\|_{F}^{2} ∥ W ∥ F 2 是正则化项,用来防止过拟合; λ > 0 \lambda>0 λ > 0 为超参数. λ \lambda λ 越大, W \boldsymbol{W} W 越接近于 0 .这里的 ∥ W ∥ F 2 \|\boldsymbol{W}\|_{F}^{2} ∥ W ∥ F 2 一般使用 Frobenius 范数:∥ W ∥ F 2 = ∑ l = 1 L ∑ i = 1 M l ∑ j = 1 M l − 1 ( w i j ( l ) ) 2 \|\boldsymbol{W}\|_{F}^{2}=\sum_{l=1}^{L} \sum_{i=1}^{M_{l}} \sum_{j=1}^{M_{l-1}}\left(w_{i j}^{(l)}\right)^{2} ∥ W ∥ F 2 = ∑ l = 1 L ∑ i = 1 M l ∑ j = 1 M l − 1 ( w ij ( l ) ) 2
有了学习准则和训练样本,网络参数可以通过梯度下降法来进行学习.在梯度下降方法的每次迭代中,第 l l l 层的参数 W ( l ) \boldsymbol{W}^{(l)} W ( l ) 和 b ( l ) \boldsymbol{b}^{(l)} b ( l ) 参数更新方式为
W ( l ) ← W ( l ) − α ∂ R ( W , b ) ∂ W ( l ) = W ( l ) − α ( 1 N ∑ n = 1 N ( ∂ L ( y ( n ) , y ^ ( n ) ) ∂ W ( l ) ) + λ W ( l ) ) , b ( l ) ← b ( l ) − α ∂ R ( W , b ) ∂ b ( l ) = b ( l ) − α ( 1 N ∑ n = 1 N ∂ L ( y ( n ) , y ^ ( n ) ) ∂ b ( l ) ) , \begin{aligned}
\boldsymbol{W}^{(l)} & \leftarrow \boldsymbol{W}^{(l)}-\alpha \frac{\partial \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})}{\partial \boldsymbol{W}^{(l)}} \\
& =\boldsymbol{W}^{(l)}-\alpha\left(\frac{1}{N} \sum_{n=1}^{N}\left(\frac{\partial \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)}{\partial \boldsymbol{W}^{(l)}}\right)+\lambda \boldsymbol{W}^{(l)}\right), \\
\boldsymbol{b}^{(l)} & \leftarrow \boldsymbol{b}^{(l)}-\alpha \frac{\partial \mathcal{R}(\boldsymbol{W}, \boldsymbol{b})}{\partial \boldsymbol{b}^{(l)}} \\
& =\boldsymbol{b}^{(l)}-\alpha\left(\frac{1}{N} \sum_{n=1}^{N} \frac{\partial \mathcal{L}\left(\boldsymbol{y}^{(n)}, \hat{\boldsymbol{y}}^{(n)}\right)}{\partial \boldsymbol{b}^{(l)}}\right),
\end{aligned} W ( l ) b ( l ) ← W ( l ) − α ∂ W ( l ) ∂ R ( W , b ) = W ( l ) − α N 1 n = 1 ∑ N ∂ W ( l ) ∂ L ( y ( n ) , y ^ ( n ) ) + λ W ( l ) , ← b ( l ) − α ∂ b ( l ) ∂ R ( W , b ) = b ( l ) − α N 1 n = 1 ∑ N ∂ b ( l ) ∂ L ( y ( n ) , y ^ ( n ) ) ,
其中 α \alpha α 为学习率。梯度下降法需要计算损失函数对参数的偏导数,如果通过链式法则逐一对每个参数进行求偏导比较低效。在神经网络的训练中经常使用反向传播算法来高效地计算梯度。
2、反向传播算法 #
反向传播是一种通过递归链式法则 计算表达式梯度的方法。
假设采用随机梯度下降进行神经网络参数学习,给定一个样本 ( x , y ) (\boldsymbol{x}, \boldsymbol{y}) ( x , y ) ,将其输入到神经网络模型中,得到网络输出为 y ^ \hat{\boldsymbol{y}} y ^ 。假设损失函数为 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L ( y , y ^ ) ,要进行参数学习就需要计算损失函数关于每个参数的导数。
不失一般性,对第 l l l 层中的参数 W ( l ) \boldsymbol{W}^{(l)} W ( l ) 和 b ( l ) \boldsymbol{b}^{(l)} b ( l ) 计算偏导数。因为 ∂ L ( y , y ^ ) ∂ W ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{W}^{(l)}} ∂ W ( l ) ∂ L ( y , y ^ ) 的计算涉及向量对矩阵的微分,十分繁琐,因此我们先计算 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L ( y , y ^ ) 关于参数矩阵中每个元素的偏导数 ∂ L ( y , y ) ∂ w i j ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \boldsymbol{y})}{\partial w_{i j}^{(l)}} ∂ w ij ( l ) ∂ L ( y , y ) 。根据链式法则,
∂ L ( y , y ^ ) ∂ w i j ( l ) = ∂ z ( l ) ∂ w i j ( l ) ∂ L ( y , y ^ ) ∂ z ( l ) , ∂ L ( y , y ^ ) ∂ b ( l ) = ∂ z ( l ) ∂ b ( l ) ∂ L ( y , y ^ ) ∂ z ( l ) . \begin{aligned}
\frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial w_{i j}^{(l)}} & =\frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}}, \\
\frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{b}^{(l)}} & =\frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} .
\end{aligned} ∂ w ij ( l ) ∂ L ( y , y ^ ) ∂ b ( l ) ∂ L ( y , y ^ ) = ∂ w ij ( l ) ∂ z ( l ) ∂ z ( l ) ∂ L ( y , y ^ ) , = ∂ b ( l ) ∂ z ( l ) ∂ z ( l ) ∂ L ( y , y ^ ) .
公式中的第二项都是目标函数关于第 l l l 层的神经元 z ( l ) z^{(l)} z ( l ) 的偏导数,称为误差项,可以一次计算得到。这样我们只需要计算三个偏导数,分别为 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} ∂ w ij ( l ) ∂ z ( l ) , ∂ z ( l ) ∂ b ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} ∂ b ( l ) ∂ z ( l ) 和 ∂ L ( y , y ^ ) ∂ z ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} ∂ z ( l ) ∂ L ( y , y ^ ) 。
(1)计算偏导数 ∂ z ( l ) ∂ w i j ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} ∂ w ij ( l ) ∂ z ( l ) 因 z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) \boldsymbol{z}^{(l)}=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+\boldsymbol{b}^{(l)} z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) ,偏导数
∂ z ( l ) ∂ w i j ( l ) = [ ∂ z 1 ( l ) ∂ w i j ( l ) , ⋯ , ∂ z i ( l ) ∂ w i j ( l ) , ⋯ , ∂ z M l ( l ) ∂ w i j ( l ) ] = [ 0 , ⋯ , ∂ ( w i : ( l ) a ( l − 1 ) + b i ( l ) ) ∂ w i j ( l ) , ⋯ , 0 ] = [ 0 , ⋯ , a j ( l − 1 ) , ⋯ , 0 ] \begin{aligned}
\frac{\partial \boldsymbol{z}^{(l)}}{\partial w_{i j}^{(l)}} & =\left[\frac{\partial z_{1}^{(l)}}{\partial w_{i j}^{(l)}}, \cdots, \frac{\partial z_{i}^{(l)}}{\partial w_{i j}^{(l)}}, \cdots, \frac{\partial z_{M_{l}}^{(l)}}{\partial w_{i j}^{(l)}}\right] \\
& =\left[0, \cdots, \frac{\partial\left(\boldsymbol{w}_{i:}^{(l)} \boldsymbol{a}^{(l-1)}+b_{i}^{(l)}\right)}{\partial w_{i j}^{(l)}}, \cdots, 0\right] \\
& =\left[0, \cdots, a_{j}^{(l-1)}, \cdots, 0\right] \\
\end{aligned} ∂ w ij ( l ) ∂ z ( l ) = [ ∂ w ij ( l ) ∂ z 1 ( l ) , ⋯ , ∂ w ij ( l ) ∂ z i ( l ) , ⋯ , ∂ w ij ( l ) ∂ z M l ( l ) ] = 0 , ⋯ , ∂ w ij ( l ) ∂ ( w i : ( l ) a ( l − 1 ) + b i ( l ) ) , ⋯ , 0 = [ 0 , ⋯ , a j ( l − 1 ) , ⋯ , 0 ]
其中 w i : ( l ) \boldsymbol{w}_{i:}^{(l)} w i : ( l ) 为权重矩阵 W ( l ) \boldsymbol{W}^{(l)} W ( l ) 的第 i i i 行。
(2)计算偏导数 ∂ z ( l ) ∂ b ( l ) \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}} ∂ b ( l ) ∂ z ( l ) 因为 z ( l ) \boldsymbol{z}^{(l)} z ( l ) 和 b ( l ) \boldsymbol{b}^{(l)} b ( l ) 的函数关系为 z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) \boldsymbol{z}^{(l)}=\boldsymbol{W}^{(l)} \boldsymbol{a}^{(l-1)}+ \boldsymbol{b}^{(l)} z ( l ) = W ( l ) a ( l − 1 ) + b ( l ) ,因此偏导数
∂ z ( l ) ∂ b ( l ) = I M l ∈ R M l × M l \frac{\partial \boldsymbol{z}^{(l)}}{\partial \boldsymbol{b}^{(l)}}=\boldsymbol{I}_{M_{l}} \quad \in \mathbb{R}^{M_{l} \times M_{l}} ∂ b ( l ) ∂ z ( l ) = I M l ∈ R M l × M l
为 M l × M l M_{l} \times M_{l} M l × M l 的单位矩阵。
(3)计算偏导数 ∂ L ( y , y ^ ) ∂ z ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} ∂ z ( l ) ∂ L ( y , y ^ ) ,偏导数 ∂ L ( y , y ^ ) ∂ z ( l ) \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} ∂ z ( l ) ∂ L ( y , y ^ ) 表示第 l l l 层神经元对最终损失的影响,也反映了最终损失对第 l l l 层神经元的敏感程度,因此一般称为第 l l l 层神经元的误差项 ,用 δ ( l ) \delta^{(l)} δ ( l ) 来表示。误差项 δ ( l ) \delta^{(l)} δ ( l ) 也间接反映了不同神经元对网络能力的贡献程度,从而比较好地解决了贡献度分配问题。
根据 z ( l + 1 ) = W ( l + 1 ) a ( l ) + b ( l + 1 ) \boldsymbol{z}^{(l+1)}=\boldsymbol{W}^{(l+1)} \boldsymbol{a}^{(l)}+\boldsymbol{b}^{(l+1)} z ( l + 1 ) = W ( l + 1 ) a ( l ) + b ( l + 1 ) ,有∂ z ( l + 1 ) ∂ a ( l ) = ( W ( l + 1 ) ) ⊤ ∈ R M l × M l + 1 \frac{\partial \boldsymbol{z}^{(l+1)}}{\partial \boldsymbol{a}^{(l)}}=\left(\boldsymbol{W}^{(l+1)}\right)^{\top} \quad \in \mathbb{R}^{M_{l} \times M_{l+1}} ∂ a ( l ) ∂ z ( l + 1 ) = ( W ( l + 1 ) ) ⊤ ∈ R M l × M l + 1
根据 a ( l ) = f l ( z ( l ) ) \boldsymbol{a}^{(l)}=f_{l}\left(\boldsymbol{z}^{(l)}\right) a ( l ) = f l ( z ( l ) ) ,其中 f l ( ⋅ ) f_{l}(\cdot) f l ( ⋅ ) 为按位计算的函数,因此有
∂ a ( l ) ∂ z ( l ) = ∂ f l ( z ( l ) ) ∂ z ( l ) = diag ( f l ′ ( z ( l ) ) ) ∈ R M l × M l . \begin{aligned}
\frac{\partial \boldsymbol{a}^{(l)}}{\partial \boldsymbol{z}^{(l)}} & =\frac{\partial f_{l}\left(\boldsymbol{z}^{(l)}\right)}{\partial \boldsymbol{z}^{(l)}} \\
& =\operatorname{diag}\left(f_{l}^{\prime}\left(\boldsymbol{z}^{(l)}\right)\right) \quad \in \mathbb{R}^{M_{l} \times M_{l}} .
\end{aligned} ∂ z ( l ) ∂ a ( l ) = ∂ z ( l ) ∂ f l ( z ( l ) ) = diag ( f l ′ ( z ( l ) ) ) ∈ R M l × M l .
因此,根据链式法则,第 l l l 层的误差项为
δ ( l ) ≜ ∂ L ( y , y ^ ) ∂ z ( l ) = ∂ a ( l ) ∂ z ( l ) ⋅ ∂ z ( l + 1 ) ∂ a ( l ) ⋅ ∂ L ( y , y ^ ) ∂ z ( l + 1 ) = diag ( f l ′ ( z ( l ) ) ) ⋅ ( W ( l + 1 ) ) ⊤ ⋅ δ ( l + 1 ) = f l ′ ( z ( l ) ) ⊙ ( ( W ( l + 1 ) ) ⊤ δ ( l + 1 ) ) ∈ R M l , \begin{aligned}
\delta^{(l)} & \triangleq \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l)}} \\
& =\frac{\partial \boldsymbol{a}^{(l)}}{\partial \boldsymbol{z}^{(l)}} \cdot \frac{\partial \boldsymbol{z}^{(l+1)}}{\partial \boldsymbol{a}^{(l)}} \cdot \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{z}^{(l+1)}} \\
& =\operatorname{diag}\left(f_{l}^{\prime}\left(\boldsymbol{z}^{(l)}\right)\right) \cdot\left(\boldsymbol{W}^{(l+1)}\right)^{\top} \cdot \delta^{(l+1)} \\
& =f_{l}^{\prime}\left(\boldsymbol{z}^{(l)}\right) \odot\left(\left(\boldsymbol{W}^{(l+1)}\right)^{\top} \delta^{(l+1)}\right) \quad \in \mathbb{R}^{M_{l}},
\end{aligned} δ ( l ) ≜ ∂ z ( l ) ∂ L ( y , y ^ ) = ∂ z ( l ) ∂ a ( l ) ⋅ ∂ a ( l ) ∂ z ( l + 1 ) ⋅ ∂ z ( l + 1 ) ∂ L ( y , y ^ ) = diag ( f l ′ ( z ( l ) ) ) ⋅ ( W ( l + 1 ) ) ⊤ ⋅ δ ( l + 1 ) = f l ′ ( z ( l ) ) ⊙ ( ( W ( l + 1 ) ) ⊤ δ ( l + 1 ) ) ∈ R M l ,
其中 ⊙ \odot ⊙ 是向量的 Hadamard 积运算符,表示每个元素相乘。
可以看出,第 l l l 层的误差项可以通过第 l + 1 l+1 l + 1 层的误差项计算得到,这就是误差的反向传播(BackPropagation,BP)。反向传播算法的含义是:第 l l l 层的一个神经元的误差项(或敏感性)是所有与该神经元相连的第 l + 1 l+1 l + 1 层的神经元的误差项的权重和。然后,再乘上该神经元激活函数的梯度。
最后,我们得到了 L ( y , y ^ ) \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}}) L ( y , y ^ ) 关于第 l l l 层权重 W ( l ) \boldsymbol{W}^{(l)} W ( l ) 的梯度为
∂ L ( y , y ^ ) ∂ W ( l ) = δ ( l ) ( a ( l − 1 ) ) ⊤ ∈ R M l × M l − 1 \frac{\partial \mathcal{L}(\boldsymbol{y}, \hat{\boldsymbol{y}})}{\partial \boldsymbol{W}^{(l)}}=\delta^{(l)}\left(\boldsymbol{a}^{(l-1)}\right)^{\top} \quad \in \mathbb{R}^{M_{l} \times M_{l-1}} ∂ W ( l ) ∂ L ( y , y ^ ) = δ ( l ) ( a ( l − 1 ) ) ⊤ ∈ R M l × M l − 1
使用误差反向传播算法的前馈神经网络训练过程可以分为以下三步:
前馈计算每一层的净输入𝒛(𝑙)和激活值𝒂(𝑙),直到最后一层;
反向传播计算每一层的误差项𝛿(𝑙);
计算每一层参数的偏导数,并更新参数。
3、优化问题 #
神经网络的参数学习比线性模型要更加困难,主要原因有两点:非凸优化问题和梯度消失问题。
神经网络目标函数是非凸的,因此很难用传统凸优化理论完整分析。
由于Sigmoid型函数的饱和性,饱和区的导数更是接近于0。这样,误差经过每一层传递都会不断衰减。当网络层数很深时,梯度就会不停衰减,甚至消失,使得整个网络很难训练。这就是所谓的梯度消失问题(VanishingGradient Problem),也称为梯度弥散问题。 在深度神经网络中,减轻梯度消失问题的方法有很多种。一种简单有效的方式是使用导数比较大的激活函数,比如ReLU等。