精华内容
下载资源
问答
  • 2019-06-13 10:22:27

    原文地址:
    https://mp.weixin.qq.com/s/xGnDcRtKKt4FyVRAMPSqYA
    讲解了添加正则项、Dropout、Early stop,数据增强、GAN,迁移学习、预训练,特征提取等等方法对小数据集训练的帮助。

    更多相关内容
  • 深度学习训练技巧总结

    万次阅读 多人点赞 2020-05-07 09:05:50
    模型训练技巧最直接的就是几个超参数的设置 根据图片大小来选择网络和超参数 如果图片不是很大比如3030,这种情况下做分类就不能用VGG和Resnet这样的网络。此时要么把图像变大要么就是选择小的网络,或者把VGG里...

    参考:

    技巧链接一!重要
    技巧链接二!重要
    技巧链接三!重要

    模型训练技巧最直接的就是几个超参数的设置

    根据图片大小来选择网络和超参数

    如果图片不是很大比如3030,这种情况下做分类就不能用VGG和Resnet这样的网络。此时要么把图像变大要么就是选择小的网络,或者把VGG里pooling的步长设置为1试试,如果类别不多(没有上千),那么直接使用小网络,如果是100100这样的大图片就采用VGG和Resnet这样的大网络。

    根据图片类别数和数量来选择batch_size

    如果训练样本少,少于1000,那么直接使用全梯度下降,不需要用批梯度下降。用批梯度的目的是为了加快训练速度,所以当训练样本少的时候是没有必要使用批梯度下降的。只是用全梯度下降反向传播一次需要很久的时间,训练起来很慢。若训练类别很多,那么bacth_size一定不要太小,例如若是上千的类别数,那么bacth_size值就设置为为128,否则震荡会很严重。

    根据网络规模和loss下降速率来选择学习率

    学习率的选择一般是0.001 0.0001 0.00001 0.000001等中的一个值,选择哪个值的最根本的依据是网络很复杂的时候学习率不能太低,否则传到后面的时候就会基本没梯度了。三五层的网络学习率基本要小于1*e^(-5),不然会下降过快导致震荡。初始学习率可以随意选择来尝试试探,如果发现loss下降得过快,那么要减少学习率。如果发现loss降低不下去,就适当增加学习率。

    深度学习的训练过程

    深度学习的训练过程大同小异,一般可以分为如下几步:

    1. 定义算法公式,也就是神经网络的前向算法,一般使用现成的网络,例如inceptionV4,mobilenet等。
    2. 定义loss,选择优化器,让loss最小。
    3. 对数据迭代训练,让loss最小。
    4. 在测试集或者验证集上对准确率评估

    深度学习模型训练过程中常遇到的问题

    问题一:收敛速度慢,训练时间长

    1. 深度学习训练过程就是一个不断调参的过程,收敛速度慢、训练时间长会使得相同总训练时间内迭代次数少,从而影响准确率。另外训练次数变少,使得尝试超参数的次数变少。
    解决办法一:设置合理的初始化权重和偏置
    1. 深度学习通过前向计算和反向传播,不断调整参数,来提取最优特征。调整的参数就是权重和偏置。根据奥卡姆剃刀法则,模型越简单越好,以线性函数这种最简单的表达式来提取特征。即f(x)=wx+b。深度学习训练时几乎所有的工作量都是用来求解w和b。训练本质也就是调整w和b的过程。
    2. 一般使用截断的正态分布(也叫作高斯分布)来初始化w。
      如下
    # 权重weight,标准差0.1。truncated_normal截断的正态分布来初始化weight。权重初始化很有讲究的,会决定学习的快慢
    def weight_variable(shape, vname):
      initial = tf.truncated_normal(shape, stddev=0.1, name=vname)
      return tf.Variable(initial)
    

    tf.truncated_normal定义如下

    tf.truncated_normal(
        shape,			# 正态分布输出数据结构,1维tensor
        mean=0.0,		# 平均值,默认为0.我们一般取默认值0
        stddev=1.0,		# 标准差
        dtype=tf.float32,		# 输出数据类型
        seed=None,		# 随机分布都会有一个seed来决定分布
        name=None
    )
    
    1. 下图左图为标准正态分布,也叫作高斯分布。利用TensorFlow中的tf.random_normal()可以得到x取值范围从负无穷到正无穷的值。所以的y值加起来为1。初始化w时,没必要将其初始化为很大或者很小的值,所以更倾向于使用截断正态分布,如下图中的右图。截断正态分布和标准正态分布的区别是:限制了x取值必须在[-2 x stddev, 2 x stddev]之间。
    2. f(x)=wx+b,b由于是加和关系,对收敛速度影响不大,一般初始化为0.如下所示
    # 偏置量bias,初始化为0,偏置可直接使用常量初始化
    def bias_variable(shape, vname):
      initial = tf.constant(0, shape=shape, name=vname)
      return tf.Variable(initial)
    
    
    解决办法二:优化学习率
    1. ,模型训练就是不断尝试和调试w和b,每次调整的幅度是多少,关系到学习率。w和b是在一定范围内调整的,增大学习率就减少了迭代次数,但学习率太大,也容易越过局部最优点,降低准确率。
    2. 所以,一般采用,一开始学习率大,从而加速收敛,训练后期学习率小一点,从而稳定地落入局部最优点。使用Adam,Adagrad等自适应优化算法,就可以实现学习率的自适应调整。从而保证准确率的同时加快收敛速度。
    解决办法三:网络节点输入值正则化batch normalization(批标准化)
    1. 神经网络训练时,每一层的输入分布都在变化,不论输入值是大还是小,学习率都是相同的,这是很浪费效率的,当输入值很小时,为了保证精细调整,学习率不能设置太大,如果让输入值标准化落到某一个范围内,如[0,1]之间,这样就不用为太小的输入值犯愁。
    2. 学习的是输入的特征分布,而不是绝对值,所以可以对每一个mini-batch数据内部进行标准化,使它们规范化到[0,1]之间。这就是bacth normalization正则化。
    3. inceptionV2在每个卷积层后,使用一个BN层,从而使得学习率可以设定为一个较大的值,使用了BN之后的inceptionV2,只需要以前的1/14的迭代次数就能达到之前的准确值,加快了收敛速度。
    4. Normalization时,选的平均值跟标准差希望它代表的是整个training set全体。但是实际上统计整个training set全体的statistics是非常耗费时间的。所以实际上算平均值和标准差的时候,只会在batch里面算。所以batch size一定要够大,如果太小的话Batch Normalization的性能就会很差,因为你没有办法从一个batch里面估测整个data集,可以想象极端case,如果batch size=1,则不能apply BN想法。
    解决办法四:采用更先进的网络结构,减少参数量
    1. 训练速度慢,归根结底是网络结构参数多,减少参数量,可以大大加快收敛速度。采用先进的网络结构可以可以用更少的参数数量达到更高的精度。如何用更少的参数数量达到更高的精度,有如下几种方法:

    方法一: 使用小卷积核代替大卷积核
    VGGNet全部使用33的小卷积核,来代替AlexNet中的1111和55等大卷积核。小卷积核虽然参数量少,但也会带来特征面积捕获过小的问题。inception net认为越往后的卷积层,应该捕获更多更高阶的抽象特征。因此它在靠后的卷积层中使用的55等大面积的卷积核的比率较高,而在前面几层卷积层中,更多使用的是11和33的卷积核。

    方法二: 使用两个串联小卷积核来代替大卷积核
    inceptionV2中提出两个33的卷积核代替一个55的卷积核,在效果相同的情况下,参数量仅为原先的332/5*5=18/25
    方法三: 1 * 1卷积核的使用
    1 * 1卷积核是性价比最高的卷积,它在参数量为1的情况下,同样能够提供线性变换、relu激活、输入输出channel变换。是VGGNet提出的1 * 1卷积核。
    方法四: 非对称卷积核的使用
    inceptionV3中将一个7 * 7的卷积拆分成了一个1 * 7和一个7 * 1的卷积核,卷积效果相同的情况下,参数量大大减小,而且还提高了卷积的多样性。
    方法五: depthwise卷积的使用
    mobileNet中将一个3 * 3的卷积拆分成了串联的一个3 * 3 depthwise卷积和一个1 * 1正常卷积。对于输入channel为M,输出为N的卷积,正常情况下,每个输出channel均需要M个卷积核对输入的每个channel进行卷积、并叠加。也就是需要M * N个卷积。而在depthwise卷积中,输出channel和输入相同,每个输入channel仅需要一个卷积核,而将channel变换的工作交给了1 * 1卷积核。这个方法在参数量减少到之前的1/9的情况下,精度仍能达到80%。
    方法六:全局平均池化代替全连接层
    AlexNet和VGGNet中,全连接层几乎占据了90%的参数量,inceptionV1使用全局平均池化来代替最后的全连接层。使得其在网络结构更深的情况下,(22层,AlexNet仅有8层)。参数量500万,是AlexNet的1/12。
    方法七:GPU并行计算
    深度学习模型训练,基本由卷积计算和矩阵乘法构成,都很适合并行运行。

    总结

    参数量的减小,加快收敛速度、减少训练时间、减小模型体积、加快预测时间、提高实时性。

    问题二:线性模型的局限性

    根据奥卡姆剃刀法则,使用最简单的线性模型即wx+b来表征神经网络。线性模型的特点是:任意线性模型的组合仍然是线性模型。即不论采用如何复杂的网络,都是线性模型。但是线性模型能够解决的问题是有限的,所以需要增加非线性元素。

    激活函数的使用
    1. 在每个卷积后,加入一个激活函数,激活函数如relu和tanh和sigmoid都是非线性函数,一方面可以增加模型的非线性元素,另一方面可以降低梯度弥散问题。目前使用较多的激活函数是relu函数。它模拟了生物学上的阈值响应机制,利用人脑只对大于某个值的信号才产生响应的机制,提出了单侧抑制的理念。relu非线性激活函数的表达式是:f(x)=max(0,x)。当x>0时,y=x,当x<0时,y=0。relu即rectified linear unit。
    2. 相比于tanh和sigmoid,relu的优点是:计算速度快,易收敛,relu是一个取max的函数,没有复杂运算,所以计算速度快,相比于tanh计算速度快6倍。第二个优点是梯度不会大幅缩小,x>0时,relu的梯度为1,梯度可以简单理解为偏导数。sigmoid函数是x稍微远离0梯度就会大幅减小,所以sigmoid激活函数会更容易出现梯度弥散的问题。
    3. 补充:梯度弥散:当使用反向传播计算导数的时候,随着网络深度的加深,反向传播梯度的幅值会显著减小,这就会造成整体的损失函数相对于最初几层的权重的导数非常小,这样当使用梯度下降法的时候,最初几层的权重变化非常缓慢,以至于不能从样本中有效的学习。
    4. 补充:与梯度弥散紧密相关的问题是:当神经网络的最后几层含有足够数量神经元的时候,可能单独这几层就足以对有标签数据进行建模,而不用最初几层的帮助。因此对所有层都进行随机初始化的方法训练得到的整个网络的性能与训练得到的浅层网络(仅有深度网络的最后几层组成的浅层网络)的性能相似。
    两个小卷积核的叠加代替一个大卷积核

    激活函数是增加非线性的法宝,但是一般只能在卷积之后使用,所以需要增加使用激活函数的场景,方法就是增加卷积层。inceptionV2提出使用两个33的卷积核代替一个55的卷积核。每次卷积后,都使用一次relu非线性激活。、

    1*1小卷积核的使用

    relu在参数量为1的条件下,能提供线性变换、relu激活、输入输出channel变换等。inceptionV1利用network in neiwork的思想,提出inception module这一结构。它在每个并行分支的最前面,使用一个1*1的卷积,卷积后紧跟一个relu激活,所以大大增加relu的使用率,提高模型的非线性特征。
    在这里插入图片描述

    问题三:过拟合问题

    过拟合指的是:一定次数的迭代后,模型准确度在训练集上越来越好,但是在测试集上越来越差,原因就是模型学习了太多无关特征,将这些特征认为是目标所应该具备的特征。
    在这里插入图片描述
    神经网络中,由于参数众多,经常出现参数比输入数据还要多的情况,导致很容易出现模型只记住了训练集特征的情况。两个方法解决这个问题:一是扩大数据量,二是减少特征量。

    方法一:输入增强,扩大样本量

    收集更多样本,可以抑制过拟合。素材整理和数据获取是深度学习的瓶颈。使用输入增强方法,对数据旋转、裁切、加入噪声等。可以增加样本数量和泛化性。tensorflow就提供了大量方法用于数据增强,方便我们增加样本数量。

    方法二:dropout,减少特征量
    1. 使用dropout,对神经网络某一层的输出节点数据随机丢弃,从而减少特征量。这实际上相当于创造了很多新的样本,可以理解为是对特征的一次采样,一般在神经网络的全连接层使用dropout。
    2. 使用丢弃法应对过拟合,丢弃法只在训练模型时使用,在测试模型时是不使用丢弃法的。
    方法三:权重衰减
    1. 权重衰减等价于L2范数正则化regularization,正则化通过为模型损失函数添加惩罚项使得学出的模型参数值较小,是应对过拟合的手段。
    2. L2正则化(权重衰减)通过惩罚绝对值较大的模型参数为需要学习的模型增加了限制,这可能对过拟合有效。实际使用中,有时会在惩罚项中添加偏差元素的平方和。
    3. 在构造优化器实例时可以通过weight_decay参数来指定权重衰减超参数。默认下pytorch会对权重和偏差同时衰减,可以分别对权重和偏差构造优化器实例,从而只对权重衰减。

    问题四:梯度弥散,无法使用更深的网络

    深度学习网络利用正向传播提取特征,同时利用反向传播调整特征。反向传播中梯度值逐渐减小,神经网络层数较多时,传播到前面几层时,梯度接近0,无法对参数做出指导性调整了,此时基本起不到训练作用,这就是梯度弥散,梯度弥散使得模型网络深度不能太大,但是网络深度越深,提取的特征越高阶,泛化性越好。

    解决办法一:relu代替sigmoid激活函数

    sigmoid函数值范围:[0,1],relu函数值范围:[0,+无穷],relu函数在x>0时导数为1,sigmoid函数,x稍微远离0,梯度就大幅减小。几乎接近0,所以在反向传播中无法指导参数更新。

    解决办法二:残差网络

    resNet将一部分输入值不经过正向传播网络,而是直接作用到输出中,这样可以提高原始信息的完整性,从而在反向传播中可以指导前面几层参数的调整。
    在这里插入图片描述
    使用了残差网络的resNet,将深度提高到152层,提高模型的泛化能力,从而提高预测准确率。

    激活函数

    sigmoid

    在这里插入图片描述
    优点:输出值是[0,1],符合概率分布。
    缺点:
    x稍微远离0,导数就接近于0了,这样在反向传播优化w时,无论w取何值,梯度都很小,也就无法对w的更新给出指导。这叫做梯度弥散,在网络层级较深时尤为明显。
    第二个缺点需要进行指数运算,计算量大。

    tanh

    在这里插入图片描述
    tanh和sigmoid很像,只是y的分布以0为中心,同样存在梯度弥散和计算耗时的问题。

    relu

    在这里插入图片描述
    使用最多的激活函数,几乎所有的cnn均使用relu作为激活函数。
    优点是:不存在梯度弥散问题,计算简单。

    损失函数

    损失函数用来衡量预测值和真实值之间的差距,目的是达到较小的损失值,这个损失值可以是局部最优解,也可以是全局最优解,全局最优解很难取得,且往往是一个过拟合的结果。损失函数有如下几种:

    损失函数的第一种:平方差

    L(Y,f(x))=(Y-f(x))^2,Y为真实值,f(x)为预测值。
    线性回归中经常使用这种形式,分类问题中不常使用。

    损失函数的第二种:交叉熵

    在这里插入图片描述
    描述两个概率分布之间的距离,在分类问题中常使用。

    优化方法

    优化方法用来指导如何调整参数w和b。来最有效率的使得损失函数达到最小值。优化方法最初需要手动调整学习率,来调整参数大小,这种手动方法麻烦,所以后面出现一些自动调整学习率的优化方法。

    优化方法一:BGD batch gradient descent

    BGD每步迭代中,都需要使用训练集的所有内容来计算梯度和误差,来指导参数的更新,这种方法由于使用了训练集中的所有数据,所以能够保证是真实有效并且不含有噪声。所以可以设置一个固定的学习率,但是计算量大。

    优化方法二: SGD stochastic gradient descent

    针对BGD计算量大的改进,随机梯度下降,每次随机抽取一定的样本计算梯度和误差,并更新参数,这种方式计算量不大,但是采用的是随机样本,所以梯度不一定是真实的梯度。带有噪声。随着梯度下降,需要减小学习率,让其稳定落入局部最优解。

    优化方法三:momentum

    针对SGD中含有噪声的改进,它将前几次的梯度也参与到本次梯度计算中来,也就是利用梯度之和来指导更新,它可以加速学习率,从而减少迭代次数,加快收敛速度。

    优化方法四:AdaGrad

    可以自动更新学习率,但是需要设置一个全局学习率,学习率表达式如下:
    在这里插入图片描述
    ϵ为全局学习率,需要设置一个固定的值。δ是一个很小的常量,大概在e^-7, 主要是为了防止分母为0.gi为第i次迭代时的梯度。可以看到随着梯度累加和的增加,学习率会降低,从而使损失函数稳定落入局部最优解。

    优化方法五:Adam Adaptive Moment Estimation自适应矩估计

    概率论中矩的定义是,如果一个随机变量服从某个分布,则其一阶矩为其平均值,即E(X)。二阶矩为其平方的平均值,即E(X^2)。Adam根据损失函数梯度的一阶矩估计和二阶矩估计来动态调整学习率。算过程如下
    在这里插入图片描述
    g为迭代运算损失函数梯度的累加和,s为梯度的一阶矩估计,r为梯度的二阶矩估计。ρ1和ρ2为衰减系数,一般ρ1=0.9,ρ2=0.999。δ目的是防止分母为0,一般取e-8。ϵ为用户设置的全局学习率,一般可设为e-4。θ为学习率。

    训练模型时的小技巧

    第一个 多尺度训练或者测试

    目标检测模型用于不同大小的图片,因而包含不同尺度的物体,很多网络并不关注输入图像的size,一个可以让模型对不同大小的输入泛化的方法是每一定的迭代过程中随机选择不同的输入尺寸,比如随机从320 * 320到608 * 608之间选择输入,而不是恒定在416 * 416。在测试的时候,也可以将图像resize到各个尺寸,得到不同尺度的框做NMS,思路和图像金字塔有点像。

    第二个 热身训练warm-up training

    yolo在早期训练阶段为每个单元中心增加一个假的真实框(先验框),采用这个额外的坐标损失来鼓励模型的预测可以匹配到检测器的先验框。

    第三个 难例挖掘hard negative mining

    因为大部分检测器是不负责检测任何物体的,这意味着正例数量要远少于负例,yolo采用一个超参数来处理这种情况,但是SSD采用难例挖掘,它并不是计算所有负例的损失,而是只计算那些预测结果最错的部分损失(即置信度较高的负例)

    第四个 NMS

    如下图,用于有效筛除多余的检测框。
    在这里插入图片描述

    第五个 Soft NMS

    这个技巧是为了解决在NMS技巧中,有可能出现的问题是,如下图,NMS会把重叠、贴近的目标筛除,下图中人和马贴的很近,所有很容易NMS就把其中一个框给删掉了。
    在这里插入图片描述

    比较NMS和Soft NMS
    1. NMS算法的思路是:先对得分排序,然后从输出结果中挑出得分最高的放入最终输出的检测结果中,接着遍历剩下的框,如果IOU重叠超过某个阈值,就直接排除这个框,遍历一次之后,再从剩下的框里按得分排序,挑出得分最高的加入最终输出的结果,如此循环直到最后输出结果里的所有的框都被挑出来或者排除掉。
    2. Soft NMS的思路是:只是在NMS思路的基础上改变了一点:IOU如果超过某个阈值,不再是直接删掉这个框,而是降低它的得分,得分如果低到一定程度就会被排除,但是如果降低后仍然比较高,就有保留下来的机会。

    热力图

    1. 通过热力图可以知道卷积神经网络是通过什么特征来分类的,这个是卷积神经网络中的隐藏特性。有一些模型把这种隐藏属性利用了,例如注意力模型,每次学习迭代中,对热力图集中部分信号加强。并且抑制其他部分。使得学习变得更加专注。也还可以查看分类因素是否正确,例如美国国防部投资 识别坦克的例子。国防部花了100万买了个模型识别坦克,确实也可以用。但是后来才发现,有坦克的场景都是阴天。原来模型识别到的是区分晴天和阴天,而不是坦克。
    2. 一般任务有回归和heatmap两种方式,heatmap相对回归来说最后的结果可能会更好一点,因为回归可能只给网络输入几个关键点的信息,而使用heatmap作为监督信号可以传递更多的信息。
    3. 在我们使用 CNN 进行图片分类时,模型到底关注的是图像的哪个区域?Grad-CAM 利用卷积网络最后一个特征图的信息,并加权对应的梯度而构建模型分类的热力图,通过该热力图,我们可以清楚地了解哪一块区域对于类别是最重要的。
    4. 这种技术不仅适用于定位,还可以用于视觉问答,图像标注等。
    5. 这种技术还在建立精确模型的数据需求方面有帮助。

    如何知道 CNN 究竟在寻找什么?答案就是,Grad-CAM。即加权梯度类激活映射

    补充小知识点:

    1. 经典的卷积神经网络有一个问题是它只能接受固定大小的输入图像,这是因为第一个全连接层和它之前的卷积层之间的权重矩阵大小是固定的,而卷积层、全连接层本身对输入图像的大小并没有限制。而在做目标检测时,卷积网络面临的输入候选区域图像大小尺寸是不固定的。
    2. 让一个已经设计好的DCNN模型,可以支持任意大小图片输入,其中一种方案是全卷积网络(FCN),即去掉所有全连接层,全部由卷积层来替代。
    3. 在卷积神经网络中,卷积层并不要求输入图像的尺寸固定,只有第一个全连接层需要固定尺寸的输入,因为它和前一层之间的权重矩阵是固定大小的,其他的全连接层也不要求图像的尺寸固定。如果在最后一个卷积层和第一个全连接层之间做一些处理,将不同大小的图像变为固定大小的全连接层输入就可以解决问题。

    超参数的设定

    输入数据像素大小
    1. 使用卷积网络处理图像问题时,对不同输入图像为了得到同等规格的输出,同时也为了GPU设备并行,统一将图像压缩到2的n次幂大小。例如imagenet数据集常用的224x224像素。
    2. 如果不考虑显存大小的限制,更高分辨率图像作为输入数据有助于网络性能的提升。特别是对基于注意力模型的深度网络提升更显著。
    3. 但是高分辨率图像会增加模型计算消耗而导致网络整体训练时间延长。
    4. 一般卷积神经网络都采用全连接层作为最后分类层,若直接改变原始网络模型的输入图像分辨率,会导致原始模型卷积层的最终输出无法输入全连接层的情况,此时需要重新改变全连接层输入滤波器的大小或者是重新指定其他相关参数。
    卷积层参数的设定
    1. 卷积层的超参数主要包括卷积核大小、卷积操作的步长和卷积核的个数。
    2. 小卷积核比大卷积核相比有两个优势:
      (1)优点一:增强网络容量和模型复杂度
      (2)优点二:减少卷积参数个数
    3. 实践中推荐使用3x3和5x5这样的小卷积核,其对应卷积操作步长建议设置为1.
    4. 卷积操作前还可以搭配填充操作padding。填充操作的两个优点:
      (1)优点一:可以充分利用和处理输入图像的边缘信息。
      (2)优点二:搭配合适的卷积层参数可以保持输出与输入同等大小,而避免随着网络深度增加,输入大小的急剧减小。
    5. 例如,当卷积核大小为3x3,步长为1时,可以将输入数据上下左右各填充1各单位的黑色像素,则padding=1,值为0,所以也叫作zeros-padding。这样做可以保持输出结果与原来的输入同等大小。
    6. 当卷积核为5x5,步长stride为1时,指定padding=2,也可以保持输出与输入等大。
    7. 总结:对于卷积核大小f x f,步长为1的卷积操作,当padding为p=(f-1)/2时,可以维持输出与原来的输入等大。

    8. 为了硬件字节级存储管理的方便,卷积核个数通常设置为2的次幂,这样的设置有利于硬件计算过程中划分数据矩阵和参数矩阵,尤其在利用显卡计算时更为显著。
    池化层参数的设置
    1. 和卷积核大小设置一样,池化层的核大小一般也设置为较小的值,如2x2,3x3等。常用的参数设定是2x2,池化层步长是2,在这个常用的设置下,输出结果大小仅仅为输入数据长宽大小的四分之一。即输入数据中有75%的响应值被丢弃,这就起到了下采样的作用。
    2. 为了不丢弃过多输入响应而损失网络性能,池化操作极少超过3x3大小的池化操作。

    训练技巧

    训练数据随机打乱
    1. 信息论:从不相似的事件中学习总是比从相似事件中学习具有更多的信息量。
    2. 训练卷积神经网络时,尽管训练数据固定,但是采用了随机批处理mini-batch的训练机制,因此可以在模型每轮epoch训练进行前将训练数据集随机打乱,确保模型不同轮次相同批次看到的数据是不一样的。
    3. 这种打乱操作提高模型的收敛速度,也能提升模型在测试集上的预测结果。
    学习率的设定
    1. 学习率设定需要遵循下面两个原则:
    2. 模型训练开始的时候,初始学习率不应该过大,以0.01和0.001最好。
    3. 如果刚开始训练没有几个批次mini-batch,模型的目标损失值就急剧上升,这就说明模型训练的学习率过大,此时应该减小学习率从头训练。
    4. 模型训练过程中,学习率应该随着轮数增加而减缓,减缓机制有三种:
      (1)方式一:轮数减缓step decay,例如五轮训练后学习率减半,下一个五轮后再次减半。
      (2)方式二:指数减缓。学习率按照训练轮数增长指数插值递减等
      (3)方式三:分数减缓。
    5. 寻找理想学习率或者是诊断模型训练学习率是否合适时可以借助模型训练曲线。下图中的红色曲线是理想学习率曲线。曲线表示:不同的学习率下训练损失值随着训练轮数增加呈现的状态
      在这里插入图片描述

    批规范化操作BN

    1. BN加快了模型的收敛速度,也在一定程度上缓解了梯度弥散问题。
    2. 目前BN几乎用于所有卷积神经网络。
    3. BN是在模型每次随机梯度下降训练时,通过mini-batch来对相应的网络响应做规范化。使得结果输出信号各个维度的均值为0,方差为1.
    4. BN操作共分为四步:

    (1)第一步:计算批处理的数据均值
    (2)第二步:计算批处理的数据方差
    (3)第三步:根据均值和方差对该批数据做规范化
    (4)第四步:尺度变换和偏移,是为了让因训练所需而刻意加入的BN能有可能还原最初的输入,从而保证整个网络的容量。

    1. BN能起作用的原因

    (1)在统计机器学习中的一个经典假设是:源空间和目标空间的数据分布是不一致的,如果不一致,那么出现新的机器学习领域即迁移学习。
    (2)协变量偏移是分布不一致假设下的一个分支问题,它是指源空间和目标空间的条件概率是一致的,但是其边缘概率是不同的。
    (3)对于神经网络的各层输出,由于它们经过了层内操作,其分布显然与各层对应的输入信号分布不一样,而且差异会随着网络深度增大而越来越大。但是它们所指示的样本标记仍然保持不变,这就符合了协变量偏移的定义。
    (4)可以通过BN来规范化某些层或所有层的输入,从而可以固定每层输入信号的均值和方差。这样的话,即使网络模型较深层的响应或者梯度很小,也可以通过BN的规范化作用将其的尺度变大。这样就可以解决深层网络训练很可能带来的梯度弥散。

    1. BN的使用位置

    (1)在卷积神经网络中BN一般应该作用在非线性映射函数前
    (2)在神经网络训练时遇到收敛速度慢或者是梯度爆炸等无法训练的情况,也可以尝试用BN解决。
    (3)常规使用情况下,同样可以加入BN来加快模型的训练速度,甚至提高模型精度。

    1. BN的变种也作为一种有效的特征处理手段应用于人脸识别等任务中,即特征规范化。FN。FN作用于网络最后一层的特征表示上,FN的下一层是目标函数层。FN的使用可以提高习得特征的分辨能力,适用于类似人脸识别、行人重检测、车辆重检测等。

    优化算法

    梯度下降法在每次迭代求解机器学习目标函数最优解时,需要计算所有训练集样本的梯度。如果训练集很大,特别是如果训练数据上万甚至上百万,所以梯度下降这种方法的效率很低。而且硬件限制所以这种做法在实际中不现实。随机梯度下降是通过每次计算一个样本来对模型参数迭代,这样只需要几百或者是几千样本便可以得到最优解,所以随机梯度下降比梯度下降效率高。但是缺点也就在于:随机梯度下降法由于每次计算只考虑一个样本,使得它每次迭代并不一定都是模型整体最优的方向,如果样本噪声多,基于随机梯度下降法的模型很容易陷入局部最优解而收敛到不理想的状态。所以深度学习中,仍然需要遍历所有的训练样本,每次遍历训练集样本一次称为训练经过了一轮epoch。在深度学习中,将SGD经过了改造,每次选取一批样本,利用这批样本上的梯度信息完成一次模型的更新。每在一批数据上训练一次,称之为一个batch的训练。所以批处理的SGD相比经典的SGD更加稳定。

    随机梯度下降法
    1. SGD即每次批处理训练时计算网络误差并且做误差的反向传播,然后根据一阶梯度信息对参数更新。
    2. 一阶梯度信息完全依赖于当前批数据在网络目标函数上的误差,故可以将学习率理解为当前批的梯度对网络整体参数更新的影响程度。
    3. 随机梯度下降是最常见的神经网络优化方法,收敛效果稳定但是速度过慢。
    基于动量的随机梯度下降
    1. 基于动量的随机梯度下降用于改善SGD更新时可能产生的震荡现象,通过积累前几轮的动量信息辅助参数更新。
    2. 基于动量的随机梯度下降除了可以抑制震荡,还可以在网络训练中后期趋于收敛,网络参数在局部最小值附近来回震荡时帮助其跳出局部限制,找到更优的网络参数。
    3. 对于动量因子,除了设置为0.9的静态设定方式,还可以将其设置为动态因子。常用的动态设定方式是将动量因子初始值设置为0.5,之后随着训练轮数增长逐渐变为0.9或者是0.99.
    Nesterov型动量随机下降法
    1. 这种方法是在上述动量梯度下降法更新梯度时加入对当前梯度的校正。相比于一般动量法,这个方法对于凸函数在收敛性上有更强的理论保证。

    总结:

    1. 上面介绍的三种优化算法都是为了使得梯度更新更加灵活,对于优化神经网络这种拥有非凸且异常复杂函数空间的学习模型尤为重要。
    2. 但是上面介绍的三种优化算法的局限性在于:因为稍微小的学习率更加适合网络后期的优化,但是这些方法的学习率却一直固定不变,并未将学习率的自适应性考虑进去。
    Adagrad法
    1. 针对学习率自适应问题,该方法根据训练轮数的不同,对学习率进行了动态调整。
    Adadelta法
    1. 该方法是对Adagrad法的扩展,通过引入衰减因子消除Adagrad法对于全局学习率的依赖。
    RMSProp法
    1. 该方法可以看成是Adadelta法的一个特例。
    2. 但是RMSProp依然利用全局学习率是它的一个缺陷。
    Adam法
    1. 该方法本质上是带有动量项的RMSProp,它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。
    2. 该方法的优点在于经过偏置校正后,每一次迭代学习率都有一个确定的范围,这样可以使得参数更新更加平稳。

    微调神经网络

    1. 除了从头训练自己的网络,一种更高效的方法是微调已经预训练好的网络模型。
    2. 微调预训练模型就是用目标任务数据在原先预训练模型上继续进行训练。
    3. 由于网络已经在原始数据集上收敛,所以应该设置较小的学习率在目标数据上微调,如10^-4数量级或者以下。
    4. 卷积神经网络的浅层拥有更广泛的特征,例如边缘、纹理等。深层网络特征对应高层语义。所以在新数据上微调时,浅层的泛化特征更新的程度比较小。而深层的高层语义更新的程度比较大。所以可以根据层深对不同层设置不同的学习率。深层网络的学习率可以稍微大于浅层网络的学习率。
    5. 根据目标任务与原始数据相似程度采用不同的微调策略:
    6. 当目标数据较少且目标数据与原始数据非常相似时,可以仅仅微调网络靠近目标函数的后几层。
    7. 当目标数据充足且相似时,可以微调更多网络层,也可以全部微调。
    8. 当目标数据充足但是与原始数据差异较大时,此时要多调节一些网络层,直至微调全部。
    9. 当目标数据极少,同时还与原始数据有较大差异时,可以尝试先微调网络后几层再微调整个网络模型。
    10. 针对目标数据极少 ,同时还与原始数据有较大差异的情况,一种方法是:借助部分原始数据与目标数据协同训练。因为预训练模型的浅层网络特征更具有泛化性,所以可以在浅层特征空间选择目标数据的近邻作为原始数据子集。之后,将微调阶段改造为多目标学习任务。一是将目标任务基于原始数据子集,二是将目标任务基于全部目标数据。
    11. 总结:

    (1)关于模型参数的优化算法选择,随机梯度下降法是目前使用最多的网络训练方法。
    (2)在理想的网络参数初始化和学习率设置方案下,随机梯度下降法得到的网络更稳定,结果更可靠。
    (3)若希望网络更快收敛且需要训练较复杂结构的网络时,推荐使用Adagrad、Adadelta、RMSProp、Adam等优化算法。
    (4)Adagrad、Adadelta、RMSProp和Adam是性能相近算法,在相同问题上表现并无较大差异。
    (5)随机梯度下降、动量法随机梯度下降和Nesterov型动量法也是性能相近的算法。
    (6)上面讲到的算法都是一阶梯度算法,基于牛顿法的二阶优化算法也是存在的。但是直接使用二阶方法用于深度卷积网络优化目前是不现实的。因为这种方法需要在整体海量的训练集上计算海森矩阵,会带来巨大的计算代价。

    不平衡样本的处理

    1. 不平衡的训练样本会导致训练模型侧重样本数目较多的类别,而轻视样本数目较少的类别。这样模型在测试数据上的泛化能力会受到影响。
    2. 从数据层面和算法层面解决不平衡样本问题。
    数据层面处理方法
    1. 数据层面处理方法借助数据采样阀使得整体训练集样本趋于平衡。
    一:数据重采样
    1. 简单的数据重采样包括上采样和下采样。
    2. 对于样本较少类,使用上采样,即复制该类图像直至与样本最多类的样本数一致。也可以用数据扩充方式来代替简单的复制操作。
    3. 对于样本较多类别,使用下采样。
    4. 对深度学习而言,下采样并不是随机丢弃一部分图像,因为那样做会降低训练数据多样性进而影响模型泛化能力。
    5. 正确的下采样方式是:在批处理训练时对每批随机抽取的图像严格控制其样本较多类别的图像数量。
    6. 如果仅仅使用数据上采样可能会引起模型过拟合,更保险和有效的数据重采样是上采样和下采样结合使用。
    二:类别平衡采样
    1. 把样本按照类别分组,每个类别生成一个样本列表。
    2. 训练过程中先随机选择一个或者几个类别,然后从各个类别所对应的样本列表中随机选择样本,这样可以保证每个类别参与训练的机会比较均衡。
    3. 但是这种方法不适用于海量类别任务。
    4. 在类别平衡采样的基础上,还有类别重组的平衡方法。
    5. 类别重组法:只需要原始图像列表即可完成同样的均匀采样任务。
    6. 类别重组的过程:首先按照类别顺序对原始样本进行排序,之后计算每个类别的样本数目。记录样本最多的那个类别的样本数量。之后,根据这个最多样本数对每类样本产生一个随机排列列表。然后用这个列表中的随机数对各自类别的样本数求余,得到对应的索引值。接着根据索引值从该类的图像中提取图像,生成该类的图像随机列表。之后把所有类别的随机列表连在一起随机打乱次序,即可得到最终图像列表。可以发现最终列表中每类样本数目均等。根据此列表训练模型,当训练列表遍历完毕,则重头再做一遍上述操作即可。进行第二轮训练,如此重复下去。
    7. 类别重组法的优点在于:只需要原始图像列表,且所有操作均在内存中在线完成,易于实现。类别重组法与数据下采样有异曲同工之意。
    算法层面处理方法
    1. 对于不平衡样本导致样本数目较少的类别欠学习这一现象,一个解决办法是:增加小样本错分的惩罚代价,并将此惩罚代价直接体现在目标函数中,即代价敏感方法。
    2. 这样通过优化目标函数就可以调整模型在小样本上的注意力。算法层面处理不平衡样本问题的方法多从代价敏感角度出发。
    一:代价敏感方法
    1. 代价敏感方法有两种,一个是基于代价敏感矩阵,另一个是基于代价敏感向量。
    2. 通过指定代价敏感矩阵或者是代价敏感向量的错分权重,可以缓解样本不平衡带来的影响。

    模型集成方法

    1. 集成学习是机器学习中的一类学习算法。指的是训练多个学习器并且将它们组合起来使用的方法。
    2. 集成学习通常会比单个学习器有更好的预测结果。
    3. 深度模型的集成从数据层面和模型层面两方面着手。

    数据层面的集成方法

    一:测试阶段数据扩充
    1. 把在训练阶段用到的数据扩充手段用在测试集上
    二:简易集成法
    1. 是一种针对不平衡样本的集成学习方法。
    2. 思路是:对于样本较多的类采取降采样,每次采样数依照样本数目最少的类别而定,这样每类取到的样本数可以保持均等。
    3. 采样结束后,针对每次采样得到的子数据集训练模型,采样、训练反复进行多次。
    4. 最后对测试数据的预测依据训练得到若干个模型的结果取平均或者是投票获得。
    5. 简易集成除了能实现模型集成,还能缓解数据不平衡。

    模型层面的集成

    一:单模型集成

    多层特征融合

    1. 多层特征融合是针对单模型的集成方法。
    2. 网络不同层特征富含的语义信息可以相互补充。
    3. 在图像语义分割、细粒度图像检索、基于视频的表象性格分析等任务中经常用到多层特征融合策略。
    4. 多层特征融合时可以直接将不同层网络的特征级联。
    5. 在特征融合时关于网络层的选取:最好使用靠近目标函数的几层卷积特征,因为越深层的特征包含的高层语义越强,分辨能力也越强。如果是选择网络的浅层特征,用于特征融合很可能起不到作用,可能甚至会起到反作用。

    网络“快照”集成

    1. 深度神经网络模型复杂的解空间中存在很多的局部最优解,但是批处理随机梯度下降法mini-batch SGD只能让网络模型收敛到其中一个局部最优解。
    2. 网络快照集成就是利用网络解空间的这些局部最优解来对单个网络做模型集成。
    3. 通过循环调整学习率可以使得网络依次收敛到不同的局部最优解。
    4. 将收敛奥不同局部最优解的模型保存可以得到M个处于不同收敛状态的模型。
    5. 测试阶段,做模型集成时,由于深度网络在初始训练阶段未必拥有优越性能,所以在测试阶段,一般挑选最后m个模型快照用于集成。
    多模型集成

    多模型的生成策略

    1. 第一种:同一模型不同初始化:不同的网络模型参数初始化会导致不同的训练结果。
    2. 实际中,特别是小样本学习,首先对同一模型不同初始化操作,之后将得到的网络模型进行结果集成会大幅缓解其随机性,提升最终任务的预测结果。
    3. 第二种:同一模型的不同训练轮数:如果网络超参数设置得当,深度模型随着网络训练的进行会逐步趋于收敛,但是不同训练轮数的结果仍有不同,无法确定到底哪一轮训练得到的模型最适用于测试数据。
    4. 所以简单的解决办法是:将最后几轮训练模型结果集成,这样既能够降低随机误差,也可以避免训练轮数过多带来的过拟合风险。
    5. 这种操作叫做轮数集成。
    6. 第三种:不同目标函数: 选择不同的目标函数即损失函数可以使得网络学习到不同的特征表示。
    7. 以分类任务为例,可以将交叉熵损失函数、合页损失函数、大间隔交叉熵损失函数、中心损失函数作为目标函数分别训练模型。
    8. 在预测阶段,既可以直接对不同模型预测结果做置信度级别的平均或者投票,也可以做特征级别的模型集成。
    9. 将不同网络得到的深度特征抽取后级联作为最终特征,之后再离线训练浅层分类器(如支持向量机)完成预测任务。
    10. 第四种:不同网络结构: 操作时可以在VGG或者深度残差网络等不同的架构上训练模型,最后将不同架构网络得到的结果集成。

    总结:

    1. 多模型集成上,可以通过不同参数初始化、不同训练轮数和不同目标函数的设定产生多个网络模型的训练结果。最后使用平均法、投票法和堆叠法进行结果集成。
    2. 之前提到的随机失活dropout实际上也是一种隐式的模型集成方法。

    梯度累积的trick

    1. 一般增大batch size会使得最终的预测效果变好,但是GPU显存是有限的,不可能无限增大batch size,这时候梯度累积就发挥作用了。
    2. 梯度累积就是累积多个batch的梯度然后一次更新参数,而不是常用的一个batch更新一次,这种trick在小数据集上是有效果提升的。
    #loss,preds,step_acc = train_step(model,inputs,labels,criterion,optimizer)
    #将batch_accumulate_size个batch的梯度累积起来,只在最后一侧更新网络参数
    inputs = inputs,to(DEVICE,dtype=torch.float)
    labels = labels.to(DEVICE,dtype=torch.float)
    if step % batch_accumulate_size == 0:
        optimizer.zero_grad()
    with torch.set_grad_enables(True):
        #forward
        outputs = model(inputs)
        #下面式子中损失值要除以batch_accumulate_size的原因是在使用梯度积累这个trick时,
        # 需要确保累积梯度的平均值与之前的相同,所以为了使得梯度变得相同就需要在每次batch_accumulate_size时
        # 将损失值除以batch_accunulate_size值。
        # 如果进行了除以batch_accumulate_size操作后,就无需更改学习率,如果不进行出发操作,就要将学习率除以iter_size来获得相同的性能
        # 在使用这个梯度累积trick时,假设使用SGD作为优化器。
        loss = criterion(outputs,labels.long())/batch_accumulate_size#一定要除以这个batch_accumulate_size。
        loss.backward()
        _,preds = torch.max(outputs,1)
    correct_num = torch.sum(preds == labels.long())
    step_acc = correct_num.double()/inputs.size(0)
    if (step + 1) % batch_accumulate_size == 0:
        optimizer.step()#只在最后一次更新网络参数
    loss = batch_accumulate_size * loss.item()#转换为数字方便后面使用
    step_acc = step_acc.item()
    
    

    训练时要多去尝试不同的模型。

    1. 将多个模型的输出集成起来,粗暴一点就是直接将输出的概率值求平均再取top3即得到最终的输出。

    predictions balancing trick

    1. 测试集中的groundtruth分布应该是均匀的,而且(训练集样本数目+1)/类别数目=330(对应于一个特定比赛的计算结果)。这一点很重要,通过对模型输出的概率按照这个规律后处理,平均给每个模型带来0.7%的提升。
    2. 后处理的算法思路:对于当前最多的预测类别,将所有这个类别对应的概率不断减去一个很小的数,直到这个类别不是最多的,重复上面的过程直到预测类别差不多均匀。
    3. 类似上面思路的算法可以分解为如下四步
      (1)先对每一种类别赋一个初始为1的系数coeddicients,当前预测概率等于实际概率乘以对应的系数。
      (2)计算每种类别的数目,按照这个数目再计算一个score,逻辑是预测越均匀则score越大。
    4. 对最多的类别label,执行coefficients[label] -= alpha
    5. 若还没有达到最大迭代次数,就继续执行第2步和第3步,执行过程中记录最大的score对应的coefficients,迭代完成后返回这个coefficients。
      算法的实现代码:pytorch实现链接
    可能存在输入数据图片尺寸越大分数则越高,但是由于显存限制,尺寸越大也就会越难训练。
    经常保存checkpoint带来的提升在于:snapshot ensembling,即一个模型最终的预测输出是这个模型的几个checkpoint的综合,最后的输出是多个模型的平均blend。
    对于超大数据集的图像类比赛,一般网络越深、图片尺寸越大、batchsize越大,则性能就越好。
    展开全文
  • 深度学习训练技巧

    千次阅读 2017-05-03 11:37:12
    本文主要介绍8种实现细节的技巧或tricks:数据增广、图像预处理、网络初始化、训练过程中的技巧、激活函数的选择、不同正则化方法、来自于数据的洞察、集成多个深度网络的方法原文如下:... 数据增广在不改变图像类别的...

    本文主要介绍8种实现细节的技巧或tricks:数据增广、图像预处理、网络初始化、训练过程中的技巧、激活函数的选择、不同正则化方法、来自于数据的洞察、集成多个深度网络的方法原文如下:http://blog.csdn.net/u013709270/article/details/70949304

    1. 数据增广

      在不改变图像类别的情况下,增加数据量,能提高模型的泛化能力。

      自然图像的数据增广方式包括很多,如常用的水平翻转(horizontally flipping),一定程度的位移或者裁剪和颜色抖动(color jittering)。此外还可以尝试多种操作的组合, 例如同时做旋转和随机尺度变换,此外还可以把每个patch中所有像素在HSV颜色空间中的饱和度和明度提升0.25-4次幂方,乘以0.7-1.4之间的一个因子,再加一个-0.1-0.1之间的值。同样你可以在色调通道(H)对每张图片或patch的所有像素增加一个-0.1~0.1之间的值。

    2. 预处理

    2.1 最简单的预处理方法
    •零均值化
    •标准化

    2.1.1 为什么要零均值化

       数据有过大的均值可能导致参数的梯度过大,如果有后续的处理,可能要求数据零均值,比如PCA。零均值化并没有消除像素之间的相对差异,人们对图像信息的摄取通常来自于像素之间的相对色差,而不是像素值的高低。
    

    2.1.2 为什么要归一化

       归一化是为了让不同维度的数据具有相同的分布。假如二维数据(X1,X2)两个维度都服从均值为零的正态分布,但是X1方差为100,X2方差为1。那么对(X1,X2)进行随机采样在二维坐标系中绘制的图像,应该是狭长的椭圆形。 
    

    对这些数据做特征提取会用到以下形式的表达式:

    S = w1*x1 + w2*x2 + b;

    那么参数W1,W2的梯度为:

    dS / dw1 = x1 ; dS / dw2 = x2

       由于x1与x2在分布规模上的巨大差异,w1与w2的导数也会差异巨大。此时绘制目标函数(不是S)的曲面图,就像一个深邃的峡谷,沿着峡谷方向变化的是w2,坡度很小;在峡谷垂直方向变化的是w1,坡度非常陡峭,如图1,而我们期望的目标函数是图2这样的。
    
       目标函数是非常难以优化的,因为w1和w2的梯度差异太大,所以在两个维度上需要不同的迭代方案。但在实际操作中,为了方便,我们通常为所有维度设置相同的步长,随着迭代的进行,步长的缩减在不同维度也是同步的。这就要求w不同纬度的分布规模大致相同,而这一切都始于数据的归一化。
    

    2.1.3 实现代码

    X-=numpy.mean(X,axis=0) # 即X的每一列都减去该列的均值1
    1

    注:对于灰度图像,零均值化也可以减去整张图片的均值:X-=numpy.mean(X)

    X/=numpy.std(X,axis=0) # 数据归一化。1
    1

       X是输入数据,(图片数目X图片维度)。另一种标准化(normalize)方式是标准化每个维度,保证每个维度的最大值和最小值是-1和1。这种预处理的方式只在输入的各个特征的尺度或者单位不同时才有意义。以图片像素作为输入为例子,所有像素值尺度都在0-255这个尺度之间,所以没必要严格的执行这种预处理操作。在自然图像上进行训练时,可以不进行归一化操作,因为理论上图像任一部分的统计性质都应该和其他部分相同,图像的这种特性被称作平稳性(stationarity)
    

    2.2 白化(Whitening)

       白化相当于在零均值化和归一化操作之间插入一个旋转操作,将数据投影到主轴上。一张图片经过白化后,可以认为每个像素之间是统计独立的。然而白化很少在卷积神经网络中使用,可能原因是图像信息本来就是依靠像素之间的相对差异来体现的,白化让像素间去相关,让这种差异变得不确定,损失了信息。
    
       首先将数据零均值化,再计算协方差矩阵(convariance matrix)来观察数据中的相关结构。
    

    X-=np.mean(X,axis=0)
    cov=np.dot(X.T,X)/X.shape[0] #计算协方差矩阵1
    2
    1
    2

    然后做去相关操作,即通过将原始数据(零均值化后的数据)投影到特征基空间(eigenbasis)。

    U,S,V=np.linalg.svd(cov) #计算数据协方差矩阵的奇异值分解(SVDfactorization)
    Xrot=np.dot(X,U) #对数据去相关1
    2
    1
    2

    最后一步变换是白化,即把特征基空间的数据除以每个维度的特征值来标准化尺度。

    Xwhite=Xrot/np.sqrt(S+1e-5) #除以奇异值的平方根,注意到这里加了个1e-5是为了防止分母是0的情况。1
    1

       PCA白化的一个缺点是会增加数据中的噪声,因为它把输入数据的所有维度都延伸到相同的大小,这些维度中就包含噪音维度(往往表现为不相关的且方差较小)。这种缺点在实际操作中可以通过把1e-5增大到一个更大的值来引入更强的平滑。
    
    1. 初始化

    3.1 不要将参数全部初始化为零

       几乎所有的CNN网络都是堆成结构,将参数零初始化会导致流过网络的数据也是对称的(都是零),并且没有办法在不受扰动的情况下打破这种数据对称,从而导致网络无法学习。 
        参数零初始化时,无论输入是什么,中间神经元的激活值都是相同的(任意一个神经元的激活值a=f(WTX),当权重W是零向量时,WTX也是零向量,因此经过激活函数后激活值都相同),反向传播过程中计算的梯度也是相同,每个权重参数的更新因此也是相同的,网络因此失去了不对称性。
    

    3.2 用小的随机数初始化

       初始化参数应该非常接近于零(但不全等于零),来打破网络的对称性。初始参数应该是随机且独立的来保证每个参数更新过程是不同的。给每个参数随机赋予一个接近零的值:
    

    W=0.01*numpy.Random.randn(D,H)1
    1

    randn方法生成一个零均值,方差为1的正态分布的随机数,同样也可以换用数值较小的均匀分布来产生初始化参数,但在实践中两种方法最终结果差别不大

    3.3 方差归一化

       用随机初始化方法来初始化参数会导致输出S的方差随输入数量(X或W向量的维度)增加而变大。 
    

    独立随机变量和的方差具有以下性质:

    Var(A+B+C)=Var(A)+ Var(B)+ Var(C)
    S = w1*x1 + w2*x2 +…+wi*xi+ b 1
    2
    1
    2

    S是多个随机变量的加权和,假设W各维度之间相互独立,随着数据维度增长,S的方差将会线性积累,由于数据的维度随任务的不同,是不可控的,所以我们希望将S的方差做归一化,这只需要对W做处理就可以了:

    W=numpy.random.randn(n)/sqrt(n) #n是数据维度1
    1

    上面操作是正确的推导过程:
    令 n*Var(W) = 1,就得到std(W) = 1 / sqrt(n)。
    注意:现在更多的论文中在实际中都在用ReLUs函数,针对ReLUs推荐:
    w=numpy.random.randn(n)*sqrt(2.0/n)

    1. 训练过程中

    4.1 卷积滤波器和池化层大小

       输入数据最好是2的整数幂次方,比如32(CIFAR-10中图片尺寸),64,224(ImageNet中常见的尺寸)。此外采用较小尺寸的滤波器(例3x3),小的步长(例1)和0值填充,不仅会减少参数数量,还会提升整个网络的准确率。当用3x3的滤波器,步长为1,填充(pad)为1时,会保持图片或特征图的空间尺寸不变。池化层经常用的池化大小是2x2。
    

    4.2 学习率

       使用验证集是获得合适LR(Learning Rate)的有效手段。开始训练时,LR通常设为0.1。在实践中,当你观察到在验证集上的loss或者准确率不在变化时,将LR除以2或5后继续跑。
    

    4.3 在预训练的模型上微调

       很多state-of-the-arts deep networks的模型被开源出来,这些预训练的模型泛化能力(generalization abilities)很强,因此可以在这些模型的基础上根据自己的任务微调。微调涉及两个重要的因素:新数据集的大小和两个数据集的相似度。网络顶层特征包含更多dataset-specific特征。
    

    数据集相似性高

    数据集相似性低

    数据少 直接提取顶层特征来训练线性分类器 比较困难,尝试用不同层的特征训练一个线性分类器
    数据多 用较小的学习率微调更多的层 用较小的学习率微调尽可能多的层

    1. 激活函数

      激活函数用于在网络中引入非线性。sigmoid 与 tanh 曾经很流行,但现在很少用于视觉模型了,主要原因在于当输入的绝对值较大时,其梯度(导数)接近于零,这时参数几乎不再更新,梯度的反向传播过程将被中断,出现梯度消散的现象。

    这里写图片描述

    激活函数示意图,图片来自斯坦福 Stanford CS231n

    这里写图片描述

    Sigmoid 激活函数

    这里写图片描述

    tanh 激活函数

    这里写图片描述

    ReLU 激活函数

    ReLU 优点:
    •实现起来非常简单,加速了计算过程。
    •加速收敛,没有饱和问题,大大缓解了梯度消散的现象。

    ReLU 缺点:

    就是它可能会永远“死”掉,假如有一组二维数据 X(x1, x2)分布在 x1:[0,1], x2:[0,1] 的区域内,有一组参数 W(w1, w2)对 X 做线性变换,并将结果输入到ReLU。

    F = w1*x1 + w2*x21
    1

    如果 w1 = w2 = -1,那么无论 X 如何取值,F 必然小于等于零。那么 ReLU 函数对 F 的导数将永远为零。这个 ReLU 节点将永远不参与整个模型的学习过程。

    为了解决ReLU 在负区间的导数为零的问题,人们发明了 Leaky ReLU, Parametric ReLU, Randomized ReLU 等变体,他们的中心思想都是为ReLU 函数在负区间赋予一定的斜率,从而让其导数不为零(这里设斜率为 alpha)。

    Leaky ReLU 就是直接给 alpha 指定一个固定的值,整个模型都用这个斜率:
    Parametric ReLU 将 alpha 作为一个参数,通过从数据中学习获取它的最优值。
    Randomized ReLU 的alpha 是在规定的区间内随机选取的,在测试阶段是定值。
    有学者将当前最优的两类CNN网络结合不同的激活函数在CIFAR-10,CIFAR-100和NDSB数据集上做实验,评价四种激活函数的优劣。 实验结果表明Leaky ReLU取较大的alpha准确率更好。Parametric ReLU很容易在小数据集上过拟合(训练集上错误率最低,测试集上不理想),但依然比ReLU好。RReLU效果较好,实验表明它可以克服模型过拟合,这可能由于alpha选择的随机性。在实践中, Parametric ReLU 和 Randomized ReLU 都是可取的。

    1. 正则化(Regularizations)

      以下是几种常用的方通过控制模型的容量来阻止 神经网络 的过拟合(Overfitting)。

    6.1 L2正则化

       L2正则化也许是最常用的正则化的形式。它可以通过将模型中所有的参数的平方级作为惩罚项加入到目标函数(objective)中来实现。也就是说,对网络中的每一个权重w ,我们将其项 12λw2 加入到目标函数中,其中λ 是正则化的强度参数。在惩罚项公式的前面加上12是很常见的,这样做的原因是因为优化函数12λw2 求导的时候不至于前面产生一个常数项因子2,而只是λw 这样简单的形式。对L2正则化的直观的解释是,L2正则化对尖峰向量的惩罚很强,并且倾向于分散权重的向量。
    

    6.2 L1正则化

       L1正则化是另一个相关的常见的正则化方式。这里,对于网络中的每一个权重w ,我们都会加上一个项λ|w| 到目标函数中。L1正则化有一个非常有趣的属性,那就是它会使得权重向量w在优化期间变得稀疏(例如非常接近零向量)。 带有L1正则化项结尾的神经网络仅仅使用它的最重要的并且接近常量的噪声的输入的一个稀疏的子集。相比之下,最终的权重向量从L2正则化通常是分散的、小数字。在实践中,如果你不关心明确的特征选择,可以预计L2正则化在L1的性能优越。
    

    6.3 最大范数约束

       正规化的另一种形式是实施绝对上限的大小在每个神经元的权向量中,利用投影梯度下降来强制约束。在实践中,这对应于执行参数正常更新,然后执行夹紧约束的vec { w }每个神经元的权向量满足平行vec { w } parallel_2 < c。典型的c值是3或4的订单。有些人报告改进在使用这种形式的正规化。其吸引人的特性之一是网络不能“爆炸”即使学习速率
    

    6.4 Dropout

       Dropout是一个极其有效的、简单的并且是最近才被提出的正则化技术作为以上三种正则化方法(L1、L2、最大范数约束)的补充。在训练期间,dropout能够被理解为在一个全连接的神经网络中的神经网络进行子采样,并且仅仅基于输入数据更新网络采样更新的参数。然而,该指数可能的取样数量,网络并不是独立的,因为他们共享参数。在测试过程中,dropout没有被使用。通过集成指数级的所有子网络解释预测的均值。实践过程中,dropout 的比率为 p=0.5 是一个合理的默认值。但是这个值可以在验证数据上进行微调。 
    

    这里写图片描述

    最流行使用的正则化技术Dropout

    1. 从数字中观察

    这里写图片描述

    7.1 从学习率观察

       太高的学习率,loss曲线会很奇怪,很容易会出现参数爆炸现象;低学习率,loss下降很慢;高学习率,一开始loss会下降很快,但很容易跌入局部最小值;好的学习率应该平滑下降。
    

    7.2 放大loss曲线观察。

       图2中横坐标是epoch(网络在整个训练集上完整的跑一遍的时间,所以每个epoch中会有多个mini batches),纵坐标是每个训练batch的分类loss。如果loss曲线表现出线性(下降缓慢)表明学习率太低;如果loss不再下降,表明学习率太高陷入局部最小值;曲线的宽度和batch size有关,如果宽度太宽,说明相邻batch间的变化太大,应该减小batch size。
    

    7.3 从精确率曲线观察。

       图3中红色线是训练集上的精确率,绿色验证集上的精确率。当验证集上精确度收敛时,红线和绿线间隔过大很明显训练集上出现了过拟合。当两线间隔很小且准确率都很低时,说明模型学习能力太低,需要增加模型的capacity。
    
    1. 集成

      在机器学习中,在训练多个学习器并将它们进行组合来使用是一种前沿的学习方法。众所周知,集成方法通常在得到更高的精确性的时候相比于单个学习器是至关重要的。并且,集成方法已经在现实任务中取得了伟大的成功。在实际应用中,尤其是挑战和竞赛中,几乎所有的第一和第二名获胜者都使用集成。

    这里,我们介绍几个在深度学习场景中的集成技巧:

    8.1 相同的模型,不同的初始化

       使用交叉验证决定最优超参数,然后根据最好的超参数集训练多个方法,但是使用不同的随机初始化。这种方法的危险是模型的多样性仅仅取决于初始化。
    

    8.2 交叉验证阶段的最优模型的发现

       使用交叉验证决定最优超参数,然后选择少量几个效果最好的模型进行集成。这样改善了集成的多样性,但是他也有风险:例如局部最优。在实践中,这可以更容易执行,因为它不需要额外的培训交叉验证后的模型。事实上,你可以直接选择几个最先进的深度模型从 Caffe Model Zoo 执行集成。
    

    8.3 单个模型的不同检查点

       如果训练的代价很高,有些人取得了有限的成功在不同的检查点的单一网络随时间(例如在每个阶段)和使用这些形成了一个整体。显然,这受制于某些缺乏多样性,但是在实践中仍然可以工作的很好。这种方法的优点是,非常简便。
    

    参考文献:
    http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html

    展开全文
  • 深度学习训练技巧(一)

    千次阅读 2017-05-30 17:29:53
    训练技巧深度学习来说是非常重要的,作为一门实验性质很强的科学,同样的网络结构使用不同的训练方法训练,结果可能会有很大的差异。这里我总结了近一年来的炼丹心得,分享给大家,也欢迎大家补充指正。 参数...

    训练技巧对深度学习来说是非常重要的,作为一门实验性质很强的科学,同样的网络结构使用不同的训练方法训练,结果可能会有很大的差异。这里我总结了近一年来的炼丹心得,分享给大家,也欢迎大家补充指正。

    参数初始化。

    下面几种方式,随便选一个,结果基本都差不多。但是一定要做。否则可能会减慢收敛速度,影响收敛结果,甚至造成Nan等一系列问题。
    n_in为网络的输入大小,n_out为网络的输出大小,n为n_in或(n_in+n_out)*0.5
    Xavier初始法论文:jmlr.org/proceedings/pa
    He初始化论文:arxiv.org/abs/1502.0185

    • uniform均匀分布初始化:
      w = np.random.uniform(low=-scale, high=scale, size=[n_in,n_out])

      • Xavier初始法,适用于普通激活函数(tanh,sigmoid):scale = np.sqrt(3/n)
      • He初始化,适用于ReLU:scale = np.sqrt(6/n)
    • normal高斯分布初始化:
      w = np.random.randn(n_in,n_out) * stdev # stdev为高斯分布的标准差,均值设为0

      • Xavier初始法,适用于普通激活函数 (tanh,sigmoid):stdev = np.sqrt(n)
      • He初始化,适用于ReLU:stdev = np.sqrt(2/n)
    • svd初始化:对RNN有比较好的效果。参考论文:arxiv.org/abs/1312.6120

    数据预处理方式

    • zero-center ,这个挺常用的.
      X -= np.mean(X, axis = 0) # zero-center
      X /= np.std(X, axis = 0) # normalize
    • PCA whitening,这个用的比较少.

    训练技巧

    • 要做梯度归一化,即算出来的梯度除以minibatch size
    • clip c(梯度裁剪): 限制最大梯度,其实是value = sqrt(w1^2+w2^2….),如果value超过了阈值,就算一个衰减系系数,让value的值等于阈值: 5,10,15
    • dropout对小数据防止过拟合有很好的效果,值一般设为0.5,小数据上dropout+sgd在我的大部分实验中,效果提升都非常明显.因此可能的话,建议一定要尝试一下。 dropout的位置比较有讲究, 对于RNN,建议放到输入->RNN与RNN->输出的位置.关于RNN如何用dropout,可以参考这篇论文:arxiv.org/abs/1409.2329
    • adam,adadelta等,在小数据上,我这里实验的效果不如sgd, sgd收敛速度会慢一些,但是最终收敛后的结果,一般都比较好。如果使用sgd的话,可以选择从1.0或者0.1的学习率开始,隔一段时间,在验证集上检查一下,如果cost没有下降,就对学习率减半. 我看过很多论文都这么搞,我自己实验的结果也很好. 当然,也可以先用ada系列先跑,最后快收敛的时候,更换成sgd继续训练.同样也会有提升.据说adadelta一般在分类问题上效果比较好,adam在生成问题上效果比较好。
    • 除了gate之类的地方,需要把输出限制成0-1之外,尽量不要用sigmoid,可以用tanh或者relu之类的激活函数.1. sigmoid函数在-4到4的区间里,才有较大的梯度。之外的区间,梯度接近0,很容易造成梯度消失问题。2. 输入0均值,sigmoid函数的输出不是0均值的。
    • rnn的dim和embdding size,一般从128上下开始调整. batch size,一般从128左右开始调整.batch size合适最重要,并不是越大越好.
    • word2vec初始化,在小数据上,不仅可以有效提高收敛速度,也可以可以提高结果.
    • 尽量对数据做shuffle
    • LSTM 的forget gate的bias,用1.0或者更大的值做初始化,可以取得更好的结果,来自这篇论文:jmlr.org/proceedings/pa, 我这里实验设成1.0,可以提高收敛速度.实际使用中,不同的任务,可能需要尝试不同的值.
    • Batch Normalization据说可以提升效果,不过我没有尝试过,建议作为最后提升模型的手段,参考论文:Accelerating Deep Network Training by Reducing Internal Covariate Shift
    • 如果你的模型包含全连接层(MLP),并且输入和输出大小一样,可以考虑将MLP替换成Highway Network,我尝试对结果有一点提升,建议作为最后提升模型的手段,原理很简单,就是给输出加了一个gate来控制信息的流动,详细介绍请参考论文:arxiv.org/abs/1505.0038
    • 来自@张馨宇的技巧:一轮加正则,一轮不加正则,反复进行。

    Ensemble

    Ensemble是论文刷结果的终极核武器,深度学习中一般有以下几种方式

    • 同样的参数,不同的初始化方式
    • 不同的参数,通过cross-validation,选取最好的几组
    • 同样的参数,模型训练的不同阶段,即不同迭代次数的模型。

    • 不同的模型,进行线性融合. 例如RNN和传统模型.

    展开全文
  • 0. 引言 1. 文本领域的数据预处理技术 1.1 文本纠错 1.2 低频词处理 1.3 停用词 1.4 关键词提取 ...2. 深度学习训练技巧 2.1 学习率调整 2.2 梯度修正 2.3 参数初始化 2.4 归一化 3 . 深度学习Debug ...
  • 深度学习入门课程---训练技巧之Transfer Learning视频教程,希望能够学习者提供帮助,实现对Transfer Learning基础知识的掌握与理解,为后续学习做好铺垫,实现Transfer Learning知识的灵活运用
  • 详解深度学习系统的训练技巧
  • 李宏毅教授在文中分四个章节对深度学习的介绍、训练深度神经网络的技巧,神经网络的种类以及未来的发展进行了介绍。注:为什么叫"一天搞懂深度学习",起因是这份资料是李教授的讲座资料,当时是一天就完成了教学,...
  • 深度学习入门课程---训练技巧之数据增强视频教程,希望能够学习者提供帮助,实现对数据增强基础知识的掌握与理解,为后续学习做好铺垫,实现数据增强的灵活运用
  • 深度学习网络训练技巧

    千次阅读 2018-07-19 11:59:40
    1. 数据增强 1.1 海康威视研究院ImageNet2016: 第一,对颜色的数据增强,包括色彩的饱和度、亮度和... 我们首先按照RGB三个颜色通道计算了均值和标准差,对网络的输入数据进行规范化,随后我们在整个训练集上计...
  • import 需要的包,小技巧:开始不知道用哪些包可以先不引用,输入命令后未引用的包下面会有红线警告,鼠标点击一下,然后 alt+enter会显示 需要引用的选项,选择即可。 train_data = torchvision.datasets.CIFAR10...
  • 深度学习模型训练技巧

    千次阅读 2018-01-10 10:02:20
    博主以前都是拿别人的模型别人的数据做做分类啊,做做目标检测,搞搞学习,最近由于导师的工程需求,自己构造网络,用自己的数据来跑网络,才发现模型训练真的是很有讲究,很有技巧在里面,最直接的几个超参数的设置...
  • 深度学习图像分类常见问题以及训练技巧

    千次阅读 多人点赞 2020-10-22 02:20:29
    图像分类常见问题以及训练技巧 写在前面 图像分类作为计算机视觉的基础任务,包含的很多问题其实也是CV领域的共性问题,分类的训练或者预测技巧也可以很好地迁移到其他任务中去,本文主要就是总结了图像分类在基础...
  • 第三章:深度学习训练与优化

    千人学习 2018-12-20 17:34:22
    本章介绍深度学习模型的训练和优化
  • pytorch 模型训练中涉及到多线程以及dataloader加速的一些技巧
  • 深度学习中的各种训练技巧   本文对深度学习中的一些训练技巧进行了总结,希望对大家的炼丹有所帮助。文章参考了Bag of Tricks for Image Classification with Convolutional Neural Networks和Accurate, ...
  • 深度学习训练过程中改变学习率的方法,公式如下所示: 二、代码实现 def noam_scheme(init_lr, global_step, warmup_steps=4000.): step = tf.cast(global_step + 1, dtype=tf.float32) return init_lr *...
  • GAN模型相比较于其他网络一直受困于三个问题的掣肘: 1. 不收敛;模型训练不稳定,收敛的慢,甚至不收敛; 2.... 生成器产生的结果模式较为单一;...本文主要以下几个方面入手,聚焦于解决以上三个问题的一些技巧
  • 机器学习训练的目的在于更新参数,优化目标函数,常见优化器有SGD,Adagrad,Adadelta,Adam,Adamax,Nadam。其中SGD和Adam优化器是最为常用的两种优化器,SGD根据每个batch的数据计算一次局部的估计,最小化代价...
  • 分割学习训练技巧模型

    千次阅读 2021-11-23 16:34:49
    1:一类分割时最好 将训练集的图片resize成统一大小时,再进行标注。可以提高准确率,这个原因是如果不进行resize 则hui
  • 深度学习入门知识整理-训练技巧以及模型调优

    千次阅读 多人点赞 2019-06-13 19:12:42
    学习率范围侧视图Colab Notebook Nanonets 数据预处理 数据增强 数据不平衡的处理 自己的数据生成器 全程跟踪工作 Linux命令 学会去查找资料和Solution 如果你有了初步的想法打算做某个研...
  • 1080ti与2080ti均为11G显存,在训练时同样的模型batch_size可以调到一样大。它们的主要区别在于2080ti具有很强的半精度浮点数计算能力。1080ti和2080ti的计算能力如下: gtx 1080ti: 半精度浮点数:0.17TFLOPS 单...
  • 深度学习神经网络训练调参技巧

    千次阅读 2018-10-19 22:52:39
    本文主要介绍8种实现细节的技巧或tricks:数据增广、图像预处理、网络初始化、训练过程中的技巧、激活函数的选择、不同正则化方法、来自于数据的洞察、集成多个深度网络的方法原文如下:... 数据增广 ...
  • Pytorch与深度学习训练trick实战(持续更新) 冻结参数 def set_parameter_requires_grad(model, feature_extracting): if feature_extracting: for param in model.parameters(): param.requires_grad = False ...
  • 本课程还讲述了神经网络的训练方法与实践技巧,且开展了代码实践演示。课程对于核心内容讲解深入细致,如基于计算图理解反向传播算法,并用数学公式推导反向传播算法;另外还讲述了卷积加速方法im2col。 【课程收获...
  • 深度学习模型训练全流程!

    万次阅读 多人点赞 2020-06-11 20:00:00
    ↑↑↑关注后"星标"Datawhale每日干货 &每月组队学习,不错过Datawhale干货作者:黄星源、奉现,Datawhale优秀学习者本文从构建数据验...
  • 深度学习中的超参数设定及训练技巧

    万次阅读 多人点赞 2018-04-28 16:47:48
    三、训练技巧 shuffle per epoch 梯度裁剪:防止梯度爆炸 迁移学习: 将从源数据集学到的知识迁移到目标数据集上 例如,虽然 ImageNet 的图像⼤多跟目标数据无关,但在该数据集上训练的模型 可以抽取...
  • 文章发布于公号【数智物语】(ID:decision_engine),关注公号不错过每一篇干货。...这又是一篇介绍深度学习技巧的文章,不过和之前的那篇文章侧重点有所不同,这篇文章更加注重于如何在实际的项目的数据集中训...
  • 得到更改的准确率模型的设计自然是重要,而使用一些数据处理和训练技巧也能提高最终模型的训练效果,因此也十分重要。本文基于对一些资料的阅读总结一些模型训练常见的trick,能够更快地拟合以及在一定程度上提升...
  • 向AI转型的程序员都关注了这个号????????????机器学习AI算法工程 公众号:datayx本文主要用于记录DSSM模型学习期间遇到的问题及分析、处理经验。先统领性地提出深度学...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 33,141
精华内容 13,256
关键字:

深度学习训练技巧