第五章
- [第5章 神经网络](#第5章 神经网络)
-
- [5.1 神经元模型](#5.1 神经元模型)
- [5.2 感知机与多层网络](#5.2 感知机与多层网络)
- [5.3 误差逆传播算法](#5.3 误差逆传播算法)
- [5.4 全局最小与局部最小](#5.4 全局最小与局部最小)
- [5.5 其他常见神经网络](#5.5 其他常见神经网络)
-
- [5.5.1 RBF网络](#5.5.1 RBF网络)
- [5.5.2 ART网络](#5.5.2 ART网络)
- [5.5.3 SOM网络](#5.5.3 SOM网络)
- [5.5.4 级联相关网络](#5.5.4 级联相关网络)
- [5.5.5 Elman网络](#5.5.5 Elman网络)
- [5.5.6 Boltzmann机](#5.5.6 Boltzmann机)
- 小结
- [5.6 深度学习](#5.6 深度学习)
- [5.7 代码](#5.7 代码)
- 章末小结
-
- [1. 神经网络基础](#1. 神经网络基础)
- [2. 神经元的数学模型](#2. 神经元的数学模型)
- [3. 感知机与多层网络](#3. 感知机与多层网络)
- [4. 误差逆传播算法(BackPropagation, BP)](#4. 误差逆传播算法(BackPropagation, BP))
- [5. 其他常见神经网络](#5. 其他常见神经网络)
- [6. 深度学习](#6. 深度学习)
第5章 神经网络
5.1 神经元模型
神经网络:神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应。、
神经网络中最基本的成分是神经元(neuron)模型,即上述定义中的"简单单元"。
在生物神经网络中,每个神经元与其他神经元相连,当它"兴奋"时,就会向相连的神经元发送化学物质,从而改变这些神经元内的电位;如果某神经元的电位超过了一个"阈值" (threshold),那么它就会被激活,然后向其他神经元发送化学物质。这一点也被很好的利用在了人工神经网络里。
目前所用的神经元模型:M-P神经元模型(创始人是McCulloch and Pitts)。如图:
在这个模型中,神经元接收到来自其他n个神经元传递进来的输入信号,这些信号通过带权重的连接进行传递,神经元接受到的总输入值将与神经元的阈值进行比较,然后通过"激活函数"(activation function)处理以产生神经元的输出。
此处式子类似第三章所讲的线性模型,还是很好理解的。
理想中的激活函数是如图所示的阶跃函数,其将输入值映射为输出值"0"或"1",但阶跃函数因为不连续、不光滑等不好的性质,故常用Sigmoid函数作为激活函数。典型的Sigmoid函数如图所示,它把可能在较大范围内变化的输入值挤压到(0,1)的范围输出,故也可以称为"挤压函数"。
这里所讲只是一个神经元模型,而如果很多个神经元模型按一定的层次结构连接起来,就会形成网状结构,于是就得到了人工神经网络。如图:
激活函数是神经网络中非线性变换的关键组成部分,它们使得神经网络能够学习和模拟复杂函数。以下是一些常见激活函数及其适用场景和优缺点的总结:
-
Sigmoid:
- 适用场景:早期的神经网络中常用于二分类问题。
- 优点:能够将输入压缩到0和1之间,输出概率解释性好。
- 缺点 :梯度消失问题,即在输入值非常大或非常小的时候,梯度接近于0,导致权重更新非常缓慢。
-
Tanh (双曲正切):
- 适用场景:与Sigmoid类似,但输出范围在-1到1之间,中心化。
- 优点:输出中心化,有助于数据的处理和收敛。
- 缺点 :同样存在梯度消失问题。
-
ReLU (Rectified Linear Unit):
- 适用场景:现代深度学习中广泛使用,适用于隐藏层。
- 优点:计算简单,训练速度快,能够缓解梯度消失问题。
- 缺点 :存在死亡ReLU问题,即某些神经元可能永远不会激活。
-
Leaky ReLU:
- 适用场景:改进ReLU,用于解决死亡ReLU问题。
- 优点:对于负输入有一个非零的梯度,避免了神经元死亡。
- 缺点 :超参数(斜率)需要调整,以确定负输入的梯度大小。
-
Parametric ReLU (PReLU):
- 适用场景:进一步改进Leaky ReLU,自适应调整负斜率。
- 优点:负斜率是可学习的参数,可以适应不同的数据分布。
- 缺点 :增加了模型的复杂性,需要额外的参数。
-
ELU (Exponential Linear Unit):
- 适用场景:对于有大量负输入的数据集,特别是在输入分布未知时。
- 优点:对于负输入,输出接近于0,有助于缓解神经元死亡问题。
- 缺点 :计算稍微复杂,需要指数运算。
-
Swish:
- 适用场景:自门控的激活函数,可以看作是ReLU的自适应版本。
- 优点:自适应调整激活程度,有助于提高模型的表达能力。
- 缺点 :计算复杂度较高,需要求导和指数运算。
-
Softmax:
- 适用场景:多分类问题的最后一层,将输出转换为概率分布。
- 优点:输出是概率分布,易于解释。
- 缺点 :对于类别数量很多时,计算量较大。
每种激活函数都有其特定的应用场景和优缺点,选择合适的激活函数对于构建有效的神经网络至关重要。通常,ReLU及其变体由于其训练效率和性能而在实践中非常受欢迎。然而,选择哪种激活函数还需要考虑具体的任务和数据特性。
5.2 感知机与多层网络
感知机(perceptron)由两层神经元组成,输入层接受外界输入信号后传递给输出层,输出层是M-P神经元,也叫做"阈值逻辑单元"(threshold logic unit)。
简单的感知机模型 y = f ( ∑ i w i x i − θ ) y=f(\sum_iw_ix_i-\theta) y=f(∑iwixi−θ)如图:
感知机能容易地实现逻辑与、或、非运算注意到 y = f ( ∑ i w i x i − θ ) y=f(\sum_iw_ix_i-\theta) y=f(∑iwixi−θ),假定f是阶跃函数,有
- "与"( x 1 ∧ x 2 x_1 \wedge x_2 x1∧x2),令 w 1 = w 2 = 1 , θ = 2 w_1=w_2=1,\theta=2 w1=w2=1,θ=2,则 y = f ( 1 • x 1 + 1 • x 2 --- 2 ) y=f(1•x_1+1•x_2---2) y=f(1•x1+1•x2---2),仅在 x 1 = x 2 = 1 x_1=x_2=1 x1=x2=1时,y=1;
- "或"( x 1 ∨ x 2 x_1 \vee x_2 x1∨x2),令 w 1 = w 2 = 1 , θ = 0.5 w_1=w_2=1,\theta=0.5 w1=w2=1,θ=0.5,则 y = f ( 1 • x 1 + 1 • x 2 --- 0.5 ) y=f(1•x_1+1•x_2---0.5) y=f(1•x1+1•x2---0.5),仅在 x 1 = 1 x_1=1 x1=1或 x 2 = 1 x_2=1 x2=1时,y=1;
- "非"( ¬ x 1 \neg x_1 ¬x1),令 w 1 = − 0.6 , w 2 = 0 , θ = − 0.5 w_1=-0.6,w_2=0,\theta=-0.5 w1=−0.6,w2=0,θ=−0.5,则 y = f ( − 0.6 • x 1 + 0 • x 2 + 0.5 ) y=f(-0.6•x_1+0•x_2+0.5) y=f(−0.6•x1+0•x2+0.5),当 x 1 = 1 x_1=1 x1=1时,y=0 ; 当 ;当 ;当x_1=0$时,y=1;
一般情况,给定训练数据集,权重 w i ( i = 1 , 2 , ... , n ) w_i(i=1,2,...,n) wi(i=1,2,...,n)以及阈值θ可通过学习得到。阈值θ可看作一个固定输入为-1.0的"哑结点"(dummy node)所对应的连接权重 w n + 1 w_{n+1} wn+1,这样,权重和阈值的学习就可统一为权重的学习。对训练样例(x,y),若当前感知机的输出为 y ^ \hat{y} y^,则感知机权重应当如下调整:
w i ← w i + △ w i , △ w i = η ( y − y ^ ) x i w_i \leftarrow w_i+\bigtriangleup w_i,\bigtriangleup w_i=\eta(y-\hat{y})x_i wi←wi+△wi,△wi=η(y−y^)xi,
其中 η ∈ ( 0 , 1 ) η∈(0,1) η∈(0,1)被称为学习率。
需注意的是,感知机只有输出层神经元进行激活函数处理,即只拥有一层功能神经元(functional neuron),其学习能力非常有限.事实上,上述与、或、非问题都是线性可分(linearly separable)的问题。若两类模式是线性可分的,即存在一个线性超平面能将它们分开,则感知机的学习过程一定会收敛(converge)而求得适当的权向量w。否则感知机学习过程将会发生振荡(fluctuation),w难以稳定下来,不能求得合适解,例如感知机甚至不能解决异或这样简单的非线性可分问题。
要解决非线性可分问题,需考虑使用多层功能神经元。简单的两层感知机就能斛决异或问题,输出层与输入区之间的一层神经元,被称为隐层或隐含层(hidden layer),隐含层和输出层神经元都是拥有激活函数的功能神经元。
更一般的神经网络就是如下图的层级结构,每层神经元与下层神经元全互连,神经元之间不存在同层连接,也不存在跨层连接。这样的网络结构通常称为"多层前馈神经网络"。由于下图所示的神经网络的前一层的每一个神经元都与后一层的所有神经元相连,故把这种神经网络通常称为全连接神经网络。
需要注意,输入层神经元仅仅是接受输入,而隐层与输出层则都包含功能神经元。神经网络的学习过程,就是根据训练数据来调整神经元之间的"连接权" (connection weight) 以及每个功能神经元的阈值。只要包含隐层,就可称为多层网络。
5.3 误差逆传播算法
误差逆传播(Back Propagation)又称为反向传播算法,是迄今为止最成功的神经网络学习算法,适用于绝大多数的场景,非常重要。通常说"BP网络"时,一般指用BP算法训练的多层前馈神经网络。
给定训练集 D = ( x 1 , y 1 ) , ... , ( x m , y m ) , x i ∈ R d , y i ∈ R l D={(x_1,y_1),...,(x_m,y_m)},x_i∈R^d,y_i∈R^l D=(x1,y1),...,(xm,ym),xi∈Rd,yi∈Rl,即输入示例由d个属性描述,输出l维实值向量。如下图:
给出一个拥有d个输入神经元,l个输出神经元,q个隐层神经元的多层前馈网络结构,其中输出层第j个神经元的阈值由 θ j θ_j θj表示,隐层第h个神经元的阈值由 v h v_h vh表示。输入层第i个神经元与隐层第h个神经元之间的权值为 v i h v_{ih} vih,隐层第h个神经元与输出层第j个神经元之间的权值为 w h j w_{hj} whj,记隐层第h个神经元接收到的输入为 α h = ∑ i = 1 d v i h x i \alpha_h=\sum_{i=1}^{d}v_{ih}x_i αh=∑i=1dvihxi,输出层第j个神经元接收到的输入为 β j = ∑ h = 1 q w h j b h \beta_j=\sum_{h=1}^{q}w_{hj}b_h βj=∑h=1qwhjbh,其中 b h b_h bh为隐层第h个神经元的输出,假设激活函数都是sigmoid函数。
对训练例 ( x k , y k ) (x_k,y_k) (xk,yk),假定神经网络的输出为 y ^ k = ( y ^ 1 k , ... , y ^ l k ) \hat{y}k=(\hat{y}1^k,...,\hat{y}l^k) y^k=(y^1k,...,y^lk),即: y ^ j k = f ( β j − θ j ) \hat{y}j^k=f(\beta_j-\theta_j) y^jk=f(βj−θj),则网络在 ( x k , y k ) (x_k,y_k) (xk,yk)的均方误差为: E k = 1 2 ∑ j = 1 l ( y ^ j k − y j k ) 2 E_k=\frac{1}{2}\sum{j=1}^{l}(\hat{y}j^k-y_j^k)^2 Ek=21∑j=1l(y^jk−yjk)2。网络中有 ( d + l + 1 ) q + l (d+l+1)q+l (d+l+1)q+l个参数需确定输入层到隐层的 d x q dxq dxq个权值、隐层到输出层的 q x l qxl qxl个权值、 q q q个隐层神经元的阈值、 l l l个输出层神经元的间值,BP是一个迭代学习算法,在迭代的每一轮中采用广义的感知机学习规则对参数进行更新估计,任意参数v/w的更新估计式: v ← v + △ v ; w ← w + △ w v \leftarrow v + \bigtriangleup v;w \leftarrow w + \bigtriangleup w v←v+△v;w←w+△w,下面以隐层到输出层的权重 w h j w{hj} whj为例来进行推导。BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,对上方的均方误差,给定学习率η,有: △ w h j = − η ∂ E k ∂ w h j \bigtriangleup w{hj} = -\eta \frac{\partial E_k}{\partial w{hj}} △whj=−η∂whj∂Ek,根据链式法则有 ∂ E k ∂ w h j = ∂ E k ∂ y ^ j k ⋅ ∂ y ^ j k ∂ β j ⋅ ∂ β j ∂ w h j \frac{\partial E_k}{\partial w{hj}}=\frac{\partial E_k}{\partial \hat{y}j^k } \cdot \frac{\partial \hat{y}j^k}{\partial \beta_j} \cdot \frac{\partial \beta_j}{\partial w{hj}} ∂whj∂Ek=∂y^jk∂Ek⋅∂βj∂y^jk⋅∂whj∂βj,而 ∂ β j ∂ w h j = b h \frac{\partial \beta_j}{\partial w{hj}}=b_h ∂whj∂βj=bh。sigmoid函数本身导数存在良好形式,即 f ′ ( x ) = f ( x ) ( 1 − f ( x ) ) f'(x)=f(x)(1-f(x)) f′(x)=f(x)(1−f(x)),于是有 g j = − ∂ E k ∂ y ^ j k ⋅ ∂ y ^ j k ∂ β j = − ( y ^ j k − y j k ) f ′ ( β j − θ j ) = y ^ j k ( 1 − y ^ j k ) ( y j k − y ^ j k ) g_j = - \frac{\partial E_k}{\partial \hat{y}j^k } \cdot \frac{\partial \hat{y}j^k}{\partial \beta_j} = -(\hat{y}j^k- y_j^k)f'(\beta_j-\theta_j)=\hat{y}j^k(1-\hat{y}j^k)(y_j^k-\hat{y}j^k) gj=−∂y^jk∂Ek⋅∂βj∂y^jk=−(y^jk−yjk)f′(βj−θj)=y^jk(1−y^jk)(yjk−y^jk),最终得到 △ w h j = η g j b h \bigtriangleup w{hj} = \eta g_j b_h △whj=ηgjbh。类似的利用链式法则求导有 △ θ j = − η g j \bigtriangleup \theta_j=-\eta g_j △θj=−ηgj、 △ v i h = η e h x i \bigtriangleup v{ih}=\eta e_hx_i △vih=ηehxi和 △ γ h = − η e h \bigtriangleup \gamma_h=-\eta e_h △γh=−ηeh。其中 e h = − ∂ E k ∂ b h ⋅ ∂ b h ∂ α h = ∑ j = 1 l w h j g j f ′ ( α h − γ h ) = b h ( 1 − b h ) ∑ j = 1 l w h j g j e_h=-\frac{\partial E_k}{\partial b_h} \cdot \frac{\partial b_h}{\partial \alpha_h}=\sum{j=1}^l w{hj}g_jf'(\alpha_h-\gamma_h)=b_h(1-b_h)\sum{j=1}^lw{hj}g_j eh=−∂bh∂Ek⋅∂αh∂bh=∑j=1lwhjgjf′(αh−γh)=bh(1−bh)∑j=1lwhjgj。
学习率 η ∈ ( 0 , 1 ) \eta \in (0,1) η∈(0,1)控制着算法每一轮迭代中的更新步长,太大则容易振荡,太小则收敛速度又会过慢,因此各权值的学习率可以各自单独设置,未必相等。下图给出了BP算法的基本流程:
对每个训练样例, BP 算法执行以下操作:先将输入示例提供给输入层神经元,然后逐层将信号前传,直到产生输出层的结果;然后计算输出层的误差(第4-5行),再将误差逆向传播至隐层神经元(第6行),最后根据隐层神经元的误差来对权值和阈值进行调整(第7行)。该迭代过程循环进行,直到达到某些停止条件为止,例如训练误差己达到一个很小的值。
上述所讲只是BP算法对 w h j w_{hj} whj的单个样本k误差的处理,而实际上BP算法的目的是要最小化训练集D上所有样本的累积误差: E = 1 m ∑ k = 1 m E k E=\frac{1}{m}\sum_{k=1}^mE_k E=m1∑k=1mEk。根据上方所讲,可以推导出对于累积误差最小化的更新规则,称为累积误差逆传播算法(批量梯度下降)。一般来说,标准BP算法每次更新只针对单个样例(随机梯度下降),参数更新的非常频繁,而且对不同样例进行更新的效果可能出现"抵消"线性,故标准BP算法往往要经过很多轮的迭代。累积BP算法直接针对累积误差最小化,在读取整个训练集一遍后才对参数进行更新,更新频率小很多。但在很多任务重,累积误差下降到一定程度后,进一步下降会很慢,这时标准BP往往有很好的解,尤其在D较大时更明显。当然还有,批梯度下降和随机梯度下降权衡下的产物,小批量梯度下降。
由于BP算法强大的表示能力,BP神经网络经常遭到或拟合,有两种策略来缓解BP网络的过拟合:第一是早停(early stopping):将数据分成训练集和验证集,训练集用来计算梯度、更新连接权和阈值,验证集用来估计误差,若连续多轮训练集误差降低但验证集误差升高,则停止训练,同时返回具有最小验证集误差的连接权和阈值。第二是正则化(regularization):在误差目标函数中增加一个用于描述网络复杂度的部分,例如权值与阈值的平方和。
小结
反向传播算法(Backpropagation)是深度学习中用于训练神经网络的一种标准算法。以下是对反向传播算法的一些关键点的总结:
-
目的:反向传播算法的主要目的是通过计算损失函数关于网络参数的梯度来更新神经网络的权重和偏置。
-
损失函数:算法首先定义一个损失函数(如均方误差、交叉熵等),用于衡量模型预测与实际值之间的差异。
-
前向传播:在训练过程中,首先进行前向传播,即输入数据通过神经网络的各层,直到输出层,得到预测结果。
-
计算梯度:反向传播的核心是计算损失函数相对于每个参数的梯度。这通过链式法则完成,从输出层开始,逆向通过网络的每一层,直到输入层。
-
链式法则:反向传播利用了微积分中的链式法则,将损失函数对输出的梯度分解为对每一层输入的梯度。
-
权重更新:一旦得到了梯度,就可以使用梯度下降或其他优化算法来更新网络的权重和偏置,以减少损失函数的值。
-
迭代过程:这个过程在训练数据集上重复进行多次迭代,直到模型的性能达到满意的水平或达到预设的迭代次数。
-
激活函数的导数:在反向传播过程中,需要计算激活函数的导数,因为它们是梯度计算的一部分。常见的激活函数包括ReLU、Sigmoid和Tanh。
-
正则化:为了防止过拟合,可以在损失函数中加入正则化项,如L1或L2正则化。
-
学习率:学习率是梯度下降算法中的一个关键超参数,它决定了权重更新的步长。
-
动量(Momentum):动量是一种优化技术,可以加速梯度下降过程,特别是在梯度空间中的"山谷"中。
-
自适应学习率算法:如Adam、RMSprop等,这些算法可以自适应地调整每个参数的学习率。
-
批量大小:反向传播可以应用于整个数据集(批量大小=1,即随机梯度下降SGD),也可以应用于小批量数据,这会影响梯度估计的稳定性和内存使用。
-
深度学习框架:现代深度学习框架如TensorFlow、PyTorch等,都内置了反向传播算法的实现,使得开发者可以方便地训练复杂的神经网络模型。
反向传播算法是深度学习的基础,它使得复杂的神经网络模型能够在大量数据上进行有效训练。
5.4 全局最小与局部最小
若用E表示神经网络在训练集上的误差,其显然是关于权值w和阈值θ的函数。此时,神经网络的训练过程可以看做是一个参数寻优过程,即在参数空间中,寻找一组最优参数使得E最小。
有两种最优: "局部最小"(local minimum)和"全局最小"(global minimum)。
直观地看,局部极小解是参数空间中的某个点,其邻域点的误差函数值均不小于该点的函数值;全局最小解则是指参数空间中所有点的误差函数值均不小于该点的误差函数值。两者对应的E(ω;θ) 分别称为误差函数的局部极小值和全局最小值。
显然参数空间内梯度为0的点,只要其误差函数值小于相邻点的函数值,就是局部极小点,一个函数可能有多个局部极小点,但只有一个全局最小值,且全局最小一定是局部最小。
寻找局部最小点与全局最小点的常用方法是梯度下降法
明显,如果误差函数有多个局部最小,则不能保证找到的解一定是全局最小,对这种情形,称参数寻优陷入了局部极小。现实中通常采用以下方法来试图跳出局部极小:
- 以多组不同参数值初始化多个神经网络,按标准方法训练后,取其中误差最小的解作为最终参数。这相当于从多个不同的初始点开始搜索,这样就可能陷入不同的局部极小从中进行选择有可能获得更接近全局最小的结果。
- 使用"模拟退火"(simulated annealing)技术。
- 使用SGD。随机梯度下降由于加入了随机因素,因此即使陷入局部最小点,其计算出的梯度仍然可能不为零,这样就有机会跳出局部极小继续搜索。
遗传算法(genetic algorithms)也常用来训练神经网络以更好的逼近全局最小。注意:上述用于跳出局部最小的技术大多是启发式,理论上缺乏保障。
5.5 其他常见神经网络
5.5.1 RBF网络
RBF(Radial Basis Function, 径向基函数)网络是一种单隐层前馈神经网络,使用径向基函数作为隐层神经元激活函数,输出层则是对隐层神经元输出的线性组合。假定输入d维向量x,输出为实值,则RBF网络可表示为: φ ( x ) = ∑ i = 1 q w i ρ ( x , c i ) \varphi (x) = \sum_{i=1}^qw_i\rho(x,c_i) φ(x)=∑i=1qwiρ(x,ci),其中q为隐层神经元个数, c i c_i ci和 w i w_i wi分别是第i个隐层神经元所对应的中心和权重, ρ ( x , c i ) ρ(x,c_i) ρ(x,ci)是径向基函数,这是某种沿径向对称的标量函数,通常定义为样本x到数据中心 c i c_i ci之间欧式距离的单调函数。常用的高斯径向基函数形如: ρ ( x , c i ) = e − β i ∣ ∣ x − c i ∣ ∣ 2 \rho(x,c_i)=e^{-\beta_i||x-c_i||^2} ρ(x,ci)=e−βi∣∣x−ci∣∣2。通常采用两步过程来训练RBF网络:第一步,确定神经元中心 c i c_i ci,常用的方式包括随机采样、聚类等;第二步使用BP算法,来训练确定参数 w i w_i wi和 β i \beta_i βi。
5.5.2 ART网络
竞争型学习(competitive learning) 是神经网络中一种常用的无监督学习策略,在使用该策略时,网络的输出神经元相互竞争,每一时刻仅有一个竞争获胜的神经元被激活,其他神经元的状态被抑制。这种机制亦称"胜者通吃" (winner-take-all) 原则。
ART(Adaptive Resonance Theory,自适应谐振理论)网络是竞争型学习的代表,该网络由比较层、识别层、识别阈值和重置模块构成。
在接收到比较层的输入信号后识别层神经元之间相互竞争以产生获胜神经元。竞争的最简单方式是计算输入向量与每个识别层神经元所对应的模式类的代表向量之间的距离,距离最小者胜。获胜神经元将向其他识别层神经元发送信号,抑制其激活。若输入向量与获胜神经元所对应的代表向量之间的相似度大于识别阈值,则当前输入样本将被归为该代表向量所属类别,同时,网络连接权将会更新,使得以后在接收到相似输入样本时该模式类会计算出更大的相似度。从而使该获胜神经元有更大可能获胜;若相似度不大于识别阈值,则重置模块将在识别层增设一个新的神经元,其代表向量就设置为当前输入向量。
5.5.3 SOM网络
SOM(Self-Organizing Map, 自组织映射)网络是一种竞争学习型的无监督神经网络,他能将高维输入数据映射到低维空间(通常为二维),同时保持输入数据在高维空间的拓扑结构,即将高维空间中相似的样本点映射到网络输出层中的邻近神经元。如图:
SOM 网络中的输出层神经元以矩阵方式排列在二维空间中,每个神经元都拥有一个权向量,网络在接收输入向量后,将会确定输出层获胜神经元,它决定了该输入向量在低维空间中的位置。SOM 的训练目标就是为每个输出层神经元找到合适的权向量以达到保持拓扑结构的目的。
SOM 的训练过程很简单:在接收到一个训练样本后。每个输出层神经元会计算该样本与自身携带的权向量之间的距离,距离最近的神经元成为竞争获胜者,称为最佳匹配单元(best matching unit)。然后,最佳匹配单元及其邻近神经元的权向量将被调整,以使得这些权向量与当前输入样本的距离缩小。这个过程不断迭代,直至收敛。
5.5.4 级联相关网络
一般的神经网络模型通常假定网络结构是事先固定的,训练的目的是利用训练样本来确定合适的连接权、阈值等参数。与此不同, 结构自适应网络则将网络结构也当作学习的目标之一,并希望能在训练过程中找到最符合数据特点的网络结构。
级联相关(Cascade-Correlation)网络就是结构自适应网络的重要代表。
两个主要成分:"级联"和"相关"。级联指建立层次连接的层级结构。在开始训练时,网络只有输入层和输出层,随着训练进行,新的隐层神经元逐渐加入,从而创建起层级结构。当新的隐层神经元加入时,其输入端连接权值是固定的。相关是指通过最大化新神经元的输出与网络误差之间的相关性来训练相关参数。
5.5.5 Elman网络
与前馈神经网络不同,"递归神经网络"(recurrent neural networks)允许网络结构中出现环形结构,从而可让一些神经元的输出反馈回来作为输入信号。这样的结构与信息反馈过程,使得网络在t时刻的输出状态不仅与t时刻的输入有关,还与t-1时刻的网络状态有关。
Elman网络如图,其隐层神经元的输出被反馈回来,与下一刻的输入层神经元提供的信号一起,作为隐层神经元在下一时刻的输入。
5.5.6 Boltzmann机
神经网络中有一类模型是为网络状态定义一个"能量" (energy) ,能量最小化时网络达到理想状态,而网络的训练就是在最小化这个能量函数。Boltzmann机是一种"基于能量的模型",其神经元为两层:显层和隐层。显层用于表示数据的输入与输出,隐层则被理解为数据的内在表达。Boltzmann机中的神经元都是布尔型的,即只能取0,1两种状态,1表示激活,0表示抑制。
s = { 0 , 1 } n s=\{0,1\}^n s={0,1}n表示n个神经元的状态, w i j w_{ij} wij表示神经元i与j之间的连接权, θ i θ_i θi表示神经元i的阈值,则s所对应的能量定义为: E ( s ) = − ∑ i = 1 n − 1 ∑ j = i + 1 n w i j s i s j − ∑ i = 1 n θ i s i E(s)=-\sum_{i=1}^{n-1}\sum_{j=i+1}^nw_{ij}s_is_j-\sum_{i=1}^n\theta_is_i E(s)=−∑i=1n−1∑j=i+1nwijsisj−∑i=1nθisi。
若网络中的神经元以任意不依赖于输入值的顺序进行更新,则网络最终将达到Boltzman分布(平衡态/平衡分布),此时状态向量s出现的概率仅由其能量与所有可能状态向量的能量确定: P ( s ) = e − E ( s ) ∑ t e − E ( t ) P(s)=\frac{e^{-E(s)}}{\sum_te^{-E(t)}} P(s)=∑te−E(t)e−E(s)。
标准Boltzmann机是一个全连接图,训练网络的复杂度很高,现实中常采用受限Boltzmann机(RBM)。仅保留隐层与显层的链接,并使用对比散度算法来进行训练,如图:
小结
书籍给出的神经网络其实都有点老了,近些年,常用的神经网络其实已经变化了很多。
目前常用的主要是:(比较火的是Transformer及其各种变体)
多层感知器(Multilayer Perceptron, MLP):最基础的前馈神经网络,由输入层、隐藏层和输出层组成。
卷积神经网络(Convolutional Neural Networks, CNN):特别适用于图像识别任务,使用卷积层来提取图像特征。
循环神经网络(Recurrent Neural Networks, RNN):适合处理序列数据,如时间序列分析、语音识别等。
长短期记忆网络(Long Short-Term Memory, LSTM):RNN的一种变体,能够解决传统RNN的梯度消失问题。
门控循环单元(Gated Recurrent Unit, GRU):另一种RNN的变体,与LSTM类似,但结构更简单。
生成对抗网络(Generative Adversarial Networks, GAN):由生成器和判别器组成,用于生成新的数据样本。
自编码器(Autoencoders):用于数据压缩和特征学习,通过编码器和解码器重建输入数据。
深度信念网络(Deep Belief Networks, DBN):由多层RBM(受限玻尔兹曼机)堆叠而成,用于特征学习和分类任务。
残差网络(Residual Networks, ResNet):通过引入残差学习解决了深度网络训练中的梯度消失问题。
Transformer网络:主要用于处理序列数据,特别是在自然语言处理领域,通过自注意力机制处理数据。
每种神经网络都有其特定的应用场景和优势,选择合适的网络类型通常取决于具体的任务需求和数据特性。
5.6 深度学习
理论上来说参数越多的模型复杂度越高、容量"(capacity)越大,这意味着它能完成更复杂的学习任务。但一般情形下,复杂模型的训练效率低易陷入过拟合,因此难以受到人们青眯。而随着云计算、大数据时代的到来,计算能力的大幅提高可缓解训练低效性,训练数据的大幅增加则可降低过拟合风险,因此,以"深度学习"(deeplearning)为代表的复杂模型开始受到人们的关注。
典型的深度学习模型就是很深层的神经网络。显然,对神经网络模型,提高容量的一个简单办法是增加隐层的数目。隐层多了,相应的神经元连接权、阀值等参数就会更多。模型复杂度也可通过单纯增加隐层神经元的数目来实现,前面谈到过,单隐层的多层前馈网络已具有很强大的学习能力;但从增加模型复杂度的角度来看,增加隐层的数目显然比增加隐层神经元的数目更有效,因为增加隐层数不仅增加了拥有激活函数的神经几数目,还增加了激活函数嵌套的层数。然而,多隐层神经网络难以直接用经典算法(例如标准BP算法)进行训练。因为误差在多隐层内逆传播时,往往会"发散"(diverge)而不能收敛到稳定状态。
无监督逐层训练(unsupervised layer-wise training)是多隐层网络训练的有效手段其基本思想是每次训练一层隐结点训练时将上一层隐结点的输出作为输入,而本层隐结点的输出作为下一层隐结点的输入,这称为"预训练"(pre-training);在预训练全部完成后,再对整个网络进行"微调"(finetuning)训练。
事实上,"预训练+微调"的做法可视为将大量参数分组,对每组先找到局部看来比较好的设置,然后再基于这些局部较优的结果联合起米进行全局寻优。这样就在利用了模型大量参数所提供的自由度的同时,有效地节省了训练开销。
另一种节省训练开销的策略是"权共享"(weight sharing),即让一组神经元使用相同的连接权。这个策略在卷积神经网络(Convolutional Neural Network,简称CNN)中发挥了重要作用。以CNN进行手写数字识别任务为例,如图所示
网络输入是一个32x32的手写数字图像,输出是其识别结果,CNN复合多个"卷积层"和"采样层"对输入信号进行加工,然后在连接层实现与输出目标之间的映射每个卷积层都包含多个特征映射(featuremap),每个特征映射是一个由多个神经元构成的"平面",通过一种卷积滤波器捉取输入的一种特征。CNN可用BP算法进行训练,但在训练中,尤论是卷积层还是采样层,其每一组神经元(同一"平面")都是用相同的连接权,从而大幅减少了需要训练的参数数目。
可以从另一个角度来理解深度学习,多隐层堆叠、每层对上一层的输出进行处理的机制,可看作是在对输入信号进行逐层加工,从而把初始的、与输出目标之间联系不太密切的输入表示,转化成与输出目标联系更密切的表示,使得原来仅基于最后一层输出映射难以完成的任务成为可能换言之,通过多层处理,逐渐将初始的"低层"特征表示转化为"高层"特征表示后,用"简单模型"即可完成复杂的分类等学习任务由此可将深度学习理解为进行"特征学习"(featurelearning)或"表示学习"(representationlearning).
以往在机器学习用于现实任务时,描述样本的特征通常需由人类专家来设计,这称为"特征工程"(feature engineering)众所周知,特征的好坏对泛化性能有至关重要的影响,人类专家设计出好特征也并非易事;特征学习则通过机器学习技术自身来产生好特征,这使机器学习向"全自动数据分析"又前进了一步。
5.7 代码
多层感知机回归
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.neural_network import MLPRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.tree import DecisionTreeRegressor
from sklearn.inspection import plot_partial_dependence
diabetes = load_diabetes()
X = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
y = diabetes.target
tree = DecisionTreeRegressor()
mlp = make_pipeline(StandardScaler(),
MLPRegressor(hidden_layer_sizes=(100, 100),
tol=1e-2, max_iter=500, random_state=0))
tree.fit(X, y)
mlp.fit(X, y)
fig, ax = plt.subplots(figsize=(12, 6))
ax.set_title("Decision Tree")
tree_disp = plot_partial_dependence(tree, X, ["age", "bmi"], ax=ax)
fig, ax = plt.subplots(figsize=(12, 6))
ax.set_title("Multi-layer Perceptron")
mlp_disp = plot_partial_dependence(mlp, X, ["age", "bmi"], ax=ax,
line_kw={"c": "red"})
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 10))
tree_disp.plot(ax=ax1)
ax1.set_title("Decision Tree")
mlp_disp.plot(ax=ax2, line_kw={"c": "red"})
ax2.set_title("Multi-layer Perceptron")
多层感知机分类
import warnings
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import MinMaxScaler
from sklearn import datasets
from sklearn.exceptions import ConvergenceWarning
# 不同的学习率时间表和动量参数
params = [{'solver': 'sgd', 'learning_rate': 'constant', 'momentum': 0,
'learning_rate_init': 0.2},
{'solver': 'sgd', 'learning_rate': 'constant', 'momentum': .9,
'nesterovs_momentum': False, 'learning_rate_init': 0.2},
{'solver': 'sgd', 'learning_rate': 'constant', 'momentum': .9,
'nesterovs_momentum': True, 'learning_rate_init': 0.2},
{'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': 0,
'learning_rate_init': 0.2},
{'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': .9,
'nesterovs_momentum': True, 'learning_rate_init': 0.2},
{'solver': 'sgd', 'learning_rate': 'invscaling', 'momentum': .9,
'nesterovs_momentum': False, 'learning_rate_init': 0.2},
{'solver': 'adam', 'learning_rate_init': 0.01}]
labels = ["constant learning-rate", "constant with momentum",
"constant with Nesterov's momentum",
"inv-scaling learning-rate", "inv-scaling with momentum",
"inv-scaling with Nesterov's momentum", "adam"]
plot_args = [{'c': 'red', 'linestyle': '-'},
{'c': 'green', 'linestyle': '-'},
{'c': 'blue', 'linestyle': '-'},
{'c': 'red', 'linestyle': '--'},
{'c': 'green', 'linestyle': '--'},
{'c': 'blue', 'linestyle': '--'},
{'c': 'black', 'linestyle': '-'}]
def plot_on_dataset(X, y, ax, name):
# 对于每个数据集,对每种学习策略进行学习
print("\nlearning on dataset %s" % name)
ax.set_title(name)
X = MinMaxScaler().fit_transform(X)
mlps = []
if name == "digits":
# 数字较大,但收敛很快
max_iter = 15
else:
max_iter = 400
for label, param in zip(labels, params):
print("training: %s" % label)
mlp = MLPClassifier(random_state=0,
max_iter=max_iter, **param)
# 一些参数组合将不会收敛,如在图上看到的那样,因此此处将其忽略
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ConvergenceWarning,
module="sklearn")
mlp.fit(X, y)
mlps.append(mlp)
print("Training set score: %f" % mlp.score(X, y))
print("Training set loss: %f" % mlp.loss_)
for mlp, label, args in zip(mlps, labels, plot_args):
ax.plot(mlp.loss_curve_, label=label, **args)
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 加载/生成一些玩具数据集
iris = datasets.load_iris()
X_digits, y_digits = datasets.load_digits(return_X_y=True)
data_sets = [(iris.data, iris.target),
(X_digits, y_digits),
datasets.make_circles(noise=0.2, factor=0.5, random_state=1),
datasets.make_moons(noise=0.3, random_state=0)]
for ax, data, name in zip(axes.ravel(), data_sets, ['iris', 'digits',
'circles', 'moons']):
plot_on_dataset(*data, ax=ax, name=name)
fig.legend(ax.get_lines(), labels, ncol=3, loc="upper center")
plt.show()
章末小结
本章主要是关于神经网络算法的详细介绍,包括以下几个核心内容:
1. 神经网络基础
- 定义:神经网络是由具有适应性的简单单元组成的广泛并行互连的网络,能够模拟生物神经系统对真实世界物体的交互反应。
- 神经元模型:基本组成单元,模拟生物神经元的兴奋和传递机制。
2. 神经元的数学模型
- M-P神经元模型:由McCulloch和Pitts于1943年提出,包括输入信号、权重、阀值和激活函数。
- 激活函数:如阶跃函数和Sigmoid函数,用于处理神经元的输出。
3. 感知机与多层网络
- 感知机:由输入层和输出层组成,能够实现基本的逻辑运算。
- 多层网络:包含一个或多个隐层,能够解决非线性可分问题。
4. 误差逆传播算法(BackPropagation, BP)
- 目的:训练多层前馈神经网络,通过迭代调整连接权重和神经元的阀值。
- 原理:基于梯度下降策略,利用训练数据的误差来更新网络参数。
5. 其他常见神经网络
- RBF网络:使用径向基函数作为隐层神经元激活函数。
- ART网络:基于竞争型学习的无监督学习策略。
6. 深度学习
- 概念:使用多层(通常指三个以上)隐层的神经网络模型。
- 训练方法:无监督逐层训练和微调,例如深度信念网络(DBN)和卷积神经网络(CNN)。