程序项目代做,有需求私信(vue、React、Java、爬虫、电路板设计、嵌入式linux等)

第七节,改善深层神经网络:超参数调试、正则化及梯度下降算法优化(上)

这部分内容是我在看Andreg Ng深度学习视频,然后又阅读了一些文章整理后记录下来的。视频连接:http://mooc.study.163.com/smartSpec/detail/1001319001.htm

一 训练集,校验集,测试集以及偏差和方差

1.1 训练集,校验集,以及测试集

  •  训练集:学习样本数据集,通过匹配一些参数来建立一个分类器。建立一种分类的方式,主要是用来训练模型的。
  •  验证集:对学习出来的模型,调整分类器的参数,如在神经网络中选择隐藏单元数。验证集还用来确定网络结构或者控制模型复杂程度的参数。
  • 测试集:主要是测试训练好的模型的分辨能力(识别率等)。

小数据时代七三分或者六二二分是个不错的选择,在大数据时代各个数据集的比例可能需要变成 98%1%1%,甚至训练集的比例更大。 有些时候训练集和验证集、测试集的数据有所不同时,比如训练集的图片高像素、高质量,而验证集和测试集则像素较低,那么有一条经验法则是确保验证集和测试集来自于同一分布;但由于深度学习需要大量的训练数据,为了获取更大规模的训练数据集,可能会进行网页抓取,代价是训练集数据与验证集和测试集数据有可能不是来自于同一分布。

还有一种情况,就算没有测试集也是可以的,测试集的目的是对最终所选定的神经网络系统做出无偏估计,如果不需要无偏估计也可以不设置测试集。

所以搭建训练验证集合测试集能够加速神经网络的集成,也可以更有效地衡量算法的偏差和方差,从而帮助我们更高效地选择合适的方法来优化你的算法。

1.2 偏差和方差

  • 偏差:一般描述的是预测值(估计值)的期望与真实值之间的差距。偏差越大,越偏离真实数据集。(对象是单个模型, 期望输出与真实标记的差别)
  • 方差:描述的是预测值的变化范围,离散程度,也就是离其期望值的距离。方差越大,预测结果数据的分布越散。(如果对象是多个模型,表示多个模型差异程度。)     
  • 基于偏差的误差:所谓基于偏差的误差是我们模型预期的预测与我们将要预测的真实值之间的差值。偏差是用来衡量我们的模型的预测同真实值的差异。
  • 基于方差的误差:基于方差的误差描述了一个模型对给定的数据进行预测的可变性。比如,当你多次重复构建完整模型的进程时,方差是,在预测模型的不同 关系间变化的多少。

 一般来说,偏差、方差和模型的复杂度之间的关系如下图所示:

越复杂的模型偏差越小,而方差越大。

我们用一个参数少的,简单的模型进行预测,会得到低方差,高偏差,通常会出现欠拟合。

而我们用一个参数多的,复杂的模型进行预测,会得到高方差,低偏差,通常出现过拟合。

 

  

实际中,我们需要找到偏差和方差都较小的点。从上图可以看出在偏差和方差都较小的点处,total Error是最少的。

1.3 例子

让我们来看一看我们在什么情况下应该怎样选择:

  • 获得更多的训练实例——解决高方差
  • 尝试增加正则化程度 λ——解决高方差
  • 尝试减少特征的数量——解决高方差
  • 尝试获得更多的特征——解决高偏差
  • 尝试增加多项式特征——解决高偏差
  • 尝试减少正则化程度 λ——解决高偏差

过度拟合和正则化

针对训练神经网络过程中偏差过大(欠拟合),或者方差过大(过拟合)我们可以采用哪些方法?

2.1 通常方式

  • 深度学习在如今大数据时代可以通过构建一个更大的网络便可在不影响方差的同时减少你的偏差。
  • 采用更多的数据可以在不过多影响偏差的同时减少方差。扩增数据代价比较高,而且有时无法扩增数据,但我们可以通过水平翻转、随意翻转和裁剪图片来增加训练数据 。

以上两步实际要做的工作是训练网络,选择网络或者准备更多数据,现在我们有工具可以做到仅仅减少偏差或者仅仅减少方差,不对另一方产生过多不良影响。

2.2 正则化

正则化是一种非常实用的减少方差的方法,正则化会出现偏差方差权衡问题,偏差可能会略有增加,但如果网络足够大的话,增幅通常不会太大 。

这里主要讲解以下L2规范化技术。二次代价函数,以及交叉熵代价函数,柔性最大值正则化后的形式如下:

$$C=C_0 + \frac{\lambda}{2n}\sum_{w}w^2$$

其中$C_0$为原始代价函数。第二项加入的就是所有权重(每个元素)的平方和,$λ$成为规范化参数,规范化可以当做一种寻找小的权重和最小原始代价函数之间的折中,$λ$越小,就越偏向于最小化原始代价函数,反之倾向于小的权重。

常用正则化方法来防止过拟合,因此需要思考参数的选择问题。

  • $λ$越大,就会越减少过拟合现象的出现。
  • $λ$ 较小时,训练集误差较小(过拟合)而交叉验证集误差较大
  • 随着 $λ$ 的增加,训练集误差不断增加(欠拟合),而交叉验证集误差则是先减小后增加

 

2.3 弃权

利用弃权来降低过拟合。(主要应用在计算机视觉,其他领域应用较少)

假设左图存在过拟合,这就是 dropout 所要处理的,我们复制这个神经网络, dropout 会遍历网络的每一层,并概率性地设置消除神经网络中的节点,假设每个节点都以抛硬币的方式设置概率,每个节点得以保留和消除的概率都是 0.5

设置完节点概率,我们会消除一些节点,然后删掉从该节点进出的连线,最后得到一个节点更少、规模更小的网络,然后用bcakprop 方法进行训练,这是网络节点精简后的一个版本。

对于其他样本,照旧以抛硬币的方式设置概率,保留一类节点集合,删除其他类型的节点集合,对于每一个训练样本,都将采用一个精简的后的神经网络来训练它。也许你会认为这个方法有点怪,单纯遍历节点,编码也是随机,可它真的有效。

我们怎么去理解弃权?

启发式的看,当我们弃掉不同的神经元集合时,有点像我们在训练不同的神经网络。所以,弃权过程就如同大量不同的神经网络效果的平均那样。

弃权如何实现?

对于l层,我们先生成向量dl,其维数和a1.shape一致(a1表示第l层激活函数输出列向量), dl表示 dropout 向量,然后看它是否小于某数,这个数叫做 keep_prob, 是一个具体的数,表示弃权的概率,我们假设该值为它0.8,它表示保留某个隐藏单元的概率,它的作用就是生成随机矩阵。

dl是一个矩阵,每个样本和每个隐藏单元其在 dl中的对应值为 1 的概率都是 0.8,其对应值为 0 的概率是 0.2.接下来要做的是从l层获取激活函数 al, al 含有需要计算的激活函数 al*=dl(元素相乘),它的作用就是过滤 dl 中所有等于 0 的元素,如果用python 实现的话, dl 是个布尔型数值, true 或者 false,而不是 0 或 1;乘法运算会把 true 或者 false 翻译为 1 和 0。最后我们向外扩张 a3,用它除以 keep_prob 参数(why?假设第l层有 50 层神经元,在一维上 al 等于 50,我们通过因式分解将它拆成 50Xm 维的,保留和删除它们的概率分别为 80%和 20%,这意味着最后被删除或归零的单元平均有 10 个, zˆ[l+1] = wˆ[l]*al+bˆ[l+1], 我们预期是 al减少 20%,也就是说 al中有 20%的元素被归零,为了不影响 zˆ[l+1]的期望值,我们需要用 (wˆ[l+1]*al) / 0.8,它将会修正或弥补我们所需的 20%,这样 al的期望不会变)。

dl = np.random.rand(al.shape[0],al.shape[1]) < keep_prob  #dropout向量

al = np.multply(al,dl)        #乘法运算会把 true 或者 false 翻译为 1 和 0。 过滤掉dl中元素为1的神经元
al = al/keep_prob

弃权有什么不稳定的因素?

对于我们已经训练好的神经网络,我们只需计算前向输出,由于弃权矩阵dl是随机的,给定一个输入,则网络的输出也会动态变化,有时候输出结果并不会太令我们满意。

2.4 利用提前停止来降低过度拟合

在运行梯度下降时,你可以绘制训练误差图或者回归代价函数 $J$ 的优化过程图,在训练集上用 0-1 记录分类误差次数,可以看到它呈单调下降的趋势;因为在训练过程中,我们希望训练误差、代价函数 $J$ 都在下降,通过 early stopping 不仅可以看到上述这些图,还可以绘 制验证集误差图,你会发现验证集误差通常会先呈下降趋势,然后在某个节点处开始上升。

early stoping 在神经网络中随机初始化$w$ 值,它的值可能都是较小的值,随着迭代增大,而它是在中间点停止迭代过程,得到一个中等大小的$w$;与L2 正则化相似,选择参数$w$范数较小的神经网络,希望神经网络过度拟合不严重。

early stopping 的学术意思是提早停止训练神经网络,一旦校验数据集上分类准确率已经饱和,就停止训练。

但也有一个缺点:不能独立处理以下两个情况,因为提早停止梯度下降,也就停止降低代价函数 J,所以代价函数可能不会比较小,这样做的话你没有采用不同的方式来解决这个问题,你需要考虑的东西就变得更复杂了。

如果不用 early stopping,另一种方法是 L2 正则化,训练神经网络的时间就可能很长,将导致参数搜索空间更容易分解,也更容易搜索, 但缺点是你必须尝试很多正则化参数 λ 的值, 也导致搜索大量 λ 值得计算代价太高。

early stopping 的优点是只运行一次梯度下降, 你可以找出 $w$的较小值,中间值和较大值, 而无需尝试 L2 正则化超参数$λ$ 的很多值。 

训练神经网络小技巧

在训练神经网络中,我们有哪些方法可以加速神经网络的训练速度?

3.1 归一化输入(normalized)

假设一个训练集有两个特征$x_1$,$x_2$,输入特征为 2 维, 归一化需要两个步骤:

  • 零均值化
  • 归一化方差;

我们希望无论是训练集和测试集都是通过相同的μσ2定义的数据转换, 这两个是由训练集得出来的 。

 

  1. 首先计算每个特征的平均值$μ$,针对每个样本进行以下计算:$x_i = x_i - μ$。
  2. 针对新得到的样本计算方差方差$σ^2$。然后在进行以下计算:$x_i = x_i/σ$。
  3. 得到的新的样本每一个特征则服从标准正态分布μ(0,1).

为什么要标准化输入特征 ?

我们可以把左边的图当做没有归一化的代价函数曲线图,右边为经过归一化的代价曲线图。左图的话,你必须使用一个非常小的学习率,可能需要多次迭代,直到找到最小值,但函数如果是右图的话,无论从哪里开始,梯度下降法都能更直接地找到最小值,你可以使用 较大的步长,这使得函数 J 优化起来更简单快速。

实际上 $w$是个高维向量,因此二维绘制 $w$并不能正确地表达清楚,直观理解可以是代价函数更圆一些,而且更容易优化,前提是特征在相似范围内,而不是从 1 到 1000, 0 到 1的范围,而是早-1 到 1 范围内或相似的方差。所以输入特征处于不同范围时,那么归一化特征就很重要;如果特征处于相似范围内,归一化就不太需要了,当然也可以执行,通常使用归一化不管它能否提高训练和算法速度。

四 梯度检验

我们可以使用梯度检验来调试或检验 backprop 的实施是否正确。

假设网络有 如下参数,为了执行梯度检验,首先要把所有参数换成一个巨大的向量数据,你要做的就是把矩阵 $w$转换成一个向量,把所有  $w$ 矩阵转化为向量后做连接运算,得到一个巨型向量 $θ$; 代价函数 $J$ 是所有 $w$ 和 $b$ 的函数,也就是得到了一个 $θ$ 的代价函数 $J$。求导各个 $w$,$b$, 再转换成一个大向量 $dθ$。

$$J'(θ)=\frac{∂J(θ)}{∂θ}=\lim_{ε \to 0}\frac{J(θ+ε)-J(θ-ε)}{2ε}$$

为了实施梯度检验, 你要做的是循环执行, 从而对每个 $i$, 也就是每个 $θ$ 组成元素计算$dθ_{approx[i]}$的值,运用双边误差求得的值应该逼近 $dθ_{[i]}$,目的就是检验 $dθ_{approx[i]}$和 $dθ_{[i]}$ 是否相等。 先计算这两个向量的距离, 然后用向量长度进归一化, $ε$ 可能为 10 的-7 次方, 使用这个取值范围内的 $ε$, 你如果发现方程式得到的值为 10 的-7 次方或者更小, 这就很好, 这意味着导数逼近很有可能是正确的,它的值非常小;如果在 10 的-5 方范围内,要小心,也许这个值没问题,但需要再次检查这个向量的所有项,确保没有一项误差过大,如果有一项误差非常大,可能就存在 BUG。 

如何应用?

我们在调试程序的时候可以用如下公式计算:

$$dθ_{approx[i]}=\frac {J(θ [1],θ [2],...,θ [i]+ε,...θ [n])  -  J(θ [1],θ [2],...,θ [i]-ε,...θ [n])} {||2ε||}$$

然后与我们公式推导计算的$dθ$比较,看结果是否接近。

参考文章

[1].什么是高/低方差、高/低偏差

[2].验证集、偏差与方差、学习曲线

[3].【ML入门系列】(一)训练集、测试集和验证集

posted @ 2018-03-27 16:02  大奥特曼打小怪兽  阅读(1115)  评论(0编辑  收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步