深度学习 | 训练及优化方法

Posted by JoselynZhao on June 25, 2019

深度网络优化方法

优化及调试策略:实践流程

  1. 确定目标:误差度量及期望目标
  2. 建立端到端流程: 数据读取、预处理流程 端到端模型构建:基准模型(传统方法、经典模型)vs 设计模型 性能度量、评测脚本

    三个脚本先写好:数据处理、模型训练、评测脚本

  3. 搭建系统,确定性能瓶颈: 调通系统:是否出现正确结果 预期判断:过拟合、欠拟合? 调通系统:是否出现正确结果?

    我们最关心的是泛化性能,所以评测脚本很重要,得出目前结果是过拟合还是欠拟合。

  4. 根据观察进行增量式改进: 收集新数据、调参、改进算法

错误来源: 算法本身还是编程实现 难点: 1. 无法预测算法行为;2. 模型很多地方自适应 重要的调试检测手段:

  1. 可视化计算中模型的行为(看中间,最后输出结果)
  2. 可视化最严重的错误(看做错的例子)
  3. 训练、测试误差分析: 训练低,测试高:过拟合、训练模型未正确加载 训练高,测试高:欠拟合、程序错误
  4. 缩小问题规模,测试程序正确性
  5. 可视化网络参数、梯度等

梯度消失与梯度爆炸

梯度消失: 随着网络层数的增加,网络从后往前,传回的梯度越来越小,导致之前的网络层“训不动” 在这里插入图片描述

图中三张图表示网络层数分别为2、3、4的情况, 越靠近前面的层,变化越小

梯度爆炸:梯度下降训练过程中遇到损失突变的位置(墙、悬崖 等形态),梯度瞬间增大,指向某处不理想的位置。可能现象: 训练无法收敛; 损失函数、权重:变化非常大 or 出现 NaN 值; 梯 度:每层的每个节点训练时梯度一直大于 1.0

在这里插入图片描述

链式法则? 在RNN中更常见。

问题本质:梯度的乘积积累 期望效果:连续乘积都刚好平衡大约等于 1,但几率很小 梯度爆炸更多来源于不合理的参数初始化及过大的学习率 梯度消失在更深的网络中更具有普遍性 梯度的乘积积累路径变长 激活函数的问题:例如 Sigmoid 易饱和,考虑采用 ReLU 等

在这里插入图片描述

消失和爆炸都在于累乘。 sigmoid 对信息的保存更好,更平和(Relu小于0的部分全都丢掉了)

Sigmoid 激活函数问题

1.exp() 计算复杂

  1. 激活函数易饱和,梯度易消失:$z^(l−1) $偏大或偏小的地方 (-4>,>4) 接近 0,梯度传递接近 0 . 在这里插入图片描述 在这里插入图片描述 3.sigmoid 输出范围 (0 1), 非 0 中心,σ(zl−1) 总大于 0,由 在这里插入图片描述 权重更新呈现锯齿形 在这里插入图片描述

ReLU

不易出现激活函数饱和问题 (为什么), 计算高效 相比 sigmoid/tanh 收敛速度快 (为什么?) 问题: 依然是非 0 中心输出; 存在 dying ReLU 问题; 信息丢失 在这里插入图片描述

dead 节点连接的下面的 参数不再更新了。

激活函数输入 zn 小于 0,梯度也为 0,zn 之前权重 w 不能更新 权重未初始化好 (使得某些节点对所有样本输出都是负数),或训练过 程中,一股剧变梯度使得 w 分布突然改变在一定范围,使得 zn 输出一直小于0,w永远不更新。

参数初始化

  1. 优化结果优劣(不只是最小值问题,梯度学习行为)
  2. 训练是否可行(梯度消失、爆炸、训不动。。。)

在这里插入图片描述

参数设得大,容易炸。

破坏对称性: 随机初始化权重 不能 0 初始化(回顾之前可视化中的例子,为什么?) 随机初始化权重 0 初始化权重失败(回顾之前可视化中的例子)

权重大小:相对大的情况 大权重破坏对称性更强 + 有益于缓解梯度消失 + 梯度爆炸等不稳定问题-(权重累积存在反向传播链上) 激活函数易饱和-

不同层的缩放因子

一开始都是同样的01初始化,后面层的分布可能会更摘一点

偏置可以 0 初始化

偏置不会出现在链上,所以没有影响

随机、不能全0、不能太大也不能太小

LeNet 训练 MNIST 案例 1, 送分题:全 0 初始化 LeNet 导致参数不更新。为什么?

案例 2:错误的层间参数数值范围比例:初始化最后全连接层参数 均值 100,方差 10;其他层变量均值 0,方差 0.1。导致无法训练: 学习率太小,学不动;太大,爆炸,或不收敛。

在这里插入图片描述

权值大,则学习率应该大一点,才能匹配,不然学不懂。

在这里插入图片描述

在这里插入图片描述

训不动,但又没有炸,则可以抬高学习率。

参数随机初始化的问题: 10 层的神经网络,非线性变换为 tanh,每一层的参数都是随机正态分布,均值为 0,标准差为 0.01 训练后,每一层输出值分布的直方图 在这里插入图片描述 输出集中在 0 附近,对样本变化太敏感,网络表达能力差,且本层w 难以更新(反向传播公式)

均值仍然为 0,标准差现在变为 1 在这里插入图片描述

这样的网络近似为一个二值网络

输出集中在-1,1, 网络表达能力依然弱 (极端情况下,相当于 2 值网络),且 tanh 激活函数饱和,w 依然无法更新

无法更新的原因: 0值的地方穿不过来,1的地方饱和了。

问题出在哪里? 参数太大,饱和;太小,不激活:激活函数的特性(relu 也存在相 关问题) 如何配合激活函数特性初始化参数? Xavier 或者 Glorot initialization 方案 在这里插入图片描述 基本思想: 保持输入和输出的方差一致,避免所有输出值都趋向于0

针对不同激活函数的 Xavier 初始化形式 在这里插入图片描述

不同激活函数对应的初始化区别主要是根号外的系数 Tensorflow 中可以根据公式手动缩放初始化值,也有类似的 xavier_initializer 初始化方法:

initializer = tf.contrib.layers.xavier_initializer()
W = tf.get_variable("W", shape=[784, 256], initializer= initializer)
w1 = tf.Variable(initializer(w1_shape))

大多数都是采用的这个初始化方法

ReLU 实验效果:xavier 初始化 (注意:下面写法是 node_in ≈ node_out 的近似) 在这里插入图片描述

另一种方差平衡初始化:He initialization 基本思想:ReLU 网络中,假定每层一半神经元被激活,另一半为 0 保持 variance 不变,需在 Xavier 的基础上再除以2

在这里插入图片描述 这样的效果更好一些。

node_in 和node_out 是什么?

学习率

学习率选择

  • 过大: 振动、不收敛;过小: 收敛速度慢
  • 理想的学习率设计是:前期较大学习率搜索,后期小学习率调优。 以及对参数的个性化调整:优化频率高的参数小学习率调整,优化频率低的参数大学习率调整。
  • 初期选择 :指数级改变学习率观察 loss 变化
  • 其他手段: 自适应学习率算法: Nesterov ,Adagrad , Adadelta , Adam… 热启动

在这里插入图片描述

有的网络会先以小学习率训练一段时间,再调大学习率,这个叫做热身。 蓝色,下坡缓慢,学习率太低了。 红色,是比较理想的情况 学习率不光影响学习的速率,还影响最后的收敛效果。 想调整成为红色,但可能会调整成为绿色。 收敛并不代表最优。

学习率对模型训练的影响 在这里插入图片描述

学习率大了之后,毛刺比较多。在lr=0.003的时候,收敛速度慢了一些,但较为平稳了。 lr = 0.00001的时候,训练效果是最好。 为了得到更好的效果,慢也得等。

学习率分析举例:LeNet 训练 MNIST 案例 1:lr(ε 步长)=0.0001;0.001;1 各是哪个loss? 在这里插入图片描述

橙色线对应着 0.0001 ,因为收敛得最为缓慢。

lr(ε 步长)=0.0001;0.001;1 各是哪个 w? 在这里插入图片描述

学习率越小,波动越大。

学习率衰减策略:learning rate decay 学习过程中,学习率并不是一成不变,而是根据学习的情况进行调整 开始大,快速收敛,后期小,优化收敛位置 在这里插入图片描述 学习率衰减策略很多,主要包括持续衰减和周期学习率两种,其代表: Exponential decay: 学习率随一定步长阶段指数减少,最常用 Cycle learning rate: 防止网络后期 lr 十分小导致一直在某个局部最小值 中振荡,突然调大 lr 可以跳出注定不会继续增长的区域探索其他区域 在这里插入图片描述 另外,很多时候,由于网络或模型中一些部件的特性,需要先用比较 小的学习率优化其参数 (例 BatchNorm 种的 moving avg),之后再开始 训练,对此类网络常先用一个较小学习率进行“Warm up”, 再用一般 学习率衰减策略

迭代次数

由于泛化界限的存在,数据在迭代训练时,会逐渐产生过拟合现象 变化趋势表现为:

  1. test loss 与 train loss 均缓慢下降并趋于平稳
  2. train loss 虽然下降,但 test loss 已经开始上升
  3. train loss 与 test loss 一直上升 (呈现 U 形)

在这里插入图片描述

提前终止(early stop)

  • 一种常用的正则化形式
  • 当验证集上的误差在事先指定循环次数内没有进一步改善时,停止训练算法
  • 一般可取一个窗口的误差均值,当验证集上误差均值开始上升时,停止

将训练步数视作超一个超参数,提前终止通过控制拟合训练集的步数来控制模型的有效容量 在这里插入图片描述

LeNet 训练 MNIST 案例 1:总共只随机取 1000 个训练样本,缩小训练集的规模,人为制 造过拟合

在这里插入图片描述 问题:

  1. 为什么说现在的训练过拟合了?
  2. 为什么没有发生 U 型 test 上升?

训练收敛,训练 loss 没有进一步往下降, 过拟合就不再有进展。否则 loss 继续降,过拟合继续进展,呈现 U 型上升。

batch size

(batch size 和学习率的关系)

Batch 方差与 learning rate 关系

  • Batch size 变大的效果: 梯度的均值越接近期望,方向更准 梯度的方差期望越小,估计更稳 学习率增大会增大梯度估计方差
  • 另一方面,如果 batch size 比较大,可 以用比较大的 lr 而同时可以保持一定 的方差(保持证明见右公式),这样加 快学习。

在这里插入图片描述

Large-batch 魔咒

  • Large batch 会有更准的梯度,方差越小,应该有更高的准确性
  • Batch size 不见得越大越好:large batch 可能会降低准确率!
  • ICLR 2017: ON LARGE-BATCH TRAINING FOR DEEP LEARNING: GENERALIZATION GAP AND SHARP MINIMA (i) LB methods over-fit the model; (ii) LB methods are attracted to saddle points; (iii) LB methods lack the explorative properties of SB methods and tend to zoom-in on the minimizer closest to the initial point; (iv) SB and LB methods converge to qualitatively different minimizers with differing generalization properties.
  • LB 陷入的是比较 sharp 的极值点,SB 陷入的是比较 flat 的极值点, 泛化性能更好

在这里插入图片描述

  • 另一种声音:Facebook: Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour
  • LB 之所以不 work,不是泛化能力的问题,而是优化的问题
  • 学习过程要维护好学习率和 batch size 的关系
  • Linear Scaling Learning Rate:简单点:batch size 翻多少倍, learning rate 就翻多少倍
  • LB 方法,开始用大的 learning rate,效果差;只要开始把 LR 设小, 之后逐步提高 LR 到正常大小,LB 能到跟 SB 几乎一样的 training curve、基本相同的准确度

linear scale rule

  • baeline(batch size B) 走 k 步 (3), large batch(batch size kB) 走 1 步 (4) 更新公式比较 (#B = n): 在这里插入图片描述

(4):过一步相当于(3):过 k 步 为使更新效果一致,(4)的学习率应该再乘以 k 倍 在 weight 变化较快的时候,W(t+j) W(t) 不满足 故在开始变化很快的时候,一般不是 k 倍,后面逐渐放大 lr 也不能无限放大,batchsize 变大后,合适的 lr 范围在变小

large batch 问题一般在分布式训练中非常 large 的情景一般情况下,batch size 选取有以下建议

  • 小 batch 训练,受噪音影响大,不容易收敛,学习慢;泛化误差较小;
  • 大 batch 训练,梯度估计更准确,训练震荡越小,收敛速度快,但 是容易陷入局部最小(非凸函数优化);容易过拟合,过大的 large batch 准确率会低;
  • 在实践过程中,在 GPU 显存容许的情况下,一般采用较大的 batch size。注意和 learning rate 的配合

解决毛刺大的方法: batch_size 调大,或者学习率调小

正则化

正则化技术概述

  • 机器学习核心问题:如何提高泛化能力?
    • 泛化:一个假设模型应用到新样本上的能力
    • 欠拟合可直接从训练情况中观察到,并设法改进
    • 如何有效防止过拟合行为:模型过度拟合了训练数据的噪音,导致 测试集性能不佳,泛化能力差
  • 正则化:减少测试误差(可能以增加训练误差为代价),提高模型 泛化能力
  • 广义讲,提高算法测试性能的一切手段都可以视为正则化技术
  • 主要目标:减少泛化误差而不是训练误差

在这里插入图片描述

  • 正则化技术在深度学习中的必要性:
    • 小规模神经网络模型可以降低对数据量的需求并缓解过拟合,但是性能短板明显
    • 收集数据集尚无法满足复杂模型避免过拟合的要求 - - 关键还是模型能力与问题复杂度、数据量的匹配方式 (regularization)
  • 必须引入正则化以提升泛化能力
  • 正则化主要手段:
    • 数据处理:数据规范化技术/数据集扩充技术
    • 目标牵引:目标函数正则化项
    • 模型技巧:dropout 技术/batch normalization 技术
    • 策略选择与具体任务相关

在这里插入图片描述

数据增强技术

主要包括两方面:

  • 数据集扩充:问题是否被数据有效覆盖? 在这里插入图片描述

  • 数据集规范化:数据形态是否可被现有模型有效学习? 在这里插入图片描述

  • 数据集扩充与模型过拟合:

    • 过拟合本质是模型相对问题复杂,但数据的不充分,会加剧这种不 匹配 在这里插入图片描述
    • 完善数据,可以有效约束 (regularization) 过拟合的行为 在这里插入图片描述
  1. 几何变换:丰富数据集中目标的变化,更多适应卷积网的特性 刚性几何变换:目标内部的相对空间关系不变

    旋转变换:当需要分类或被识别的目标可能存在多种不同角度时 尺度变换:当任务可能面对不同的尺度 水平/垂直翻转:任务没有更多旋转条件时,翻转更为常见 平移变换:未限制学习目标在视 在这里插入图片描述

    非刚性几何变换:未来检测目标可能展示柔性的变化 例:薄样板条插值法 Thin Plate Spline(TPS) TPS 是一种插值算法,常用于图像变形,以达到数据增广的作用。 TPS 功能强大,即可涵盖之前的刚性变换,放射变换,也可以产生 更多的柔性变换。 在这里插入图片描述

TPS 应用举例:人脸关键点预测 人脸、动物等可有一定柔性空间的关键点相关算法,可用 TPS 增强算法鲁棒性 在这里插入图片描述

  1. 截取:从输入裁剪出更多保持尺寸比例样本,或突出学习重点 应对网络输入的限制 (224x224),截取采样保持目标比例 在这里插入图片描述 方法:采样 (保持目标尺寸比例)、遮挡 (突出重点) 方法:随机截取、监督式截取 在细分类、关键点标注等任务中,遮挡对于提升局部敏感度有帮助 在这里插入图片描述

随机截取:难以控制截取内容 一些样本质量有限,有一定冗余,也存在一定错误样本 在这里插入图片描述 监督式截取:训练如何截取

  • 随机初始化训练较为粗糙的类别激活模型
  • 生成的特征图反映了图像内部各区域与标签的相关性
  • 基于特征图截取样本训练高性能分类网络

在这里插入图片描述

  1. 加噪和色彩变换:
    • 对颜色进行轻微的变化(如对每个像素点的 RGB 值乘以 0.95-1.05 间的随机系数)
    • 目标具有多样颜色的情况,但要控制色彩范围
    • 对存在曝光过度或过暗的任务,增加亮度变换 - 添加噪声可有效提升识别的鲁 在这里插入图片描述 相关工具 DeepAugment 等:pip install deepaugment 在这里插入图片描述

数据集规范化

从模型学习的角度,规范数据集数据的分布范围 在这里插入图片描述

规范的是数值,常有:零均值化,归一化,去相关 (白化) 在这里插入图片描述

减去均值之后,做归一化

零均值化:对数据集内所有样本,减去数据的均值

  • 利用训练集得到图像均值
  • 每个样本均减去图像均值
  • 移除图像共同部分,凸显个体差异
  • 从数据分布来说,使数据的中心点移到了原点 在这里插入图片描述

归一化:零均值化的数据除以归一化值 (例如标准差), 使数据分布范围 限制在固定范围,例如 (-1,1) 例如标准差规范化:

  • 利用训练集得到图像的标准差
  • 每个零均值化的样本均除以图像标准差
  • 从数据分布来说,只是限制了分布的范围,并未改变分布形态,

例如不一定归一化后的就服从正太分布! 归一化减少模型偏置学习压力,零均值化使权值学习范围无明显偏向 零均值化和归一化后的数据和模型参数初始化范围已经接近,是比较 好的训练输入

但数据如果不做零均值化和归一化,模型训练将非常困难

在这里插入图片描述

去相关 (白化):去除数据相关性、降低冗余

  • 数据中,不同维度之间存在一定的相关性,例如图像中目标局部 的一定相关性
  • 训练时相关数据带来冗余,使得模型对区分特性不敏感
  • 从数据分布来说,去相关改变了数据维度上的分布形态:1. 使数 据的不同维度去相关;2. 使数据每个维度的方差为 1;
  • 常用:PCA 白化,ZCA 白化 在这里插入图片描述

维度去相关,并且维度上的方差为1 ,则为白化

PCA 白化: 应用 PCA 主成分分析,将数据在主成分特征向量上进行投 影,并用主成分特征代替原特征 在这里插入图片描述

ZCA 白化:PCA 白化后,数据原来的维度转换成了主成分维度,为了使 白化后的数据尽可能接近原数据,可以把处理过的数据再变换回原空 间,也就是 ZCA 白化。 在这里插入图片描述 白化效果举例:可见 ZCA 相比 PCA 更接近原数据 (相同的维度定义) 在这里插入图片描述

目标函数及正则化

目标函数:模型的学习引导

  1. 想让模型表达什么?分类、特征分布、流形提取、对抗。。
  2. 想让模型的表达有什么特点?稀疏、降低结构风险。。

目标函数的设计直接影响了学习效果 在这里插入图片描述 Siamense Net Loss 思路:正样本对的 Ew 要尽量小,负样本对的尽量大 也就是,Loss 要鼓励正样本对的 Ew 减小,鼓励负样本对的 Ew 增大 在这里插入图片描述

按此 loss 引导,网络学习的 Ew 最终会根据正负样本对两个阵营,形成 两个峰的分布。分类问题就变为对这两个聚集分布的划分: 在这里插入图片描述 在这里插入图片描述

在这里插入图片描述

Triplets Loss 在这里插入图片描述 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

区别:多类型的时候

  1. 假设不一样:CL 考察距离: 正例要求往一起集中 yd2,TL 考察 距离的差: 不要求集中,只要正例距离与负例距离差小就可以
  2. CL 限制了类间距 D 的范围,(d 比 a 大的时候反而会反向惩罚), 实际上会将不同类团进行聚集,实际对各个类型的分布有了潜在 的假设,同时拉动整个类型也会增加网络学习难度;
  3. TL 只要求正例与正例的距离小于正例与负例的距离 (考察的是 距离的差) 即可,更灵活适应多类分布。

Hard negative mining

  • Hard negative mining: 难例!
  • 难例:错误分类样本,而且预测的置信度很高
  • 网络训好需要难例,尤其后期,简单样本已难以提升了:(回忆我 们正负例数据不平衡的时候的 Siamese 作业)
  • 简单方案:找到难例,训一波。或者适当时候找难例,训一波
  • CL:可以很快收敛;TL:会有坍塌现象(TL 梯度 han := f(xa) − f(xp),对于难例,很近,往哪个方向推?可能同时推了 f(xa), 原来 训好的也搞坏了)
  • 问题:怎么定义难例?尤其后期训不动的时候找难例?

难例不仅是数据集未充分采集的结果: 样本缺乏、样本不平衡 更多时候,在训练过程中,模型会对大多数样本损失很小

  1. 不平衡的类型效果;
  2. 类中比较困难的样本

此时 gradient 被 easy example 支配,长期不改变 OHEM: online hard example mining 目标函数引导:根据不同样本的 loss 大小,增多 loss 比较大的样本的 学习机会

  • class 比例加权重:最常用处理类别不平衡问题的方式
  • OHEM: 只保留 loss 最高的那些样本,完全忽略掉简单样本 (梯度置为 0)
  • OHEM+ 按 class 比例 sample:在前者基础上,再保证正负样本的比例

Focal Loss: OHEM 需要根据 loss 选样本,再去对选择的样本进行训练 另一个角度,直接在 loss 上将难例的惩罚增大, 简单例的惩罚减小 在交叉熵上根据样本难度加权,(正样本难例 Pi 小,负样本难例 Pi 大) 在这里插入图片描述 在这里插入图片描述

参数正则化: 过拟合:模型相对问题复杂 增加数据可以减轻过拟合现象,但并不是解决根本问题 如何在不改变网络结构的情况下降低复杂度? 正则化:在目标函数中增加约束项损失函数:L(θ) → L(θ) + λ ∗ R(w) R(w): 正则化项, 常用 L1 范数:R(w) = ∥w∥21 = Σ|wi| 和 L2 范数: R(w) = ∥w∥2 = Σw2i 参数正则化目标:网络在降低样本损失的同时,偏好较小的权值 实际上牺牲了一些作对的样本,以换取泛化性能 L1 更易产生稀疏解 (解容易发生在轴上);L2 的解较平滑,较 L1 好解

在这里插入图片描述

L1、L2 正则化实例:手写数字分类(MNIST 数据集) 网络结构:全连接神经网络(3 隐层,节点数为 1500、1000、500) 目标函数:交叉熵目标函数 正则化方法:无正则化 (1.25%),L1(1.16%),L2(1.11%) L1、L2 正则化技术的使用可以带来一定的性能改善 L1 正则化得到更加稀疏的权值矩阵

在这里插入图片描述 参数正则化技术 tensorflow 实现示例

#例 如, 对 所 有 参 数 进 行 正 则 化 #首先选定所有训练参数tv作为正则化对象
tv = tf.trainable_variables()
Regularization_term = lambda*tf.reduce_sum( [ tf.nn.l2_loss(v)
for v in tv ])
New_loss = original_loss + Regularization_term
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(
New_loss)
#也 可 将 参 数 加 入 指 定 正 则 化 损 失 函 数 集 合, 加 入 的 同 时, 指 定 其 正 则 化 方 式 regularizer
regularizer = tf.contrib.layers.l2_regularizer(0.001) ...
tf.add_to_collection('reg_loss', regularizer(W_fc1)))) ...
#最终loss是原loss和l2正则项列表相加
loss = original_loss + tf.add_n(tf.get_collection('losses'))

在这里插入图片描述

weight_decay = tf.constant(0.0005, dtype=tf.float32) # your
weight decay rate, must be a scalar tensor.
W = tf.get_variable(name='weight', shape=[4, 4, 256, 512],
regularizer=tf.contrib.layers.l2_regularizer(weight_decay))

Weight decay 效果举例: 在这里插入图片描述 在这里插入图片描述

dropout

深度神经网络学习过程中的依赖现象:

学习过程中,如果隐含层节点较多,可能出现相互依赖的现象

  • 隐含节点之间出现固定关系
  • 若测试数据无法激活具有固定关系的隐含节点,则分类性能可能大大降低
  • 实际是一种过拟合的表现
  • 同一类型只有有限种组合的节点激活方式

可以采用模型平均的方式 缺点:需要训练多个模型,效率较低

Dropout:一种随机丢弃模型节点的方法,消除节点相互依赖

  • 不修改损失函数, 直接修改神经网络的结构
  • 训练过程中以概率 p 随机“丢弃”一部分节点:消除依赖
  • 未被丢弃的节点需以 1/p 为权重进行缩放
  • 每个迭代实际上使用了不同的网络结构
  • 测试时使用完整网络 (p=1),事实上起到了多个模型合并的作用, 可看做一种集成学习

测试的时候设成1,为什么要设成1啊?

从集成学习角度理解 Dropout

  • 假设网络中每个节点都有 50% 的概率被丢弃,网络共有 N 个节点,则一共可能有 2N 种不同的网络
  • 当 dropout 不同的神经元时,相当于训练的不同的神经网络
  • 测试时使用所有的网络节点,可以近似视为模型平均 (每个模型训 练时权值乘以 50%,节点规模测试时为训练 2 倍,相当于平均两 个训练时只有一半的节点网络)

Dropout tensorflow 应用示例:训练时:keep_prob 设为 p(0.5,0.3…); 测试 时:keep_prob=1

net = tf.nn.relu(tf.matmul(net, W2) + b2)
net = tf.nn.dropout(net, keep_prob=keep_prob)

Dropout 主要用于全连接网络,一般设为 0.5 或者 0.3 卷积网层中由于卷积自身的稀疏化以及稀疏化的 ReLu 函数的大量使 用,Dropout 使用较少

Batch Norm

在这里插入图片描述

moving_mean,moving_variance 为什么需要学习和更新?

BN 对数据进行归一化,需要的是整个样本空间的 mean,var BN 实际上一次迭代只能估计一个 batch 中的 mean 和 var

  • batch 中的 mean 和 var 是局部的,是相对全局的有噪 (还很大) 估计
  • 故用 moving_mean 和 moving_variance 通过多次 batch 的局部统计 来累积对全局的统计

μ, σ 是否需要在测试时更新?

理想情况下,train_data 和 test_data 数据分布应该一致

也就是,测试时,应该用训练得到的全局 μ, σ 但实际上,测试数据与训练数据分布可能存在一定鸿沟:1. 训练与测 试数据分布由于采样引起的不完全对应;2. 不同的 batch size:这些都 会使训练得到的 μ, σ 成为有偏估计

解决方案:1. 使用当前 batch 统计;2. 使用指数加权平均来逐步得到测 试阶段 μ, σ 估计

TF Batch Norm 接口

TF 主要调用关系:

  • tf.nn.batch_normalization: low-level API, 用户负责管理 mean,variance
  • tf.layers.batch_normalization: high-level 封装. 自动创建、管理 mean,variance. 一般常用
  • tf.contrib.layers.batch_norm: BN 早期实现,contrib 的一般都不推荐 使用,在未来版本中都有可能被放弃
  • slim.batch_norm:slim 实现,实际使用 tf.contrib.layers.batch_norm
  • keras.layers.BatchNormalization: 实际后端调用 tf.nn.batch_normalization.

TF Batch Norm 使用方式:

TF BN 使用分为训练、测试两个阶段: 测试阶段:

  1. 参数 training=True, 以训练 gamma(γ),beta(β) 两个参数
  2. moving_mean 和 moving_variance 默认只是” 需更新的”(更新操 作集合 tf.GraphKeys.UPDATE_OPS),却不是” 需学习的” 而实际上滑动平均是需要更新学习的,为此,需手动添加更新操 作集合作为 train_op 依赖项,即在 minimize 优化前,要先做 update_ops 操作
update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)
with tf.control_dependencies(update_ops): train_op = optimizer.minimize(loss)

训练参数保持

moving_mean,moving_variance 因为不是 trainable variable,所以是不在 tf.trainable_variables() 中的,或者将其填入保存变量列表 var_list 后,建 立 saver(var_list) 保存;或用 saver() 保存 global_variable() 在这里插入图片描述

TF Batch Norm 使用方式:

TF BN 使用分为训练、测试两个阶段: 测试阶段:

  1. 参数 training=False, 不训练 gamma(γ),beta(β) 两个参数
  2. 如果要用训练得到的全局 moving_mean 和 moving_variance,建 议用指数加权平均来逐步得到测试阶段 μ, σ 估计 也有用以下来恢复保存的指数加权平均影子参数来实现,此时需 要训练阶段将影子参数也同样保存。
ema = tf.train.ExponentialMovingAverage(0.999) vars = ema.variables_to_restore()

保存形式: {’xxx/varibleExponentialMovingAverage’: <tf.Variable ’xxx/varible:0’ shape=(136,) dtype=float32_ref>,…} 或不用 ema.variables_to_restore() 而将全局 moving_mean 和 moving_variance 赋予新建的影子参数

指数加权平均

tf.train.ExponentialMovingAverage 采用滑动平均的方法更新参数 需衰减速率(decay),用于控制模型的更新速度 维护一个影子变量(也就是更新参数后的参数值),这个影子变量的初 始值就是这个变量的初始值,影子变量值的更新方式如下: shadow_variable = decay * shadow_variable + (1-decay) * variable shadow_variable 是影子变量,variable 表示待更新的变量,也就是变量 被赋予的值,decay 为衰减速率。decay 一般设为接近于 1 的数 (0.99,0.999) decay 越大模型越稳定,因为 decay 越大,参数更新的速度就越慢,趋 于稳定 tf.train.ExponentialMovingAverage 这个函数还提供了自己动更新 decay 的计算方式: decay= min(decay,(1+steps)/(10+steps)) steps 是迭代的次数,可以自己设定,可在前期加速迭代

Batch Norm 实现细节剖析

def bacthnorm(inputs, scope, epsilon=1e-05, momentum=0.99, is_training=True): inputs_shape = inputs.get_shape().as_list()
params_shape = inputs_shape[-1:]
axis = list(range(len(inputs_shape) - 1))
with tf.variable_scope(scope):
beta = create_variable("beta", params_shape, initializer=tf.zeros_initializer())
gamma = create_variable("gamma", params_shape, initializer=tf.ones_initializer())
# for inference
moving_mean = create_variable("moving_mean", params_shape, initializer=tf.zeros_initializer(), trainable=False) moving_variance = create_variable("moving_variance", params_shape, initializer=tf.ones_initializer(), trainable=False)
if is_training:
mean, variance = tf.nn.moments(inputs, axes=axis)
update_move_mean = moving_averages.assign_moving_average(moving_mean,
mean, decay=momentum)
update_move_variance = moving_averages.assign_moving_average(moving_variance, variance, decay=momentum)
tf.add_to_collection(UPDATE_OPS_COLLECTION, update_move_mean) tf.add_to_collection(UPDATE_OPS_COLLECTION, update_move_variance)
else:
mean, variance = moving_mean, moving_variance
return tf.nn.batch_normalization(inputs, mean, variance, beta, gamma, epsilon)

应用举例:作业学号三次函数拟合 cos