神经网络学习过程本质就是为了学习数据分布,一旦训练数据与测试数据的分布不同,那么网络的泛化能力也大大降低;另外一方面,一旦每批训练数据的分布各不相同(batch 梯度下降),那么网络就要在每次迭代都去学习适应不同的分布,这样将会大大降低网络的训练速度,这也正是为什么我们需要对数据都要做一个归一化预处理的原因。 BN的作用是通过规范化的手段,将越来越偏的分布拉回到标准化的分布,使得激活函数的输入值落在激活函数对输入比较敏感的区域,从而使梯度变大,加快学习收敛速度,避免梯度消失的问题。
BN算法过程:首先,BN算法在每一次iteration中的每一层输入都进行了归一化,将输入数据的分布归一化为均值为0,方差为1的分布,如下式:
但是这种做法有一种致命的缺陷,就是尽管这样把每层的数据分布都固定了,但是这种分布不一定是前面一层的要学习到的数据分布,这样强行归一化就会破坏掉刚刚学习到的特征,BN算法的第二步就解决了这个缺点。
BN算法在第二步中设置了两个可学习的变量和,然后用这两个变量去学习上一层学习到的数据分布。
添加这种操作的目的就是还原出上一层需要学习的数据分布,这样BN就把原来不固定的数据分布全部转换为固定的数据分布,而这种数据分布恰恰就是要学习到的分布,从而加速了网络的训练。
Dropout说的简单一点就是:我们在前向传播过程中,通过让某个神经元的激活值以一定概率P停止工作,这样可以使模型泛化性更强,因为它不会依赖某些局部特征。在每个训练批次中,通过忽略一定比例的特征检测器(让一半的隐层节点值为0),可以明显地减少过拟合现象。这种方式可以减少特征检测器(隐层节点)间的相互作用,检测器相互作用是指某些检测器依赖其他检测器才能发挥作用。
BN是在batch上,对NHW做归一化,每一层的Batch有相同的数据分布,对小batch效果不好。
LN是在通道上,对CHW做归一化,每一个通道的输入有相同的数据分布,主要对RNN作用明显。
IN在图像像素上,对HW做归一化,用在风格化迁移。
GN将channel分组,然后再做归一化。
BN算法过程: (1)、沿着通道计算每个batch的均值u (2)、沿着通道计算每个batch的方差σ^2 (3)、对x做归一化,x’=(x-u)/开根号(σ^2+ε) (4)、加入缩放和平移变量γ和β ,归一化后的值,y=γx’+β 加入缩放平移变量的原因是: 不一定每次都是标准正态分布,也许需要偏移或者拉伸。保证每一次数据经过归一化后还保留原有学习来的特征,同时又能完成归一化操作,加速训练。 这两个参数是用来学习的参数。
整体公式:
前向传播CODE:
其中x为(N,C * H * W)
mu = np.mean(x,axis=0)
sigma2 = np.var(x,axis=0)
x_hat = (x-mu)/np.sqrt(sigma2+eps)
out = gamma*x_hat + beta
batch normalization存在以下缺点:
(1)、对batchsize的大小比较敏感,由于每次计算均值和方差是在一个batch上,所以如果batchsize太小,则计算的均值、方差不足以代表整个数据分布; (2)、BN实际使用时需要计算并且保存某一层神经网络batch的均值和方差等统计信息,对于对一个固定深度的前向神经网络(DNN,CNN)使用BN,很方便;但对于RNN来说,sequence的长度是不一致的,换句话说RNN的深度不是固定的,不同的time-step需要保存不同的statics特征,可能存在一个特殊sequence比其他sequence长很多,这样training时,计算很麻烦。
与BN不同,LN是针对深度网络的某一层的所有神经元的输入按以下公式进行normalize操作。
BN与LN的区别在于:
(1)、LN中同层神经元输入拥有相同的均值和方差,不同的输入样本有不同的均值和方差; (2)、BN中则针对不同神经元输入计算均值和方差,同一个batch中的输入拥有相同的均值和方差。 (3)、LN用于RNN效果比较明显,但是在CNN上,不如BN。 前向传播代码:
x = x.T # (D, N)
mu = np.mean(x, axis=0) # (N,)
sigma2 = np.var(x, axis=0) # (N,)
x_hat = (x - mu) / np.sqrt(sigma2 + eps)
x_hat = x_hat.T # (N, D)
out = gamma * x_hat + beta
inv_sigma = 1 / np.sqrt(sigma2 + eps)
cache = (x_hat, gamma, mu, inv_sigma)
IN 归一化的维度为[H,W];
GN介于LN和IN之间,其首先将channel分为许多组(group),对每一组做归一化,及先将feature的维度由[N, C, H, W]reshape为[N*G,C//G , H, W],归一化的维度为[C//G , H, W]
事实上,GN的极端情况就是LN和I N,分别对应G等于1和G等于C。
在深度学习中,常用的激活函数主要有:sigmoid函数,tanh函数,ReLU函数。下面我们将一一介绍。
该函数是将取值为 (−∞,+∞)的数映射到(0,1),公式为:
对于sigmoid函数的求导推导为:
函数特点:饱和函数,没有负值,容易照成梯度消失。
tanh函数相较于sigmoid函数要常见一些,该函数是将取值为 (−∞,+∞) 的数映射到 (−1,1) 之间,其公式与图形为:
tanh函数在 0 附近很短一段区域内可看做线性的。由于tanh函数均值为 0 ,因此弥补了sigmoid函数均值为 0.5 的缺点。 对于tanh函数的求导推导为:
tanh函数的缺点同sigmoid函数的第一个缺点一样,当 z很大或很小时,g′(z) 接近于 0 ,会导致梯度很小,权重更新非常缓慢,即梯度消失问题。
ReLU函数又称为修正线性单元(Rectified Linear Unit),是一种分段线性函数,其弥补了sigmoid函数以及tanh函数的梯度消失问题。ReLU函数的公式以及图形如下:
ReLU函数的优点:
在输入为正数的时候(对于大多数输入 z 空间来说),不存在梯度消失问题。
计算速度要快很多。ReLU函数只有线性关系,不管是前向传播还是反向传播,都比sigmoid和tanh要快很多。(sigmoid和tanh要计算指数,计算速度会比较慢)。
ReLU函数的缺点:当输入为负时,梯度为0,会产生梯度消失问题。
经典(以及广泛使用的)ReLU 激活函数的变体,带泄露修正线性单元(Leaky ReLU)的输出对负值输入有很小的坡度。由于导数总是不为零,这能减少静默神经元的出现,允许基于梯度的学习(虽然会很慢)。
具有relu的优势,且输出均值接近零,实际上prelu和LeakyReLU都有这一优点。有负数饱和区域,从而对噪声有一些鲁棒性。可以看做是介于relu和LeakyReLU之间的一个东西。当然,这个函数也需要计算exp,从而计算量上更大一些。
解析:如果不会画GRU,可以画LSTM或者RNN。再或者可以讲解GRU与其他两个网络的联系和区别。不要直接就说不会。
RNN,LSTM,Transformer,BERT专门写了篇博客讲。
梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足。
通过反向传播算法更新梯度的公式可以看到,影响梯度更新的有,初始权重、激活函数、梯度流动方式、损失值过大等。
初始权重和激活函数带来的影响:神经网络权重初始化不当以及激活函数选择不当 深度神经网络训练的时候,采用反向传导的方式,其背后的本质是链式求导,计算每层梯度的时候会涉及到一些连乘操作。每一层的残差都是由后一层的残差乘以两层之间的权重矩阵,再乘以当前层的激活函数的导数得到。因此,神经网络权重的初始化和激活函数选择至关重要,不当的初始化可能会带来梯度消失或者梯度爆炸。当网络过深,如果连乘的因子大部分小于1,最后乘积可能趋于0;另一方面,如果连乘的因子大部分大于1,最后乘积可能趋于无穷。这就是所谓的梯度消失与梯度爆炸。(解决:使用Xavier初始化,使用BN层,使用预训练模型,使用relu函数)
神经网络本身的结构问题,如:RNN。当我们要计算的损失函数的梯度是,反向传播需要经过RNN中的每一个单元。每次反向传播经过一个单元时,都要使用其中某一个W的转置,这意味着最终的表达式对h0梯度的表达式将会包含很多很多权重矩阵因子,这样不断对同一个值做乘法,是非常糟糕的。 (解决:梯度剪切阈值,LSTM)
Attention简单理解就是权重分配。以seq2seq中的attention公式作为讲解。就是对输入的每个词分配一个权重,权重的计算方式为与解码端的隐含层时刻作比较,得到的权重的意义就是权重越大,该词越重要。最终加权求和。 直观理解,生成输出词时,会考虑每一个输入词和当前输出词的对齐关系。对齐越好的词,权重越大,对当前输出词的影响也越大。
实现跨通道的交互和信息整合,实现卷积核通道数的降维和升维,可以实现多个feature map的线性组合,而且可是实现与全连接层的等价效果。
从数据上提升性能:收集更多的数据,对数据做缩放和变换,特征组合和重新定义问题。
从算法调优上提升性能:用可靠的模型诊断工具对模型进行诊断,权重的初始化,用小的随机数初始化权重。对学习率进行调节,尝试选择合适的激活函数,调整网络的拓扑结构,调节batch和epoch的大小,添加正则化的方法,尝试使用其它的优化方法,使用early stopping。
Seq2seq属于encoder-decoder结构的一种,利用两个RNN,一个作为encoder一个作为decoder。Encoder负责将输入序列压缩成指定长度的向量,这个向量可以看作这段序列的语义,而decoder负责根据语义向量生成指定的序列。
RNN的求解可以采用BPTT(Back Propagation Through Time)算法实现。实际上是BP的简单变种。RNN设计的初衷在于捕捉长距离输入之间的依赖关系,然而使用BPTT的算法并不能成功捕捉远距离依赖关系,这一现象源于深度神经网络中的梯度消失问题。传统的RNN网络梯度可以表示为连乘的形式:
由于预测误差沿神经网络每一层反向传播,当雅克比矩阵最大特征值大于1时,随着离输出越来越远,每层的梯度大小会呈指数增长,导致梯度爆炸。反之若最大特征值小于1,梯度大小会指数减小,产生梯度消失。梯度消失意味着无法通过加深网络层数来提升预测效果,只有靠近输出的几层才真正起到学习的作用,这样RNN很难学习到输入序列中的长距离依赖关系。梯度爆炸可以通过梯度裁剪来缓解,即当梯度的范式大于某个给定值的时候,对梯度进行等比缩放。而梯度消失问题需要对模型本身进行改进。深度残差网络是对前馈神经网络的改进。通过残差学习的方式缓解了梯度消失的现象,从而可以学习到更深层的网络表示。对于RNN来说,长短时记忆模型及其变种门控循环单元等模型通过加入门控机制,很大程度上缓解了梯度消失带来的损失。
RNN
LSTM
由上面两幅图可以观察到,LSTM结构更为复杂,在RNN中,将过去的输出和当前的输入concatenate到一起,通过tanh来控制两者的输出,它只考虑最近时刻的状态。在RNN中有两个输入和一个输出。
RNN在处理long term memory的时候存在缺陷,LSTM是一种变种的RNN,它的精髓在于引入了细胞状态这样一个概念,不同于RNN只考虑最近的状态,LSTM的细胞状态会决定哪些状态应该被留下来,哪些状态应该被遗忘,也就是途中最上面的一条通路。
卷积层 | 池化层 | |
---|---|---|
功能 | 提取特征 | 压缩特征图,提取主要特征 |
操作 | 卷积核了是二维的,对于三维数据比如RGB图像(3通道),卷积核的深度必须同输入的通道数,输出的通道数等于卷积核的个数。卷积操作会改变输入特征图的通道数。 | 池化只是在二维数据上操作的,因此不改变输入的通道数。对于多通道的输入,这一点和卷积区别很大。 |
特性 | 权值共享:减少了参数的数量,并利用了图像目标的位置无关性。稀疏连接:输出的每个值只依赖于输入的部分值。 |
https://blog.csdn.net/lrs1353281004/article/details/81188250
梯度下降法是最基本的一类优化器,目前主要分为三种梯度下降法:标准梯度下降法(GD, Gradient Descent),随机梯度下降法(SGD, Stochastic Gradient Descent)及批量梯度下降法(BGD, Batch Gradient Descent)。
GD
假设要学习训练的模型参数为W,代价函数为J(W),则代价函数关于模型参数的偏导数即相关梯度为,学习率为,则使用梯度下降法更新参数为:
基本策略可以理解为”在有限视距内寻找最快路径下山“,因此每走一步,参考当前位置最陡的方向(即梯度)进而迈出下一步。可以形象的表示为:
缺点:训练速度慢,每走一步都药计算下一步的方向,而且每输入一个样本都要更新一次参数,且每次迭代都要遍历所有样本;容易陷入局部最优解。
BGD
从表达式来看,模型参数的调整更新与全部输入样本的代价函数的和(即批量/全局误差)有关。即每次权值调整发生在批量样本输入之后,而不是每输入一个样本就更新一次模型参数。这样就会大大加快训练速度。
缺点:速度还是慢。
SGD
就是把BGD的一次选一批总数为n的训练样本改成一次随机选一个样本更新。
基本策略可以理解为随机梯度下降像是一个盲人下山,不用每走一步计算一次梯度,但是他总能下到山底,只不过过程会显得扭扭曲曲。
优点:虽然要走很多步,但是计算梯度快,而且对噪声抵抗性强。应用大型数据集时,训练速度很快。
缺点:容易陷入局部最优解;SGD在随机选择梯度的同时会引入噪声,使得权值更新的方向不一定正确。
动量优化方法是在梯度下降法的基础上进行的改变,具有加速梯度下降的作用。一般有标准动量优化方法Momentum、NAG(Nesterov accelerated gradient)动量优化方法。
Momentum
使用动量(Momentum)的随机梯度下降法(SGD),主要思想是引入一个积攒历史梯度信息动量来加速SGD。
可以看到,梯度项加入了上一个梯度的权重后值。理解策略为:由于当前权值的改变会受到上一次权值改变的影响,类似于小球向下滚动的时候带上了惯性。这样可以加快小球向下滚动的速度。
动量主要解决SGD的两个问题:一是随机梯度的方法(引入的噪声);二是Hessian矩阵病态问题(可以理解为SGD在收敛过程中和正确梯度相比来回摆动比较大的问题)。
NAG
牛顿加速梯度(NAG, Nesterov accelerated gradient)算法,是Momentum动量算法的变种。更新模型参数表达式如下:
Nesterov动量梯度的计算在模型参数施加当前速度之后,因此可以理解为往标准动量中添加了一个校正因子。
理解策略:在Momentun中小球会盲目地跟从下坡的梯度,容易发生错误。所以需要一个更聪明的小球,能提前知道它要去哪里,还要知道走到坡底的时候速度慢下来而不是又冲上另一个坡。计算可以表示小球下一个位置大概在哪里。从而可以提前知道下一个位置的梯度,然后使用到当前位置来更新参数。
然而在随机梯度的情况下,Nesterov动量对收敛率的作用却不是很大。
自适应学习率优化算法针对于机器学习模型的学习率,简单说就是传统优化算法学习率不可变或者根据训练次数调节学习率,但是自适应学习率优化算法会采取一些策略来想办法更新学习率,从而提高训练速度。
目前的自适应学习率优化算法主要有:AdaGrad算法,RMSProp算法,Adam算法以及AdaDelta算法。
AdaGrad
思想:
AdaGrad算法,独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平均值总和的平方根。具有代价函数最大梯度的参数相应地有个快速下降的学习率,而具有小梯度的参数在学习率上有相对较小的下降。
算法描述:
AdaGrad其实是对学习率加了一个约束,即:
特点:从表达式可以看出
前期较小的时候, regularizer较大,能够放大梯度
后期较大的时候,regularizer较小,能够约束梯度
适合处理稀疏梯度
Adagrad 的主要优势在于不需要人为的调节学习率,它可以自动调节;缺点在于,仍依赖于人工设置一个全局学习率,且随着迭代次数增多,学习率会越来越小,最终会趋近于0。
RMSProp算法
思想:
RMSProp算法修改了AdaGrad的梯度积累为指数加权的移动平均,使得其在非凸设定下效果更好。
算法描述:
RMSProp算法的一般策略可以表示为:
RMSProp借鉴了Adagrad的思想,观察表达式,分母为。由于取了个加权平均,避免了学习率越来越低的的问题,而且能自适应地调节学习率。
RMSProp算法在经验上已经被证明是一种有效且实用的深度神经网络优化算法。目前它是深度学习从业者经常采用的优化方法之一。
AdaDelta算法
思想:AdaGrad算法和RMSProp算法都需要指定全局学习率,AdaDelta算法结合两种算法每次参数的更新步长即:
在模型训练的初期和中期,AdaDelta表现很好,加速效果不错,训练速度快。
在模型训练的后期,模型会反复地在局部最小值附近抖动。
Adam算法
思想:
首先,Adam中动量直接并入了梯度一阶矩(指数加权)的估计。其次,相比于缺少修正因子导致二阶矩估计可能在训练初期具有很高偏置的RMSProp,Adam包括偏置修正,修正从原点初始化的一阶矩(动量项)和(非中心的)二阶矩估计。
算法描述:
Adam算法策略可以表示为:
修正的原因:一般说法是,如果不修正,初始化时m和v都是0,刚开始更新的时候则计算出的结果会更偏向于0,会导致最终计算的步长过大,导致有可能使参数更新到一个不是很合适的区域,使得训练时间大大增长。那为什么步长会过大呢,因为β2一般会比β1设计更接近于1, 比如β1是0.9,β2是0.999,那么不修正的情况下,s计算是0.1g,r是0.001,其中g是梯度,假设这时候计算步长就是,步长会很大,而且不是梯度导致的,是公式本身导致的,就会迭代到不合适的区域,使得训练时间增长,设置修正项就是为了使初始化的时候不出现这样的情况,刚开始,t=1的时候,通过修正项公式,修正项s就等于g, r就等于, 这样的话刚开始的步长就接近于1 ,因为最后是,这样就比较合适。随着更新的进行,t越来越大,t是指迭代的次数。分母越来越接近1,使得修正项和不修正时越来越接近。
评价:Adam通常被认为对超参数的选择相当鲁棒,尽管学习率有时需要从建议的默认修改。
https://blog.csdn.net/weixin_40170902/article/details/80092628
对于稀疏数据,尽量使用学习率可自适应的算法,不用手动调节,而且最好采用默认参数
SGD通常训练时间最长,但是在好的初始化和学习率调度方案下,结果往往更可靠。但SGD容易困在鞍点,这个缺点也不能忽略。
如果在意收敛的速度,并且需要训练比较深比较复杂的网络时,推荐使用学习率自适应的优化方法。
Adagrad,Adadelta和RMSprop是比较相近的算法,表现都差不多。
在能使用带动量的RMSprop或者Adam的地方,使用Aadam往往能取得更好的效果。