一、前馈神经网络
概念:前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数
前馈神经网络(feedforward neural network),也叫作多层感知机(MLP),是典型的深度学习模型。前馈网络的目的是近似某个函数 f^
。例如,对于分类器, y=f^
(x) 将输入 x 映射到一个类别 y 。前馈网络定义了一个映射 y=f(x;t) ,并且学习参数t的值,使它能够得到最佳的函数近似。
1.前馈神经网络介绍
前馈神经网络,也叫作多层感知机MLP,是深度学习模型 ,前馈网络的目的是近似某个函数
。例对于分类器,
将输入映射到一个类别y.前馈网络定义了一个映射
,并且学习参数的值,使它能够得到最佳的函数近似。
2.神经元模型介绍
x1,x2,x3代表输入,
代表权重,b代表偏置,g代表非线性激活函数
z叫做带权输入,a叫做激活值,最神经元的输出。
3.神经网络的结构
前馈神经网络之所以被称为网络,是因为它们通常用许多不同函数复合在一起来表示,这个模型与一个有向无环相关联,而图描述是如何复合在一起的。
我们以下图为例子说明神经网络的结构。神经网络分为输入层,隐藏层和输出层。
前馈网络最前面的层称作输入层,最后一层称作输出层,中间既不是输入也不是输出的层叫做隐藏层。
下图是一个3层的神经网络,
输入层不计入层数
。神经网络的层数称为模型的深度,正是因为这个术语才出现了“深度学习”这个名字。每一层的节点都代表一个神经元(neuron),每层的单元数代表了模型的宽度。
二、感知机相关
1,超平面的定义
令w1,w2,…wn,v都是实数® ,其中至少有一个wi不为零,由所有满足线性方程w1x1+w2x2+…+wn*xn=v
的点X=[x1,x2,…xn]组成的集合,称为空间R的超平面。
从定义可以看出:超平面就是点的集合。集合中的某一点X,与向量w=[w1,w2,…wn]的内积,等于v
特殊地,如果令v等于0,对于训练集中某个点X:
wX=w1x1+w2x2+…+wnxn>0,将X标记为一类
wX=w1x1+w2x2+…+wnxn<0,将X标记为另一类
2,数据集的线性可分
对于数据集T={(X1, y1),(X2, y2)…(XN, yN)},Xi belongs to Rn,yi belongs to {-1, 1},i=1,2,…N
若存在某个超平面S:w*X=0
将数据集中的所有样本点正确地分类,则称数据集T线性可分。
所谓正确地分类,就是:如果w*Xi>0,那么样本点(Xi, yi)中的 yi 等于1
如果w*Xi<0,那么样本点(Xi, yi)中的 yi 等于-1
因此,给定超平面 wX=0,对于数据集 T中任何一个点(Xi, yi),都有yi(wXi)>0,这样T中所有的样本点都被正确地分类了。
如果有某个点(Xi, yi),使得yi(wXi)<0,则称超平面wX对该点分类失败,这个点就是一个误分类的点。
3.感知机模型
f(X)=sign(w*X+b),其中sign是符号函数。
感知机模型,对应着一个超平面w*X+b=0,这个超平面的参数是(w,b),w是超平面的法向量,b是超平面的截距。
我们的目标是,找到一个(w,b),能够将线性可分的数据集T中的所有的样本点正确地分成两类。
如何找到(w,b)?—感知机学习算法做的事
三.激活函数相关
神经元的结构如下图所示,其中f就是激活函数(activation function),它的输入是x的线性组合,然后对其进行某种固定的数学操作后输出到下一个神经元。
常用的神经元激活函数主要有以下几种:
sigmoid
tanh
ReLU
Leaky ReLU
Maxout
ELU
激活函数的用途(为什么要用激活函数)
如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层节点的输入都是上层输出的线性函数,很容易验证,
无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了,那么网络的逼近能力就相当有限
。正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络表达能力就更加强大(不再是输入的线性组合,而是几乎可以逼近任意函数)。
1.sigmoid激活函数
sigmoid非线性函数的数学公式是:
函数图像如下图所示。它输入实数值并将其“挤压”到0到1范围内。更具体地说,很大的负数变成0,很大的正数变成1。
在历史上,sigmoid函数非常常用,这是因为它对于神经元的激活频率有良好的解释:从完全不激活(0)到在求和后的最大频率处的完全饱和(saturated)的激活(1)。然而现在sigmoid函数已经不太受欢迎,实际很少使用了,这是因为它有两个主要缺点:
(1)Sigmoid函数饱和使梯度消失。
sigmoid神经元有一个不好的特性,就是当神经元的激活在接近0或1处时会饱和:在这些区域,梯度几乎为0。回忆一下,在反向传播的时候,这个(局部)梯度将会与整个损失函数关于该门单元输出的梯度相乘。因此,如果局部梯度非常小,那么相乘的结果也会接近零,这会有效地“杀死”梯度,几乎就有没有信号通过神经元传到权重再到数据了。还有,为了防止饱和,必须对于权重矩阵初始化特别留意。比如,如果初始化权重过大,那么大多数神经元将会饱和,导致网络就几乎不学习了。
(2)Sigmoid函数的输出不是零中心的。
这个性质并不是我们想要的,因为在神经网络后面层中的神经元得到的数据将不是零中心的。这一情况将影响梯度下降的运作,因为如果输入神经元的数据总是正数,那么关于的梯度在反向传播的过程中,将会要么全部是正数,要么全部是负数(具体依整个表达式而定)。这将会导致梯度下降权重更新时出现z字型的下降。然而,可以看到整个批量的数据的梯度被加起来后,对于权重的最终更新将会有不同的正负,这样就从一定程度上减轻了这个问题。因此,该问题相对于上面的神经元饱和问题来说只是个小麻烦,没有那么严重。
2.Tanh激活函数
对上述sigmoid函数的缺点进行修正得到tanh激活函数。
具体表达式为:y=(ex−e−x)/(ex+e−x)
数学图像如下图所示。
它将实数值压缩到[-1,1]之间。和sigmoid神经元一样,它也存在饱
和问题,但是和sigmoid神经元不同的是,它的输出是零中心的。因此,在实际操作中,tanh非线性函数比sigmoid非线性函数更受欢迎。注意tanh神经元是一个简单放大的sigmoid神经元,具体说来就是:
但不足的是,tanh函数仍未解决梯度消失问题。
3.ReLU激活函数
ReLu函数的全称为Rectified Linear Units,函数表达式为y=max(0,x)。数学图像如下图所示。
ReLU在今年非常流行。
优点:相较于sigmoid和tanh函数,ReLU对于随机梯度下降的收敛有巨大的加速作用。据称这是由它的线性,非饱和的公式导致的。
优点:sigmoid和tanh神经元含有指数运算等耗费计算资源的操作,而ReLU可以简单地通过对一个矩阵进行阈值计算得到。
缺点:在训练的时候,ReLU单元比较脆弱并且可能“死掉”。举例来说,当一个很大的梯度流过ReLU的神经元的时候,可能会导致梯度更新到一种特别的状态,在这种状态下神经元将无法被其他任何数据点再次激活。如果这种情况发生,那么从此所以流过这个神经元的梯度将都变成0。也就是说,这个ReLU单元在训练中将不可逆转的死亡,因为这导致了数据多样化的丢失。例如,如果学习率设置得太高,可能会发现网络中40%的神经元都会死掉(在整个训练集中这些神经元都不会被激活)。通过合理设置学习率,这种情况的发生概率会降低。
4.Leaky ReLU
Leaky ReLU是为解决“ReLU死亡”问题的尝试。ReLU中当x<0时,函数值为0。而Leaky ReLU则是给
出一个很小的负数梯度值,比如0.01。其函数表达式为:
其中α为一个很小的常量。
5.Maxout激活函数
Maxout是对ReLU和leaky ReLU的一般化归纳,它的数学表达式为:
这样Maxout神经元就拥有ReLU单元的所有优点(线性操作和不饱和),而没有它的缺点(死亡的ReLU单元)。然而和ReLU对比,它每个神经元的参数数量增加了一倍,这就导致整体参数的数量激增。
6.ELU激活函数
ELU函数的全称是EXPONENTIAL LINEAR UNITS,其数学表示式如下:
其中α是一个可调整的参数,它控制着ELU负值部分在何时饱和。
在论文(FAST AND ACCURATE DEEP NETWORK LEARNING BY EXPONENTIAL LINEAR UNITS (ELUS))中给出四种激活函数(ELU,LReLU,ReLU,SReLU)比较图如下
ELU通过在正值区间取输入x本身减轻了梯度弥散问题(x>0区间导数处处为1),这一点特性这四种激活函数都具备。四者当中只有ReLU的输出值没有负值,所以输出的均值会大于0,当激活值的均值非0时,就会对下一层造成一个bias,如果激活值之间不会相互抵消(即均值非0),会导致下一层的激活单元有bias shift。如此叠加,单元越多时,bias shift就会越大。相比ReLU,ELU可以取到负值,这让单元激活均值可以更接近0,类似于Batch Normalization的效果但是只需要更低的计算复杂度。虽然LReLU和PReLU都也有负值,但是它们不保证在不激活状态下(就是在输入为负的状态下)对噪声鲁棒。反观ELU在输入取较小值时具有软饱和的特性,提升了对噪声的鲁棒性。
简而言之,ELU具有以下的优点:
1、将前面单元输入的激活值均值控制在0
2、让激活函数的负值部分也可以被使用了(这意思应该是之前的激活函数,负值部分几乎不携带信息,特别是ReLU)
小结
总结了那么多常用的激活函数,那么到底在实际应用中该选择哪一个呢?
用ReLU非线性函数。注意设置好学习率,或许可以监控你的网络中死亡的神经元占的比例。如果单元死亡问题困扰你,就试试Leaky ReLU或者Maxout,不要再用sigmoid了。也可以试试tanh,但是其效果应该不如ReLU或者Maxout。总有一款适合你!
四.正则化相关
1.概念
正则化定义为“对学习算法的修改——旨在减少泛化误差而不是训练误差”。
目前有许多正则化策略。 有些策略向机器学习模型添加限制参数值的额外约束。 有些策略向目标函数增加额外项来对参数值进行软约束。 有时侯,这些约束和惩罚被设计为编码特定类型的先验知识; 其他时候,这些约束和惩罚被设计为偏好简单模型,以便提高泛化能力。 有时,惩罚和约束对于确定欠定的问题是必要的。 其他形式的正则化,如被称为集成的方法,则结合多个假说来解释训练数据。
2.参数范数惩罚
在神经网络中,参数包括每一层仿射变换的权重和偏置,我们通常只对权重做惩罚而不对偏置做正则惩罚。 精确拟合偏置所需的数据通常比拟合权重少得多。 每个权重会指定两个变量如何相互作用。 我们需要在各种条件下观察这两个变量才能良好地拟合权重。 而每个偏置仅控制一个单变量。 这意味着,我们不对其进行正则化也不会导致太大的方差。 另外,正则化偏置参数可能会导致明显的欠拟合。
2.1 L2参数正则化
目标函数:
L2参数正则化效应示意图:
说明:只有在显著减小目标函数方向上的参数会保留得相对完好。 在无助于目标函数减小的方向上改变参数不会显著增加梯度。 这种不重要方向对应的分量会在训练过程中因正则化而衰减掉。
2.2 L1参数正则化
形式地,对模型参数ww的L1L1正则化被定义为:
Ω(θ)=||w||1=∑i|wi|,
即各个参数的绝对值之和正则化。
相比L2正则化,L1正则化会产生更稀疏的解。 此处稀疏性指的是最优值中的一些参数为0。 L2正则化不会使参数变得稀疏,而L1正则化有可能通过足够大的αα实现稀疏。
由L1正则化导出的稀疏性质已经被广泛地用于特征选择机制。 特征选择从可用的特征子集选择出有意义的特征,化简机器学习问题。 著名的LASSO(Least Absolute Shrinkage and Selection Operator)模型将L1L1惩罚和线性模型结合,并使用最小二乘代价函数。 L1惩罚使部分子集的权重为零,表明相应的特征可以被安全地忽略。
3.作为约束的范数惩罚
这和最小化J̃ 的正则化训练问题是完全一样的。 因此,我们可以把参数范数惩罚看作对权重强加的约束。 如果Ω是L2范数,那么权重就是被约束在一个L2球中。 如果Ω是L1范数,那么权重就是被约束在一个L1范数限制的区域中。 通常我们不知道权重衰减系数α约束的区域大小,因为α的值不直接告诉我们kk的值。 原则上我们可以解得k,但k和α∗之间的关系取决于J的形式。 虽然我们不知道约束区域的确切大小,但我们可以通过增加或者减小αα来大致扩大或收缩约束区域。 较大的α,将得到一个较小的约束区域。
有时候,我们希望使用显式的限制,而不是惩罚。 我们可以修改下降算法(如随机梯度下降算法),使其先计算J(θ)的下降步长,然后将θ投影到满足Ω(θ)<kΩ(θ)<k的最近点。 如果我们知道什么样的kk是合适的,而不想花时间寻找对应于此k处的α值,这会非常有用。原因如下:
a.惩罚可能会导致目标函数非凸而使算法陷入局部极小(对应于小的θ)。
b.当使用较高的学习率时,很可能进入正反馈,即大的权重诱导大梯度,然后使得权重获得较大更新。 如果这些更新持续增加权重的大小,θ就会迅速增大,直到离原点很远而发生溢出。 重投影的显式约束可以防止这种反馈环引起权重无限制地持续增加。 建议结合使用约束和高学习速率,这样能更快地探索参数空间,并保持一定的稳定性。
4.数据集增强
让机器学习模型泛化得更好的最好办法是使用更多的数据进行训练。 当然,在实践中,我们拥有的数据量是很有限的。 解决这个问题的一种方法是创建假数据并添加到训练集中。方式包括加入特定噪声(如高斯噪声),做一定的几何变换等等。
另一种正则化模型的噪声使用方式是将其加到权重,这项技术主要用于循环神经网络。 这可以被解释为关于权重的贝叶斯推断的随机实现。 贝叶斯学习过程将权重视为不确定的,并且可以通过概率分布表示这种不确定性。 向权重添加噪声是反映这种不确定性的一种实用的随机方法。
大多数数据集的y标签都有一定错误。 错误的yy不利于最大化logp(y∣x)l。 避免这种情况的一种方法是显式地对标签上的噪声进行建模。 例如,我们可以假设,对于一些小常数ϵ,训练集标记yy是正确的概率是1−ϵ,(以ϵ的概率)任何其他可能的标签也可能是正确的。 这个假设很容易就能解析地与代价函数结合,而不用显式地抽取噪声样本。 例如,标签平滑(label smoothing)通过把确切分类目标从0和1替换成ϵk−1ϵk−1和1−ϵ1−ϵ,正则化具有kk个输出的softmax函数的模型。 标准交叉熵损失可以用在这些非确切目标的输出上。 使用softmax函数和明确目标的最大似然学习可能永远不会收敛—— softmax函数永远无法真正预测0概率或1概率,因此它会继续学习越来越大的权重,使预测更极端。 使用如权重衰减等其他正则化策略能够防止这种情况。 标签平滑的优势是能够防止模型追求确切概率而不影响模型学习正确分类。
5.半监督学习
在半监督学习的框架下,P(x)P(x)产生的未标记样本和P(x,y)P(x,y)中的标记样本都用于估计P(y∣x)P(y∣x)或者根据x预测y。
在深度学习的背景下,半监督学习通常指的是学习一个表示 h=f(x)。 学习表示的目的是使相同类中的样本有类似的表示。 无监督学习可以为如何在表示空间聚集样本提供有用线索。 在输入空间紧密聚集的样本应该被映射到类似的表示。 在许多情况下,新空间上的线性分类器可以达到较好的泛化。 这种方法的一个经典变种是使用主成分分析作为分类前(在投影后的数据上分类)的预处理步骤。
我们可以构建这样一个模型,其中生成模型P(x)或P(x,y)P(x,y)与判别模型P(y∣x)共享参数,而不用分离无监督和监督部分。 我们权衡监督模型准则−logP(y∣x)和无监督或生成模型准则(如−logP(x)或−logP(x,y)。 生成模型准则表达了对监督学习问题解的特殊形式的先验知识,即P(x)P(x)的结构通过某种共享参数的方式连接到P(y∣x)P(y∣x)。 通过控制在总准则中的生成准则,我们可以获得比纯生成或纯判别训练准则更好的权衡。
6.多任务学习
从深度学习的观点看,底层的先验知识如下:能解释数据变化(在与之相关联的不同任务中观察到)的因素中,某些因素是跨两个或更多任务共享的。
7.提前终止
当训练有足够的表示能力甚至会过拟合的大模型时,我们经常观察到,训练误差会随着时间的推移逐渐降低但验证集的误差会再次上升。
这意味着我们只要返回使验证集误差最低的参数设置,就可以获得验证集误差更低的模型(并且因此有希望获得更好的测试误差)。 在每次验证集误差有所改善后,我们存储模型参数的副本。 当训练算法终止时,我们返回这些参数而不是最新的参数。 当验证集上的误差在事先指定的循环次数内没有进一步改善时,算法就会终止。
8. 参数绑定与参数共享
我们经常想要表达的一种常见依赖是某些参数应当彼此接近。 考虑以下情形:我们有两个模型执行相同的分类任务(具有相同类别),但输入分布稍有不同。 形式地,我们有参数为w(A)w(A)的模型AA和参数为w(B)w(B)的模型BB。 这两种模型将输入映射到两个不同但相关的输出:ŷ (A)=f(w(A),x)和ŷ (B)=f(w(B),x)。
我们可以想象,这些任务会足够相似(或许具有相似的输入和输出分布),因此我们认为模型参数应彼此靠近: ∀i,w(A)i∀i,wi(A)应该与w(B)i接近。 我们可以通过正则化利用此信息。 具体来说,我们可以使用以下形式的参数范数惩罚: Ω(w(A),w(B))=w(A)
。 在这里我们使用
L2惩罚,但也可以使用其他选择。
参数范数惩罚是正则化参数使其彼此接近的一种方式,而更流行的方法是使用约束:强迫某些参数相等。 由于我们将各种模型或模型组件解释为共享唯一的一组参数,这种正则化方法通常被称为参数共享。 和正则化参数使其接近(通过范数惩罚)相比,参数共享的一个显著优点是,只有参数(唯一一个集合)的子集需要被存储在内存中。 对于某些特定模型,如卷积神经网络,这可能可以显著减少模型所占用的内存。
9. Bagging和其他集成方法
Bagging是通过结合几个模型降低泛化误差的技术。 主要想法是分别训练几个不同的模型,然后让所有模型表决测试样例的输出。 这是机器学习中常规策略的一个例子,被称为模型平均。 采用这种策略的技术被称为集成方法。
模型平均奏效的原因是不同的模型通常不会在测试集上产生完全相同的误差。
10.Dropout
Dropout通过随机行为训练网络并平均多个随机决定进行预测,实现了一种参数共享的Bagging形式。
在训练中使用Dropout时,我们会使用基于小批量产生较小步长的学习算法,如随机梯度下降等。 我们每次在小批量中加载一个样本,然后随机抽样应用于网络中所有输入和隐藏单元的不同二值掩码。 对于每个单元,掩码是独立采样的。 掩码值为1的采样概率(导致包含一个单元)是训练开始前一个固定的超参数。 它不是模型当前参数值或输入样本的函数。 通常在每一个小批量训练的神经网络中,一个输入单元被包括的概率为0.8,一个隐藏单元被包括的概率为0.5。 然后,我们运行和之前一样的前向传播、反向传播以及学习更新。
更正式地说,假设一个掩码向量uu指定被包括的单元,J(θ,u)是由参数θθ和掩码 uu定义的模型代价。 那么Dropout训练的目标是最小化EuJ(θ,u)。 这个期望包含多达指数级的项,但我们可以通过抽样mumu获得梯度的无偏估计。
Dropout训练与Bagging训练不太一样。 在Bagging的情况下,所有模型都是独立的。 在Dropout的情况下,所有模型共享参数,其中每个模型继承父神经网络参数的不同子集。 参数共享使得在有限可用的内存下表示指数级数量的模型变得可能。 在Bagging的情况下,每一个模型在其相应训练集上训练到收敛。 在Dropout的情况下,通常大部分模型都没有显式地被训练,因为通常父神经网络会很大,以致于到宇宙毁灭都不可能采样完所有的子网络。 取而代之的是,在单个步骤中我们训练一小部分的子网络,参数共享会使得剩余的子网络也能有好的参数设定。 这些是仅有的区别。 除了这些,Dropout与Bagging算法一样。 例如,每个子网络中遇到的训练集确实是有放回采样的原始训练集的一个子集。
Bagging集成必须根据所有成员的累积投票做一个预测。 在这种背景下,我们将这个过程称为推断。 目前为止,我们在介绍Bagging和Dropout时没有要求模型具有明确的概率。 现在,我们假定该模型的作用是输出一个概率分布。 在Bagging的情况下,每个模型ii产生一个概率分布p(i)(y∣x)p(i)(y∣x)。 集成的预测由这些分布的算术平均值给出:
其中p(u)p(u)是训练时采样uu的概率分布。
虽然Dropout在特定模型上每一步的代价是微不足道的,但在一个完整的系统上使用Dropout的代价可能非常显著。 因为Dropout是一个正则化技术,它减少了模型的有效容量。 为了抵消这种影响,我们必须增大模型规模。 不出意外的话,使用Dropout时最佳验证集的误差会低很多,但这是以更大的模型和更多训练算法的迭代次数为代价换来的。 对于非常大的数据集,正则化带来的泛化误差减少得很小。 在这些情况下,使用Dropout和更大模型的计算代价可能超过正则化带来的好处。
11. 对抗训练
我们可以训练分类器为xx和x′x′分配相同的标签。 这鼓励分类器学习一个沿着未标签数据所在流形上任意微小变化都很鲁棒的函数。 驱动这种方法的假设是,不同的类通常位于分离的流形上,并且小扰动不会使数据点从一个类的流形跳到另一个类的流形上。
进行对抗训练的目的是使分类结果对训练样本小邻域更加鲁棒!
12. 切面距离、正切传播和流形正切分类器
正切传播算法训练带有额外惩罚的神经网络分类器,使神经网络的每个输出f(x)f(x)对已知的变化因素是局部不变的。 这些变化因素对应于沿着的相同样本聚集的流形的移动。 这里实现局部不变性的方法是要求∇xf(x)∇xf(x)与已知流形的切向v(i)v(i)正交,或者等价地通过正则化惩罚ΩΩ使ff在xx的v(i)v(i)方向的导数较小:
五、代码(神经网络的前向后向传播)
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
import warnings
warnings.filterwarnings("ignore")
# 数据集加载
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
sess = tf.InteractiveSession()
# 定义算法公式
in_units = 784
h1_units = 300
W1 = tf.Variable(tf.truncated_normal([in_units, h1_units], stddev=0.1))
b1 = tf.Variable(tf.zeros([h1_units]))
W2 = tf.Variable(tf.zeros([h1_units, 10]))
b2 = tf.Variable(tf.zeros([10]))
x = tf.placeholder(tf.float32, [None, in_units])
keep_prob = tf.placeholder(tf.float32)
hidden1 = tf.nn.relu(tf.matmul(x, W1) + b1)
hidden1_drop = tf.nn.dropout(hidden1, keep_prob)
y = tf.nn.softmax(tf.matmul(hidden1_drop, W2) + b2)
# 定义损失函数和选择优化器来优化loss
y_ = tf.placeholder(tf.float32, [None, 10])
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
train_step = tf.train.AdagradOptimizer(0.3).minimize(cross_entropy)
# 训练,加入keep_prop作为计算图输入,并在训练时设为0.75,保留75%的节点
tf.global_variables_initializer().run()
for i in range(3000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run({x: batch_xs, y_: batch_ys, keep_prob: 0.75})
# 对模型进行评测
prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(prediction, tf.float32))
print("acc:", accuracy.eval({x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
六.参考