这节主要来详细说一下神经网络。从神经网络定义到 M-P模型再扩展到 单层感知机、 多层前馈神经网络、再到 深层神经网络。(本文有一些概念省略了,若有写得不清楚的地方,我们一起在微信群里面讨论讨论)。
神经网络的定义
在不同的领域、以及不同人的一些偏好。大家对神经网络的叫法有些许差别。但主要会包括以下几种命名方式:
- 神经网络(Neural Network)
- 人工神经网络(Artificial Neural Network)
- 人工神经系统(Artificial Neural Systems)
- 神经计算机(Neural Computer)
- 自适应系统(Adaptive Systems)
- 自适应网(Adaptive Network)
- 联结主义(Connectionisms)
不同的学科对神经网络的定义也大不相同,比较广泛的一种定义是:由具有适应性的简单单元组成的广泛并行互联的网络,它的组织能够模拟生物神经系统对真实世界物体所作出的反应。
M-P神经元模型
在神经网络中,最基本的信息处理单元就是M-P神经元模型。
一个M-P神经元模型,接收来自其它n nn个神经元传递过来的输入信号。输入信号通过带权重的连接,进行传递,神经元接收到的总输入值将与神经元的阈值进行比较,,如果大于阈值,就会通过激活函数处理产生神经元的输出。到这里,所谓的M-P模型,其本质就是一个广义的线性回归模型。
理想的激活函数是阶跃函数,但阶跃函数具有不可导的性质一般我么采用Sigmoid函数,这一点在经典机器学习系列之【线性模型与广义线性模型】有具体详解。
当M-P神经元模型的激活函数选用Sigmoid函数时,M-P模型其实就是一个逻辑斯蒂回归模型。
单层感知机
所谓单层感知机,就是只拥有一层M-P神经元的神经网络模型。只包含两层神经元,输入层和输出层。输入层接收外界输入信号后,传递给输出层;输出层是一个或者多个M-P神经元,进行激活处理。
给定训练数据集,权重以及阈值θ 可通过学习得到。阈值θ 可看作一个固定输入为− 1 的“哑节点”(dummy node)所对应的连接权重w n + 1 ,这样,权重和阈值的学习就可统一为权重的学习。
其学习规则为:对训练样例( x , y ),若当前感知机的输出为y ^ ,则感知机权重调整如下所示:
上述公式是误差对参数w 求偏导数所得到的。η ∈ ( 0 , 1 ) 称为学习率(learning rate)。从上式可以看出,若预测正确,误差为0,感知器参数将不发生调整。否者将会更具错误的大小进行修正。
对于线性可分问题,感知机最终将会收敛,而对于线性不可分的异或问题,感知机将会发生振荡(fluctuation),w 难以稳定下来,不能求得合适解。例如对下图所示的异或非线性问题,感知机就难以求解。
要解决非线性可分问题,需要考虑使用多层功能神经元。即输入层和输出层之间包含一层隐藏层。隐藏层和输出层神经元都是拥有激活函数的功能神经元。
多层前馈神经网络
当把隐藏层层数扩大之后,神经元之间的连接将会更加复杂。每层神经元与下一层神经元全互连,神经元之间不存在同层连接,也不存在跨层连接,这样的神经网络结构通常称为“多层前馈神经网络”(multi-layer feedforward neural network)。
其中多层指的是,除了输入层和输出层以外,还存在一个或者多个隐含层。前馈指的是:外界信号从输入层经由隐含层到达输出层,不存在信号的逆向传播。
与M-P模型一样,输入层神经元接收外界的输入信号,隐藏层与输出层对信号进行处理加工,最终结果由输出层神经元输出。
神经网络所需要做的事情就是:依据训练给定的样本,来调整神经元之间的“连接权”,以及每个功能神经元的阈值。最终所得到的这个模型,期望对未知样本有一定的泛化能力。
BP求解单隐层前馈网络
我们以单隐层前馈网络为例,对其模型进行求解。由于这里固定了是单隐层前馈神经网络,我们就不对其神经网络结构求解进行讨论,只讨论其参数学习问题。这里我们采用误差反向传播算法(Back Propagation,简称BP算法)来对其模型参数进行求解。神经网络学习就是依据训练数据来调整神经元之间的连接权值,以及每个M-P神经元的阈值。
给定训练集即输入样本由d dd个属性描述,输出是l ll维实值向量。如下图所示:
假设隐藏层神经元个数为q 个。输出层神经元的阈值用θ j 表示。隐层第h 个神经元的阈值用γ h表示。
到这里,我么整个的前馈神经网络的数学模型就已经建立完成了。接下来我们需要依据使误差最小这个优化目标,来求解神经网络参数矩阵。在计算参数矩阵之前,我们先来计算一下神经网络的参数有多少个:输入层到隐藏层的d × q 权值;隐藏层到输出层的q × l 个权值;q 个隐藏层神经元阈值;l 个输出层神经元阈值,总共( d + l + 1 )个参数。
之后我们需要利用BP算法,对这些参数进行更新估计。BP算法基于梯度下降(gradient descent)策略,以目标的负梯度方向对参数进行调整。给定学习率η \etaη,有:
于是可以得到BP算法中关于w h j 的更新公式:
类似这种链式求导法则,我们可以得到:
到这里模型参数的求解大体过程就完成了。
最后做一个总结:基于BP的单隐层前馈神经网络工作流程如下所示:对每个训练样本,先走前向传播,输入传递给输入层、隐藏层、输出层。依据输出层的输出结果计算误差,再将误差反向传播到隐藏层神经元,最后依据隐层神经元的误差来对连接权和阈值进行调整,迭代循环该过程,直到达到设定的终止条件(如设定的迭代次数,或者误差小于某个值)。
其算法伪代码如下图所示:
BP算法所存在的问题
在实际的运用过程中,BP算法还会面临一些实际的问题:
- 结构学习问题
多层前馈神经网络包括输入层、输出层、一个或者多个隐藏层。
在数学原理上,一个包含足够多神经元的隐藏层的前馈神经网络就能以任意精度逼近任意复杂的连续函数。也就是说两层的前馈神经网络就足够逼近任意的连续复杂函数,因此通常选用一个隐含层。
当网络层数确定下来之后,每层设置的神经元个数又为多少呢?通常,输入层依据求解问题的数据维度及数据类型而定。输出层由待分类问题的类别数目所确定的。隐含层神经元个数是一个超参数问题,实际操作过程中依据经验而定。
- 初始化问题
在网络学习之前,连接权重和阈值都初始化为不同的小随机数。不同是为了保证网络可以学习。小随机数是为了防止其值过大,而提前进入饱和状态。初始化参数设置不好的话,网络容易陷入局部最优,若这种情况发生,程序多跑几次,网络重新初始化就可以了。
- 步长设置问题
学习率控制着算法的收敛速度。太大容易振荡,太小收敛速度又过慢。比较好的设置方法是,训练刚开始时,补偿设置较大,随着训练进行,步长逐渐缩小。实际应用过程中,可以采取自适应步长,步长随网络训练变化。
- 权值与阈值的更新问题
标准的BP算法是样例更新,即每处理一个样本就更新权值和阈值。样例更新的缺陷就是:参数更新频繁,不同样例之间的下降梯度方向可能抵消,迭代的次数较多。训练样例的输入顺序会对训练结果有较大的影响,单个处理会对最后更新的样例比较偏爱,而给样例排序是比较困难的一件事情。
采用的办法是周期更新制,即处理完一遍所有的训练样例才更新权值和阈值。但周期更新的累计误差下降到一定程度后,进一步下降会非常缓慢。这个时候样例更新就会比较好。两者折中就变成了Batch更新。
- 过拟合问题
神经网络的过拟合问题表现为:训练误差持续降低,但测试误差却升高。缓解这个问题可以采取提前结束训练和正则化方法。提前结束训练:就是训练误差降低,测试误差升高的时候停止训练;正则化:在误差目标函数中增加描述网络复杂程度的部分,比如连接权值和阈值的平方和,所体现的是大道至简的思想。
深层神经网络
随着计算能力的大幅提高可缓解训练低效性;训练数据的大幅增加则可降低过拟合风险,因此,以深度学习(deep learning)为代表的复杂模型开始受到人们的关注。
典型的深度学习模型就是很深层的神经网络:包含2个以上隐含层的神经网络。
深度伸进网络的模型更加复杂,能够拟合更加复杂的模型,主要是归功于隐藏层神经元数目的增多(模型宽度),和隐藏层层数的增多(模型深度)。增加隐藏层层数更容易使得神经网络模型变复杂,因为隐藏层数目不仅增加了拥有激活函数的神经元数目,还增加了激活函数嵌套的层数。
但是随着隐藏层的增多,BP算法中误差一层一层往前传播会变得越来越困难,导致梯度消失。那如何学习深层神经网络模型呢?目前主要采取两种办法:
- 预训练+微调
在预训练阶段,采用无监督逐层训练,将上一层隐藏层节点的输出作为输入,而本层隐藏层结点的输出作为一下一层隐含层节点的输入。
预训练全部完成后,再对整个网络进行微调训练,一般使用BP算法。
预训练+微调的做法可以视为将大量参数进行分组,对每组先找到局部看起来比较好的设置,然后再基于这些局部较优的结果联合起来进行全局寻优。
- 权共享
权共享就是让一组神经元共享相同的连接权值。卷积神经网络就是典型的权共享网络。CNN复合多个卷积层和采样层对输入信号进行加工,然后在连接层实现与输出目标之间的映射。
深度学习理解
深度学习通过多层处理,逐渐将初始的低层特征表示转化为高层特征表示后,用“简单模型”即可完成复杂的分类学习等任务。由此可将深度学习理解为进行“特征学习”(feature learning) 或“表示学习” (representation learning)。
非深度学习技术用于解决现实任务时,描述样本的特征通常需由人类专家来手工设计,这称为“特征工程” (feature engineering)。众所周知,特征的好坏对模型的泛化性能有至关重要的影响,要人类专家手工设计出好特征并非易事;而特征学习则通过深度学习技术自动产生好特征,这使得机器学习向“全自动数据分析”又前进了一步。
在Python中使用神经网络分类算法
在Scikit-Learn
库中,基于神经网络这一大类的算法模型的相关类库都在sklearn.neural_network
包中,这个包只有三种算法API
。神经网络算法在Scikit-Learn
库中被称为多层感知机(Multi-layer Perceptron
)算法,这里可以简单地认为二者只有叫法上的区别,缩写为MLP
。神经网络算法可以完成多种任务,前面所介绍的用于解决分类问题的神经网络分类算法对应的API
为MLPClassifier
,除此之外,神经网络算法也可以用来解决回归问题,对应的API
为MLPRegressor
。该包还有一种算法,为基于Bernoulli Restricted Boltzmann Machine
模型的神经网络分类算法类BernoulliRBM
。
from sklearn.datasets import load_iris # 导入神经网络模型中的神经网络分类算法 from sklearn.neural_network import MLPClassifier # 载入鸢尾花数据集 X, y = load_iris(return_X_y=True) clf = MLPClassifier().fit(X, y) # 训练模型 print(clf.predict(X)) # 分类预测 print(clf.score(X, y))
我的微信公众号名称:深度学习与先进智能决策
微信公众号ID:MultiAgent1024
公众号介绍:主要研究强化学习、计算机视觉、深度学习、机器学习等相关内容,分享学习过程中的学习笔记和心得!期待您的关注,欢迎一起学习交流进步!