文章目录

  • 基础
  • 1. 常见的梯度下降方法及优缺点——优化器
  • 梯度下降的推导
  • Momentum——优化器
  • 指数加权移动平均
  • Nesterov动量
  • Adagrad——优化器
  • Adadelta——优化器
  • RMSprop——优化器
  • Adam——优化器
  • 2. dropout原理以及为什么能用于防止过拟合?
  • 3. 为什么需要Normalization
  • 4.[Batch Normalization的理解](https://zh.gluon.ai/chapter_convolutional-neural-networks/batch-norm.html)
  • 5. BN的前向传播和反向传播公式
  • 6. BN的使用场景
  • 7. BN和Dropout共同使用时会出现的问题
  • 8. LN的作用
  • 9. [梯度消失与梯度膨胀,以及6种解决措施]()
  • 10. 为什么神经网络参数不能全部初始化为全0
  • 一、神经网络基础和前馈神经网络
  • 1、激活函数的比较
  • 2、神经网络结构哪几种?各自都有什么特点?
  • 3、前馈神经网络叫做多层感知机是否合适?
  • 4、前馈神经网络怎么划分层?
  • 5、如何理解通用近似定理?
  • 6、怎么理解前馈神经网络中的反向传播?具体计算流程是怎样的?
  • 7、在深度学习中,网络层数增多会伴随哪些问题,怎么解决?为什么要采取残差网络ResNet?
  • 二、神经网络的训练技巧及优化问题
  • 1、神经网络优化的难点体现在哪里?
  • 2、神经网络数据预处理方法有哪些?参数初始化为0、过大、过小会怎样?神经网络怎样进行参数初始化?
  • 3、神经网络优化方法有哪些?(学习率衰减+梯度方向优化)
  • 4、请介绍逐层归一化(Batch Normalization和Layer Normalization)?
  • 为什么要进行逐层归一化?什么是内部协变量偏移?**
  • BN的主要作用是和主要原理 *
  • BN 在训练和测试时分别是怎么做的?
  • 5、神经网络正则化的方法有哪些?
  • 6、神经网络怎么解决梯度消失/梯度爆炸问题?
  • tensorflow
  • tensorflow 计算图
  • 使用tf编写一个LR
  • 用tensorflow实现线性回归,主要考察的是一个tf的一个实现思路。
  • Tensorflow的计算图


基础

1. 常见的梯度下降方法及优缺点——优化器

  • Batch gradient descent
    优点: 理想状态下经过足够多的迭代后可以达到全局最优。
    缺点: 如果你的数据集非常的大(现在很常见),根本没法全部塞到内存(显存)里,所以BGD对于小样本还行,大数据集就没法娱乐了。而且因为每次迭代都要计算全部的样本,所以对于大数据量会非常的慢。
  • stochastic gradient descent(随机梯度下降)
    为了加快收敛速度,并且解决大数据量无法一次性塞入内存(显卡)的问题,stochastic gradient descent (SGD)被提出来,SGD的思想是每次只训练一个样本去更新参数
    如果我们的数据集很大,比如几亿条数据,num_iterations 基本上 设置1,2,(10以内的就足够了)就可以。
    优点:训练速度快,无内存问题
    缺点: 因为每次只用一个样本来更新参数,会导致不稳定性大些,每次更新的方向,不像batch gradient descent那样每次都朝着最优点的方向逼近,会在最优点附近震荡。因为每次训练的都是随机的一个样本,会导致梯度的方向不会像BGD那样朝着最优点。
    (随机梯度下降时将数据的顺序打乱很重要,因为这个随机性相当于引入了“噪音”,这个噪音能使SGD避免陷入局部最优解中)
  • mini-batch gradient descent
    优点:相对SGD在下降的时候,相对平滑些(相对稳定),不像SGD那样震荡的比较厉害
    缺点:增加了一个超参数 batch_size ,要去调这个超参数。
    关于batch_size:(batch_size通常设置为2的幂次方,通常设置2,4,8,16,32,64,128,256,512(很少设置大于512)。因为设置成2的幂次方,更有利于GPU加速)
    合理范围内,增大 Batch_Size 有何好处?
    ① 内存利用率提高了,大矩阵乘法的并行化效率提高。
    ② 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
    ③ 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。
    盲目增大 Batch_Size 有何坏处?
    ① 内存利用率提高了,但是内存容量可能撑不住了。
    ② 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
    ③ Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。

小批量随机梯度在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。实验中随机梯度下降的一个迭代周期耗时更多。这是因为随机梯度下降在一个迭代周期里做了更多次的自变量迭代,而且单样本的梯度计算难以有效利用矢量计算。

梯度下降的推导

梯度: 某一函数沿着某点处的方向可以以最快速度到达最大值,该方向导数定义为该函数的梯度。
参考:
参考: https://www.jianshu.com/p/93d9fea7f4c2 推导过程
R语言新增一列归一化数据_R语言新增一列归一化数据
R语言新增一列归一化数据_随机梯度下降_02
R语言新增一列归一化数据_神经网络_03

Momentum——优化器

梯度下降的问题
较大的学习率会导致在竖直方向上越过最优解,较小的学习率会导致水平方向上移动缓慢,模型收敛时间长。
R语言新增一列归一化数据_神经网络_04
R语言新增一列归一化数据_R语言新增一列归一化数据_05是当前随机梯度下降的导数。R语言新增一列归一化数据_迭代_06第t个时间步的速度。 对过去的R语言新增一列归一化数据_迭代_07天做指数加权移动平均

动量法: 参数更新不仅由当前梯度决定,也与此前累积的下降方向有关,这使得参数方向变化不大的维度可以加速更新,并减少梯度方向变化大的维度上的更新幅度。因此有加速收敛和减小振荡的效果

相比于小批量随机梯度下降,动量法自变量在各个方向上的移动幅度不仅取决于当前梯度,还取决于过去的各个梯度在各个方向上是否一致。
动量法积累了之前梯度指数衰减的移动平均,并且继续沿该方向移动。R语言新增一列归一化数据_神经网络_08越大,说明之前梯度对现在方向的影响越大。
动量法主要目的是解决两个问题:Hessian矩阵的病态条件和随机梯度的方差。积累的动量能够正确地走向穿过峡谷,而普通的梯度则会浪费时间在峡谷的窄轴上来回移动


优点:

更快的收敛 减少振荡

指数加权移动平均

R语言新增一列归一化数据_神经网络_09

Nesterov动量

Nesterov与标准的动量之间的区别体现在梯度计算上。
R语言新增一列归一化数据_R语言新增一列归一化数据_10
在目标函数有增高的趋势之前,减缓更新速率

Adagrad——优化器

Adagrad是一个在迭代过程中不断自我调整学习率,并让模型参数中每个元素都是用不同的学习率进行优化的算法。不同参数的更新频率往往有所区别。对于更新不频繁的参数(典型例子:更新 word embedding 中的低频词),我们希望单次步长更大,多学习一些知识;对于更新频繁的参数,我们则希望步长较小,使得学习到的参数更稳定,不至于被单个样本影响太多
即对于参数R语言新增一列归一化数据_随机梯度下降_11都有自己的学习率R语言新增一列归一化数据_R语言新增一列归一化数据_12
R语言新增一列归一化数据_R语言新增一列归一化数据_13
Adagrad的缺点是如果目标函数有关自变量中某个元素的偏导数一直都较大,那么该元素的学习率将下降较快;反之,如果目标函数有关自变量中某个元素的偏导数一直都较小,那么该元素的学习率将下降较慢。然而自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。所以,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。

Adadelta——优化器

它没有学习率。 AdaDelta算法与RMSProp算法的不同之处在于使用 R语言新增一列归一化数据_R语言新增一列归一化数据_14来替代超参数 R语言新增一列归一化数据_R语言新增一列归一化数据_15
R语言新增一列归一化数据_迭代_16
R语言新增一列归一化数据_R语言新增一列归一化数据_17用来记录自变量变化量R语言新增一列归一化数据_R语言新增一列归一化数据_18按元素平方的指数加权移动平均
R语言新增一列归一化数据_R语言新增一列归一化数据_19

RMSprop——优化器

RMSprop是在Adagrad的基础上,增加了指数加权移动平均,防止学习率衰减的过快从而避免无法找到有用的解。
因为R语言新增一列归一化数据_随机梯度下降_20是单调递增的,使得学习率逐渐减至0,可能导致训练过程提前结束。为了改进这个缺点,考虑在计算二阶动量时不累计全部历史梯度,而只关注最近某一时间窗口内的下降梯度。
R语言新增一列归一化数据_神经网络_21

Adam——优化器

R语言新增一列归一化数据_迭代_22

AdaGrad算法在迭代过程中不断调整学习率,并让目标函数自变量中每个元素都分别拥有自己的学习率。
使用AdaGrad算法时,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。
RMSProp算法和AdaGrad算法的不同在于,RMSProp算法使用了小批量随机梯度按元素平方的指数加权移动平均来调整学习率。

2. dropout原理以及为什么能用于防止过拟合?

R语言新增一列归一化数据_R语言新增一列归一化数据_23


没有dropout网络计算公式:

R语言新增一列归一化数据_随机梯度下降_24

采用dropout后计算公式就变成了:

R语言新增一列归一化数据_神经网络_25

对某一隐藏层使用丢弃法,改成的隐藏单元将有一定概率被丢弃掉。设丢弃概率为R语言新增一列归一化数据_随机梯度下降_26,那么有R语言新增一列归一化数据_随机梯度下降_26的概率R语言新增一列归一化数据_迭代_28会被清零,有R语言新增一列归一化数据_R语言新增一列归一化数据_29的概率R语言新增一列归一化数据_迭代_28会除以R语言新增一列归一化数据_R语言新增一列归一化数据_29做拉伸。丢弃概率是丢弃法的超参数。具体说设随机变量R语言新增一列归一化数据_随机梯度下降_32为0和1的概率分别为 R语言新增一列归一化数据_随机梯度下降_26R语言新增一列归一化数据_R语言新增一列归一化数据_29。使用丢弃法时我们计算新的隐藏单元R语言新增一列归一化数据_R语言新增一列归一化数据_35
R语言新增一列归一化数据_随机梯度下降_36
由于R语言新增一列归一化数据_迭代_37 ,因此R语言新增一列归一化数据_R语言新增一列归一化数据_38
即丢弃法不改变其输入的期望值。

为什么说Dropout可以解决过拟合?
由于在训练中隐藏层神经元的丢弃是随机的,因此输出层的计算无法过度依赖其中的任意一个,从而在训练模型时起到正则化的作用,可以用来应对过拟合。在测试模型时,为了获得更准确的结果,一般不使用丢弃法。
  1. 由于每次用输入网络的样本进行权值更新时,隐含节点都是以一定概率随机出现,因此不能保证每2个隐含节点每次都同时出现,这样权值的更新不再依赖于有固定关系隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况。
  2. 可以将dropout看作是模型平均的一种。对于每次输入到网络中的样本(可能是一个样本,也可能是一个batch的样本),其对应的网络结构都是不同的,但所有的这些不同的网络结构又同时share隐含节点的权值。这样不同的样本就对应不同的模型,是bagging的一种极端情况。个人感觉这个解释稍微靠谱些,和bagging,boosting理论有点像,但又不完全相同。

3. native bayes是dropout的一个特例。Native bayes有个错误的前提,即假设各个特征之间相互独立,这样在训练样本比较少的情况下,单独对每个特征进行学习,测试时将所有的特征都相乘,且在实际应用时效果还不错。而Droput每次不是训练一个特征,而是一部分隐含层特征。

4. 还有一个比较有意思的解释是,Dropout类似于性别在生物进化中的角色,物种为了使适应不断变化的环境,性别的出现有效的阻止了过拟合,即避免环境改变时物种可能面临的灭亡。

参考: https://zhuanlan.zhihu.com/p/38200980

3. 为什么需要Normalization

参考: https://zhuanlan.zhihu.com/p/33173246 推荐
(1) 因为归一化能够使得数据具有“独立同分布”的特点,归一化能够使得模型更容易训练,并且能够提升模型的预测能力。因此机器学习中经常对数据进行“白化”操作,白化的目的一般有两个:① 去除特征之间的相关性->独立; ② 使得所有特征具有相同的均值和方差->同分布。
(2)对数据不一致的问题进行简单处理

Normalization 为什么会有效
Normalization的权重伸缩不变性,因为当权重伸缩时,对应的均值和标准差均等比例伸缩。权重伸缩不变性可以有效地提高反向传播的效率,权重的伸缩变化不会影响反向梯度的 Jacobian 矩阵,因此也就对反向传播没有影响,避免了反向传播时因为权重过大或过小导致的梯度消失或梯度爆炸问题,从而加速了神经网络的训练。。
权重伸缩不变性还具有参数正则化的效果,可以使用更高的学习率。下层的权重值越大,其梯度就越小。参数的变化就越稳定,相当于实现了参数正则化的效果,避免参数的大幅震荡,提高网络的泛化性能。
数据伸缩不变性: 数据伸缩不变性可以有效地减少梯度弥散,简化对学习率的选择。

4.Batch Normalization的理解

Batch Normalization,就是在深度神经网络训练过程中使得每一层神经网络的输入保持相近的分布;
(对输入数据做标准化处理:、
(1)处理后的任意一个特征在数据集中所有样本上的均值为0、标准差为1,
(2)对数据进行拉升和偏移。R语言新增一列归一化数据_神经网络_39,拉伸(scale)参数 R语言新增一列归一化数据_R语言新增一列归一化数据_40 和偏移(shift)参数R语言新增一列归一化数据_随机梯度下降_41,使得最终的数据分布:均值为R语言新增一列归一化数据_随机梯度下降_41, 方差为R语言新增一列归一化数据_神经网络_43
第一步是得到标准分布,第二步的目的是为了保证模型的表达能力不因为规范而下降。并且恰恰是因为有第二步,才保留了不对数据做批量归一化的可能。除了充分利用底层学习的能力,另一方面的重要意义在于保证获得非线性的表达能力。Sigmoid 等激活函数在神经网络中有着重要作用,通过区分饱和区和非饱和区,使得神经网络的数据变换具有了非线性计算能力。而第一步的规范化会将几乎所有数据映射到激活函数的非饱和区(线性区),仅利用到了线性变化能力,从而降低了神经网络的表达能力。而进行再变换,则可以将数据从线性区变换到非线性区,恢复模型的表达能力。
标准化后使各个特征的分布相近,使得整个神经网络在各层的中间输出的数值更稳定,更容易训练模型。)

对全连接层和卷积层做批量归一化的方法稍有不同。批量归一化层置于全连接层中的仿射变换和激活函数之间。即R语言新增一列归一化数据_迭代_44. 对卷积层来说,批量归一化发生在卷积计算之后、应用激活函数之前。如果卷积计算输出多个通道,我们需要对这些通道的输出分别做批量归一化,且每个通道都拥有独立的拉伸和偏移参数,并均为标量。
使用批量归一化训练时,我们可以将批量大小设得大一点,从而使批量内样本的均值和方差的计算都较为准确。

简单回答BN作用: (1)使得数据分布保持相近,使得模型更容易训练。 (2)有效避免梯度消失 (3)防止过拟合

BN训练和测试时的参数是一样的嘛?
批量归一化层和丢弃层一样,在训练模式和预测模式的计算结果是不一样的。对于BN,在训练时,是对每一批的训练数据进行归一化,也即用每一批数据的均值和方差。
而在测试时,比如进行一个样本的预测,就并没有batch的概念,因此,这个时候用的均值和方差是全量训练数据的均值和方差,这个可以通过移动平均法求得。

5. BN的前向传播和反向传播公式

参考:
前向传播
R语言新增一列归一化数据_迭代_45
反向传播
R语言新增一列归一化数据_随机梯度下降_46

6. BN的使用场景

BN独立地规范化每一个输入维度,但规范化的参数是一个min-batch的一阶统计量(均值)和二阶统计量(方差)。这就要求每一个min-batch的统计量是整体统计量的近似估计,或者说每一个mini-batch彼此之间,以及和整体数据都应该是近似同分布的。分布差距较小的min-batch可以看做是为规范化操作和模型训练引入了噪声,可以增强模型的鲁棒性;但如果每个mini-batch的元素分布差别很大,那么不同mini-batch的数据将会进行不一样的数据变换,这就增加了模型训练的难度。

因此,BN 比较适用的场景是:每个 mini-batch 比较大,数据分布比较接近。在进行训练之前,要做好充分的 shuffle. 否则效果会差很多。因而不适用于动态的网络结构和RNN网络

7. BN和Dropout共同使用时会出现的问题

BN和Dropout单独使用都能减少过拟合并加速训练速度, 但一起使用会得到比单独使用更差的效果。
Dropout 与 BN 之间冲突的关键是网络状态切换过程中存在神经方差的不一致行为。当网络从训练转为测试时,Dropout 可以通过其随机失活保留率(即 p)来缩放响应,并在学习中改变神经元的方差,而 BN 仍然维持 X 的统计滑动方差。这种方差不匹配可能导致数值不稳定。而随着网络越来越深,最终预测的数值偏差可能会累计,从而降低系统的性能。
解决方案: 1. 将Dropout放在所有BN层的后面,这样就不会产生方差的偏移; 2.使用高斯dropout,降低对方差偏移的敏感度

8. LN的作用

归一化的本质都是将数据转化为均值为0,方差为1的数据。这样可以减小数据的偏差,规避训练过程中梯度消失或爆炸的情况。我们在训练网络中比较常见的归一化方法是Batch Normalization,即在每一层输出的每一批数据上进行归一化。而Layer Normalization与BN稍有不同,即在每一层输出的每一个样本上进行归一化。

LN针对单个训练样本进行,不依赖于其他数据,相较于BN,避免了受到min-batch数据分布的影响,可以用于小mini-batch场景、动态网络场景和RNN

LN与BN的对比
BN 的转换是针对单个神经元可训练的——不同神经元的输入经过再平移和再缩放后分布在不同的区间,而 LN 对于一整层的神经元训练得到同一个转换——所有的输入都在同一个区间范围内。如果不同输入特征不属于相似的类别(比如颜色和大小),那么 LN 的处理可能会降低模型的表达能力。
因此两者的适用情况不同

  • LN针对单个训练样本进行规范化,不像BN那样依赖于一个MiniBatch的数据,因此避免了不同样本之间的相互影响,可以适用于动态网络场景,RNN和自然语言处理领域
  • LN不需要保存MiniBatch的均值和方差,相比BN计算量更小
  • BN针对单个神经元进行规范化,不同神经元的输入经过平移和缩放使不同神经元的分布在不同的区间中,LN对于整个一层的神经元进行转换,所有的输入全部控制在同一个区间范围内。在CNN中,假设输入的是一张图片,同一层的输入特征表征着不同的特征,例如有的位置神经元表征的是颜色信息,有的位置神经元表征的是形状信息,那么这个时候BN是更合适的,使不同的特征信息进行分别处理,但是如果这种输入使用LN处理,将一个样本的所有特征的分布全部标准化到一个统一的区间,显然会降低模型的表达能力。

9. 梯度消失与梯度膨胀,以及6种解决措施

**梯度消失:**根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都小于1的话,那么即使这个结果是0.99,在经过足够多层传播之后,误差对输入层的偏导会趋于0。 这种情况会导致输入层的隐藏层隐含层神经元调整极小。
**梯度爆炸:**根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都大于1的话,在经过足够多层传播之后,误差对输入层的偏导会趋于无穷大。 这种情况又会导致靠近输入层的隐含层神经元调整变动极大。

梯度消失和梯度爆炸的解决方案

  • 预训练加微调
    此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。
    Hinton在训练深度信念网络(Deep Belief Networks)中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
  • 梯度裁剪和正则化
    梯度裁剪这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度裁剪的阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内,通过这种直接的方法就可以防止梯度爆炸。(梯度裁剪在RNN中会用到吧)
    另一种解决梯度爆炸的手段是采用正则化,比较常见的是L1正则和L2正则,在各个深度框架中都有相应的API可以使用正则化。
    正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式: R语言新增一列归一化数据_迭代_47其中,R语言新增一列归一化数据_神经网络_48是正则化系数,因此,如果发生梯度爆炸,权重的范数就会变得非常大,通过正则化项,可以部分限制梯度爆炸的发生。

注:事实上,在深度神经网络中,往往是梯度消失出现的更多一些。

  • relu、leakrelu、elu等激活函数
    **Relu:**思想也很简单,如果激活函数的导数为1,那么就不存在梯度消失爆炸的问题了,每层的网络都可以得到相同的更新速度,relu就这样应运而生。

Relu的主要贡献在于:

解决了梯度消失、爆炸的问题
计算方便,计算速度快,加速了网络的训练
单侧抑制提供了网络的稀疏表达能力

同时也存在一些缺点:

由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)
输出不是以0为中心的

leakrelu就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu=max(k∗x,x)
其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来。leakrelu解决了0区间带来的影响,而且包含了relu的所有优点

  • batchnorm
    Batchnorm是深度学习发展以来提出的最重要的成果之一了,目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。
    通过规范化操作将输出x规范化以此来保证网络的稳定性。batchnorm就是通过对每一层的输出规范为均值和方差一致的方法,消除了w带来的放大缩小的影响,进而解决梯度消失和爆炸的问题。
  • 残差结果
    残差可以很轻松的构建几百层,一千多层的网络而不用担心梯度消失过快的问题,原因就在于残差的捷径(shortcut)部分。
  • LSTM
    LSTM全称是长短期记忆网络(long-short term memory networks),是不那么容易发生梯度消失的,主要原因在于LSTM内部复杂的“门”(gates),LSTM通过它内部的“门”可以接下来更新的时候“记住”前几次训练的”残留记忆“,因此,经常用于生成文本中。

10. 为什么神经网络参数不能全部初始化为全0

参考: https://zhuanlan.zhihu.com/p/27190255
如果将神经网络参数全部初始化为0,那么在进行反向传播的时候,参数更新的幅度也是一样的,这样新参数也就全部相同了。然后不管进行多少轮的正向传播以及反向传播,每两层之间的参数都是一样的。
换句话说,本来希望网络中不同的结点学习到不同的参数,但是由于参数相同以及输出值都一样,不同的结点根本无法学到不同的特征,这样就失去了网络学习特征的意义了。
W初始化全为0,很可能导致模型失效,无法收敛。

一、神经网络基础和前馈神经网络

1、激活函数的比较

常见的激活函数有sigmoid、tanh、relu、softmax

sigmoid函数

sigmoid函数和一阶导数如下

R语言新增一列归一化数据_神经网络_49

R语言新增一列归一化数据_迭代_50


sigmoid函数是将取值为R语言新增一列归一化数据_神经网络_51的数据映射到R语言新增一列归一化数据_迭代_52之间,取R语言新增一列归一化数据_迭代_53的时候映射为0, 取R语言新增一列归一化数据_神经网络_54的时候映射为1,取0的时候映射为0.5.它的一阶导数的范围为R语言新增一列归一化数据_R语言新增一列归一化数据_55,数据越趋近0,导数越趋近与0.25,数据越趋近R语言新增一列归一化数据_随机梯度下降_56,导数越趋于0

优点:

  1. 数据压缩能力,将数据规约在[0,1]之间
  2. 导数形式优秀,方便计算

缺点:

  1. 容易梯度消失,x稍大的情况下就趋近一条水平线
  2. 非0中心化,在神经网络算法等情况下,造成反向传播时权重的全正全负的情况

tanh函数

tanh函数和一阶导数如下:

R语言新增一列归一化数据_R语言新增一列归一化数据_57

R语言新增一列归一化数据_随机梯度下降_58


tanh 函数是将取值为R语言新增一列归一化数据_R语言新增一列归一化数据_59的数据映射到R语言新增一列归一化数据_迭代_60之间,取 R语言新增一列归一化数据_迭代_53 的时候映射为 -1,取 R语言新增一列归一化数据_神经网络_54 的时候映射为 1,取 0 的时候映射为 0。它的一阶导数取值范围为 R语言新增一列归一化数据_R语言新增一列归一化数据_63,数据越趋近 0,导数越趋于 1,数据越趋近 R语言新增一列归一化数据_随机梯度下降_56,导数越趋于 0。相比于 sigmoid 函数,tanh 函数是关于 0 中心对称的。

优点:

  1. tanh 函数是关于 0 中心对称的,有利于提高训练效率

relu函数

relu函数和一阶导数如下:

R语言新增一列归一化数据_迭代_65

R语言新增一列归一化数据_迭代_66


Relu 函数是一种分段函数(注:Relu 函数本身是非线性函数,但是两个分段部分都是线性函数):它弥补了 sigmoid 函数以及 tanh 函数的梯度消失问题(当输入为正,梯度恒为 1;当输入为负,梯度恒为 0)。此外,相比于 sigmoid 函数或 tanh 函数,它的计算只有线性关系,因此运算速度会快很多。但是 Rule 函数也有问题,首先它在 0 点处是不可导的,通常我们可以采用中间导数代替(0.5),其次当输入为负的时候,神经元不会被激活,造成梯度消失问题。关于 Relu 函数的改进版本也有很多,比如Leaky Relu,但是 Relu 依然是深度学习中使用最广泛的激活函数。

优点:

  • 从计算的角度上,Sigmoid和Tanh激活函数均需要计算指数,复杂度高,而ReLU只需要一个阈值即可得到激活值;
  • ReLU的非饱和性可以有效地解决梯度消失的问题,提供相对宽的激活边界。
  • ReLU的单侧抑制提供了网络的稀疏表达能力。

缺点:

  • ReLU和Sigmoid一样,它们的输出是非零中心化的,给后一层的神经网络引入偏置偏移, 会影响梯度下降的效率。
  • ReLU的局限性在于其训练过程中会导致神经元死亡的问题。

0 中心对称问题

下图以二维空间为例说明 0 中心对称问题,其中R语言新增一列归一化数据_R语言新增一列归一化数据_67 为模型的初始参数,R语言新增一列归一化数据_迭代_68 为模型最优解。模型走绿色箭头能够最快收敛,如果采用 sigmoid 作为激活函数,则后面的每一层输入均为正,此时模型为了收敛,可能走类似红色折线箭头逼近最优解,收敛速度就会慢很多

R语言新增一列归一化数据_随机梯度下降_69

ReLU死亡问题
在训练时,如果参数在一次不恰当的更新后,第一个隐藏层中的某个ReLU神经元在所有的训练数据上都不能被激活,那么这个神经元自身的参数的梯度永远都会是0,在以后的训练过程中远远不能被激活。这种现象称为死亡ReLU问题,并且也可能会发生在其它隐藏层。

ReLU的变种

在实际使用中,为了避免上述情况,有几种ReLU的变种也会被广泛使用:Leakly ReLU、 ELU以及softplus函数

R语言新增一列归一化数据_随机梯度下降_70


R语言新增一列归一化数据_迭代_71

2、神经网络结构哪几种?各自都有什么特点?

前馈网络: 整个网络中的信息是朝一个方向传播,没有反向的信息传播,可以用一个有向无环路图表示。前馈网络主要包括全连接前馈网络卷积神经网络等。
反馈网络:反馈网络中的神经元不但可以接收其它神经元的信号,也可以接收自己的反馈信号。和前馈网络相比,反馈网络中的神经元具有记忆功能,在不同的时刻具有不同的状态。反馈神经网络中的信息传播可以是单向或者双向传递,因此可用一个有向循环图或无向图来表示。反馈网络包括循环神经网络、Hopfield网络、玻尔兹曼机等。
**图网络:**图网络是定义在图结构数据上的神经网络。图中每个结点都由一个或一组神经元构成。节点之间的连接可以是邮箱的,也可以是无向的。每个结点可以接受来自相邻结点或自身的信息。图网络是前馈网络和记忆网络的泛化,包含很多不同的实现方式,比如图卷积网络、消息传递网络等。

R语言新增一列归一化数据_随机梯度下降_72

3、前馈神经网络叫做多层感知机是否合适?

前馈神经网络也经常称为多层感知器(Multi-Layer Perceptron,MLP)。但多层感知器的叫法并不是十分合理,因为前馈神经网络其实是由多层的logistic 回归模型(连续的非线性函数)组成,而不是由多层的感知器(不连续的非线性函数)组成。

4、前馈神经网络怎么划分层?

在前馈神经网络中,各神经元分别属于不同的层。每一层的神经元可以接受前一层神经元的信号,并产生信号输出到下一层。第0层叫输入层,最后一层叫输出层,其他中间层叫隐藏层。整个网络中无反馈,信号从输入层向输出层单向传播,可用一个有向无环图表示。

5、如何理解通用近似定理?

通用近似定理: 对于具有线性输出层和至少一个使用“挤压”性质的激活函数的隐藏层组成的前馈神经网络,只要其隐藏层的神经元数量足够多,它可以以任意的精度来近似任何从一个定义在实数空间中的有界闭集函数。 其中挤压性质的函数比如sigmoid有界函数。

6、怎么理解前馈神经网络中的反向传播?具体计算流程是怎样的?

R语言新增一列归一化数据_随机梯度下降_73

R语言新增一列归一化数据_R语言新增一列归一化数据_74

上式中,误差项R语言新增一列归一化数据_神经网络_75来表示第R语言新增一列归一化数据_随机梯度下降_76层的神经元对最终误差的影响,也反映了最终的输出对第R语言新增一列归一化数据_随机梯度下降_76层的神经元对最终误差的敏感程度。

前馈神经网络中反向传播的实质就是误差的反向传播:R语言新增一列归一化数据_随机梯度下降_76层的误差项可以通过第R语言新增一列归一化数据_神经网络_79层的误差项计算得到,这就是误差的反向传播。

误差反向传播算法的具体含义是: 第R语言新增一列归一化数据_随机梯度下降_80层的神经元的误差项(或敏感性)是所有与该神经元相连的第R语言新增一列归一化数据_随机梯度下降_81层的神经元的误差项的权重和,然后再乘上该神经元激活函数的梯度

7、在深度学习中,网络层数增多会伴随哪些问题,怎么解决?为什么要采取残差网络ResNet?

随着网络层数的增加,网络发生了退化(degradation)的现象:随着网络层数的增多,训练集loss逐渐下降,然后趋于饱和,当你再增加网络深度的话,训练集loss反而会增大。注意这并不是过拟合,因为在过拟合中训练loss是一直减小的。
(1) 在深度学习中,网络层数增多会伴随哪些问题,如何解决

  • 随着网络层数的增加,需要消耗的计算资源也随之变大
  • 模型容易过拟合, 可以使用Dropout和正则化的方法来防止过拟合
  • 梯度消失和梯度爆炸问题的产生(批量归一化BN): BN层能对各层的输出做归一化,这样梯度在反向层传递后仍能保持大小稳定,不会出现过大或过小的情况
  • degradation退化问题: 可以使用ResNet残差网络帮助解决网络退化问题

(2)为什么要采用残差网络ResNet?

  1. 在残差网络中不会出现梯度消失的问题
  2. 残差网络在进行反向传播时能将第R语言新增一列归一化数据_神经网络_82层的梯度直接传递到任何一个比它浅的R语言新增一列归一化数据_随机梯度下降_80

二、神经网络的训练技巧及优化问题

1、神经网络优化的难点体现在哪里?

深层神经网络是一个高度非线性的模型,其风险函数是一个非凸函数,因此风险最小化是一个非凸优化问题,会存在很多局部最优点。在高维空间中,非凸优化的难点并不在于如何逃离局部最优点,而是如何逃离鞍点

2、神经网络数据预处理方法有哪些?参数初始化为0、过大、过小会怎样?神经网络怎样进行参数初始化?

(1)神经网络数据预处理方法有哪些?

  • 缩放归一化: 通过缩放将每一个特征的取值范围归一到[0, 1]或[-1, 1]之间
  • 标准归一化: 将每一维特征都处理为符合标准正态分布(均值为0, 标准差为1)
  • 白化: 是一种重要的预处理方法,用来降低输入数据特征之间的冗余。输入数据经过白化处理之后,特征之间的相关性较低,并且所有特征具有相同的方差。

参数初始化为0、过大、过小会怎样?

  • 参数为0:在第一遍前向计算时,所有的隐层神经元的激活值都相同。这样会导致深层神经元没有区分性。这种线性也称为对称权重现象。
  • 参数过大或过小: 参数过小还会使得sigmoid型激活函数丢失非线性的能力,这样多层神经网络的优势也就不存在了。如果参数取得太大,会导致输入状态过大。对于sigmoid型激活函数来说,激活值变得饱和,从而导致梯度接近0.

神经网络怎样进行参数初始化

  • Gaussian分布初始化
    R语言新增一列归一化数据_迭代_84
    例如: tf.truncated_normal, tf.random_normal
  • Xavier均匀分布初始化: 参数可以在[-r, r]内采用均匀分布进行初始化
    对于sigmoid型激活函数:
    R语言新增一列归一化数据_R语言新增一列归一化数据_85
    对于tanh函数:
    R语言新增一列归一化数据_迭代_86

3、神经网络优化方法有哪些?(学习率衰减+梯度方向优化)

集中优化方法答题上可以分为两类: 一是调整学习率,使得优化更稳定; 而是调整梯度方向,优化训练速度

R语言新增一列归一化数据_迭代_87

  • AdaGrad: Adagrad算法的缺点是在经过一定次数的迭代依然没有找到最优点时,由于这时学习率已经非常小,很难再继续找到最优点。在第t迭代时,计算每个参数梯度平方的累计值:
    R语言新增一列归一化数据_神经网络_88
    AdaGrad算法在迭代过程中不断调整学习率,并让目标函数自变量中每个元素都分别拥有自己的学习率。使用AdaGrad算法时,自变量中每个元素的学习率在迭代过程中一直在降低(或不变)。
  • RMSprop: 计算每次迭代梯度R语言新增一列归一化数据_迭代_89平方的指数衰减移动平均:
    R语言新增一列归一化数据_迭代_90
    RMSProp算法和AdaGrad算法的不同在于,RMSProp算法使用了小批量随机梯度按元素平方的指数加权移动平均来调整学习率。
  • 动量法:用梯度的移动平均来代替每次的实际梯度R语言新增一列归一化数据_迭代_91
  • Adam: Adam算法一方面计算梯度平方的指数加权平均(和RMSprop类似),另一方面计算梯度R语言新增一列归一化数据_迭代_89的指数加权平均(和动量法类似)R语言新增一列归一化数据_随机梯度下降_93

4、请介绍逐层归一化(Batch Normalization和Layer Normalization)?

强烈推荐参考: http://xiaofengshi.com/2019/03/06/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0-Normalization/

为什么要进行逐层归一化?什么是内部协变量偏移?**

在深层神经网络中,中间某一层的输入是其之前的神经层的输出。因此,其之前的神经层的参数变化会导致其输入的分布发生较大的差异。在使用随机梯度下降来训练网络时,每次参数更新都会导致网络中间每一层的输入的分布发生改变。越深的层,其输入的分布会改变得越明显。就像一栋高楼,低楼层发生一个较小的偏移,都会导致高楼层较大的偏移。

协变量偏移: 协变量是统计学概念,是可能影响预测结果的统计变量。在机器学习中,协变量可以看作是输入。一般的机器学习算法都要求输入在训练集和测试集上的分布式相似的。如果不满足这个要求,这些学习算法在测试集的表现会比较差。

从机器学习的角度来看,如果某个神经层的输入分布发生了改变,那么其参数需要重新学习,这种现象叫作内部协变量偏移

内部协变量偏移会导致什么问题?
简而言之,每个神经元的输入数据不再是“独立同分布”。

  1. 上层参数需要不断适应新的输入数据分布,降低学习速度
  2. 下层输入的变化可能趋向于变大或者变小,导致上层落入饱和区,使得学习过早停止。
  3. 每层的更新都会影响到其它层,因此每层的参数更新策略需要尽可能的谨慎

为了解决内部协变量偏移问题,就要使得每一个神经层的输入的分布在训练过程中保持一致。最简单直接的方法就是对每一个神经层都进行归一化操作,使其分布保持稳定。下面介绍几种比较常用的逐层归一化方法: 批量归一化、层归一化。层归一化和批量归一化整体上是十分相似的,差别在于归一化的方法不同。

动机

  • 训练的本质是学习数据分布。如果训练数据和测试数据的分布不同会降低模型的泛化能力。因此,应该在开始训练前对所有输入数据做归一化处理。
  • 在神经网络中,因为每个隐层的参数不同,会使得下一层的输入发生变化,从而导致每一批数据的分布也发生改变,致使网络在每次迭代中都需要拟合不同的数据分布,增加了网络的训练难度和过拟合的风险。

BN的主要作用是和主要原理 *

BN是一种正则化方法(减少泛化误差),主要作用有:

  • 使网络中每层的数据分布相对稳定,加速模型的学习速度(缓解梯度消失,支持更大的学习率)
  • BN使模型对网络中参数不太敏感,简化调参过程,学习更稳定
  • BN允许网络使用饱和性激活函数,缓解梯度消失
  • 防止过拟合: BN可以看作在各层之间加入了一个新的计算层,对数据分布进行额外的约束,从而增强模型的泛化能力
  • 降低了参数初始化的要求

基本原理

  • BN方法会针对每一批数据,在网络的每一层输入之前添加归一化处理,使输入的均值为0, 标准差为1。目的是将数据限制在统一的分布下。
  • 具体来说,针对每层的第k个神经元,计算这一批数据在第k个神经元的均值与标准差,然后将归一化后的值作为该神经元的激活值
    R语言新增一列归一化数据_神经网络_94
  • BN可以看作在各层之间加入了一个新的计算层,对数据分布进行额外的约束,从而增强模型的泛化能力
  • 但同时BN也降低了模型的拟合能力,破坏了之前学到的特征分布;为了恢复数据的原始分布,BN引入了一个重构变换来还原最优的输入数据分布。
    R语言新增一列归一化数据_随机梯度下降_95
    其中R语言新增一列归一化数据_迭代_96R语言新增一列归一化数据_迭代_97为可训练参数

BN 在训练和测试时分别是怎么做的?

  • 训练时每次会传入一批数据,做法如前述;训练时不采用移动平均,使用 BN 的目的就是为了保证每批数据的分布稳定,使用全局统计量反而违背了这个初衷;
  • 当测试或预测时,每次可能只会传入单个数据,此时模型会使用全局统计量代替批统计量(移动平均(moving averages))

5、神经网络正则化的方法有哪些?

  • L1和L2正则化: L1和L2正则化是机器学习中最常用的正则化方法,通过约束参数的L1和L2范数来减小模型在训练数据集上的过拟合现象。
  • Batch Normalization
  • 提前停止: 当验证集上的错误率不再下降,就停止迭代
  • Dropout: 集成学习的解释 每做一次丢弃,相当于从原始的网络中采样得到一个子网络。每次迭代都相当于训练一个不同的子网络,这些子网络都共享原始网络的参数。那么,最终的网络可以近似看作是集成了指数级个不同网络的组合模型。当在循环神经网络上应用丢弃法,不能直接对每个时刻的因状态进行随机丢弃,这样会损害循环网络在时间维度上记忆能力。一种简单的方法是对非时间维度的连接(即非循环连接)进行随机丢弃。
  • 数据增强: 增加数据量,提高模型鲁棒性,避免过拟合。目前,数据增强还主要应用在图像数据上,在文本等其它类型的数据还没有太好的方法。
  • 标签平滑: 在输出标签中添加噪声来避免模型过拟合

6、神经网络怎么解决梯度消失/梯度爆炸问题?

  • 选择合适的激活函数: 前馈神经网络: ReLU 循环神经网络: tanh
  • Batch Normalization
  • 采用残差网络ResNet

tensorflow

tensorflow 计算图

使用tf编写一个LR

# 计算图的输入
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])

# 模型的权重
W = tf.Variable(tf.random_normal(shape=[784, 10], mean=0, stddev=0.1, dtype=tf.float32))
# W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))

# 构建模型
pred = tf.nn.softmax(tf.matmul(X, W) + b)
# pred = tf.nn.sigmoid(tf.matmul(X, W) + b)

# 损失函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=Y, logits=labels))
# loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=pred, logits=Y))

# SGD
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

# 初始化
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    # Training_Processing,一般面试写到这儿应该就可以了
    
     for epoch in range(training_epochs):
        avg_loss = 0.
        total_batch = int(mnist.train.num_examples/batch_size)
        
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            
            _,l = sess.run([train_step,loss],feed_dict={X:batch_xs,Y:batch_ys})
            
            avg_loss += l / total_batch
            
        if (epoch+1)%display_step == 0:
            print("Epoch:", '%04d' % (epoch+1), "loss=", "{:.9f}".format(avg_loss))
    
    print("Optimization Finished!")
    
     # Test model
    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(Y, 1))
    # Calculate accuracy
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    #print("Accuracy:",sess.run([accuracy],feed_dict={X: mnist.test.images, Y: mnist.test.labels}))
    print("Accuracy:", accuracy.eval({X: mnist.test.images, Y: mnist.test.labels}))

用tensorflow实现线性回归,主要考察的是一个tf的一个实现思路。

import tensorflow as tf
import numpy as np
 
#使用numpy生成200个随机点
x_data=np.linspace(-0.5,0.5,200)[:,np.newaxis]
noise=np.random.normal(0,0.02,x_data.shape)
y_data=np.square(x_data)+noise
 
#定义两个placeholder存放输入数据
x=tf.placeholder(tf.float32,[None,1])
y=tf.placeholder(tf.float32,[None,1])
 
#定义神经网络中间层
Weights_L1=tf.Variable(tf.random_normal([1,10]))
biases_L1=tf.Variable(tf.zeros([1,10]))    #加入偏置项
Wx_plus_b_L1=tf.matmul(x,Weights_L1)+biases_L1
L1=tf.nn.tanh(Wx_plus_b_L1)   #加入激活函数
 
#定义神经网络输出层
Weights_L2=tf.Variable(tf.random_normal([10,1]))
biases_L2=tf.Variable(tf.zeros([1,1]))  #加入偏置项
Wx_plus_b_L2=tf.matmul(L1,Weights_L2)+biases_L2
prediction=tf.nn.tanh(Wx_plus_b_L2)   #加入激活函数
 
#定义损失函数(均方差函数)
loss=tf.reduce_mean(tf.square(y-prediction))
#定义反向传播算法(使用梯度下降算法训练)
train_step=tf.train.GradientDescentOptimizer(0.1).minimize(loss)
 
with tf.Session() as sess:
    #变量初始化
    sess.run(tf.global_variables_initializer())
    #训练2000次
    for i in range(2000):
        sess.run(train_step,feed_dict={x:x_data,y:y_data})
 
    #获得预测值
    prediction_value=sess.run(prediction,feed_dict={x:x_data})

Tensorflow的计算图

Tensorflow是一个通过计算图的形式来表述计算的编程系统,计算图也叫数据流图,可以把计算图看做是一种有向图,Tensorflow中的每一个节点都是计算图上的一个Tensor, 也就是张量,而节点之间的边描述了计算之间的依赖关系(定义时)和数学操作(运算时)。如下两图表示:
R语言新增一列归一化数据_神经网络_98


R语言新增一列归一化数据_神经网络_99

R语言新增一列归一化数据_神经网络_100