Skip to main content

Command Palette

Search for a command to run...

《深度学习入门》的cpp实现-ch06: 与学习相关的技巧

Published
《深度学习入门》的cpp实现-ch06: 与学习相关的技巧

上一篇文章中,我们使用随机正态分布初始化神经网络的权重,SGD的方法更新参数,对于学习率、batch大小、权重衰减率等超参数选择了固定值,这篇文章我们会探讨对于这些做法的改进方案。

由于这一节涉及到众多方法, 并且要求网络结构复杂,不能逐一进行"cpp实现",理解原理并掌握即可(所以请把这篇文章当作读书笔记看待)。

参数的更新

SGD

SGD公式如下 $$W \gets W - \eta \frac{\partial L}{\partial W} $$

SGD原理简单,并且在代码上容易实现,但是针对某些参数空间, 解决问题的效率比较低下,比方说对于 $$f(x,y) = \frac{1}{20}x^2 + y^2$$

image.png

梯度特征是,在y轴方向上很大,在x轴方向上很小。虽然在(x,y)=(0,0)处梯度最小,但是很多地方梯度并没有指向(0, 0)

对于这种函数形状非均向(anisotropic),比如呈延伸状,搜索的路径就会非常低效,根本原因是梯度的方向并没有指向最小值的方向。

image.png

Momentum

Momentum是“动量”的意思,公式如下 $$v \gets \alpha v - \eta \frac{\partial L}{\partial W}$$ $$W \gets W + v$$ η 表示学习率; v对应物理上的速度; αv 在物体不受任何力时,该项承担使物体逐渐减速的任务,对应物理上的地面摩擦或空气阻力。

在 Momentum 公式中,W 保存了过往梯度的矢量和。如果在一个方向上,梯度方向变化反复,那么经过多次,在一个方向上的力会被抵消;如果在一个方向上,梯度很小,但是持续不变,那么经过多次,在这个方向上的力就会有一个“加速度”。

image.png

和 SGD 相比,我们发现“之”字形的“程度”减轻了。这是因为虽然 x 轴方向上受到的力非常小,但是一直在同一方向上受力,所以朝同一个方向会有一定的加速。反过来,虽然 y 轴方向上受到的力很大,但是因为交互地受到正方向和反方向的力,它 们会互相抵消,所以 y 轴方向上的速度不稳定。

AdaGrad

在神经网络的学习中,学习率过小, 会导致学习花费过多时间;学习率过大,则会导致学习发散而不能正确进行。

AdaGrad 会为参数的每个元素适当地调整学习率,与此同时进行学习 (AdaGrad 的 Ada 来自英文单词 Adaptive,即“适当的”的意思)。

$$h \gets h + \frac{\partial L}{\partial W} \odot \frac{\partial L}{\partial W} $$ $$ W \gets W - \eta \frac{1}{\sqrt{h}} \frac{\partial L}{\partial W} $$

在更新参数时,通过乘以 1/sqrt(h),就可以调整学习的尺度。这意味着,参数的元素中变动较大(被大幅更新)的元素的学习率将变小。也就是说,可以按参数的元素进行学习率衰减,使变动大的参数的学习率逐渐减小。

image.png

Adam

Adam 是 2015 年提出的新方法。它的理论有些复杂,直观地讲,就是融合了 Momentum 和 AdaGrad 的方法。

image.png

image.png

权重初始值

随机的初始化值

当深度学习网络发生过拟合时,是由于权重参数过大导致的。如果要抑制过拟合,在设定权重初始值的时候就选择比较小的值。

那么如果将权重初始值设定为0,这并不是一个好主意。将权重参数设置为0,或者设置为一样的值,会导致后面层神经元会在前向推理时传递相同的值,意味着在反向传播的时候,所有权重参数会进行相同的更新。这使得神经网络拥有许多不同的权重的意义丧失了。为了防止“权重均一化”(严格地讲,是为了瓦解权重的对称结构),必须随机生成初始值。

隐藏层的激活值的分布

  • 当使用第一层网络权重标准差为1的高斯分布

image.png

这里使用激活函数sigmoid函数是S型函数,随着输出不断地靠近0(或者靠近1),它的导数的值逐渐接近0。因此,偏向0和1的数据分布会造成反向传播中梯度的值不断变小,最后消失。这个问题称为梯度消失(gradient vanishing)

  • 将权重的标准差设为 0.01,进行相同的实验

image.png

这次的激活值分布有所偏向,说明多个神经元会输出近似相同的值,有些神经元的存在是没有意义的,整个神经网络会表现力受限

** Xavier 初始值 在 Xavier Glorot 的论文中, 为了使各层的激活值呈现出具有相同广度的分布, 提出前一层的节点数越多,要设定为目标节点的初始值的权重尺度就越小。

如果前一层的节点数为 n,则初始值使用标准差为1/sqrt(n)的高斯分布

image.png

** He 初始值

当激活函数使用 ReLU 时,一般推荐使用 ReLU 专用的初始值,也被称为"He初始值"。

当前一层的节点数为 n 时,He 初始值使用标准差为sqrt(2/n)的高斯分布。和 Xavier初始值相比,因为 ReLU 的负值区域的值 为 0,为了使它更有广度,所以需要 2 倍的系数。

Batch Normalization

Batch Norm的思路是调整各层的激活值分布使其拥有适当广度,有以下优点:

  • 可以使学习快速进行(可以增大学习率)。
  • 不那么依赖初始值(对于初始值不用那么神经质)。
  • 抑制过拟合(降低Dropout等的必要性)。

image.png

正则化

过拟合

发生过拟合的原因,主要有以下两个:

  1. 模型拥有大量参数、表现力强。
  2. 训练数据少。

权值衰减

很多过拟合原本就是 因为权重参数取值过大才发生的。权值衰减通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。为损失函数加上权重的平方范数(L2范数)。这样一来,就可以抑制权重变大。

Dropout

Dropout 是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递。

训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出

image.png

class Dropout:
    def __init__(self, dropout_ratio=0.5):
        self.dropout_ratio = dropout_ratio
        self.mask = None
    def forward(self, x, train_flg=True):
        if train_flg:
            # 训练时, 随机选择神经元, 并且将选择神经元序号保存
            self.mask = np.random.rand(*x.shape) > self.dropout_ratio
            return x * self.mask
        else:
            # 推理时,将每个值乘以保留系数
            return x * (1.0 - self.dropout_ratio)
    def backward(self, dout):
        # 反向传播时,使用mask选择保留的神经元进行
        return dout * self.mask

可以将 Dropout 理解为,通过在学习过程中随机删除神经元,从而每一次都让不同的模型进行学习。

##超参数的验证

调整超参数时,必须使用超参数专用的确认数据。用于调整超参 数的数据,一般称为验证数据(validation data)

超参数的范围只要“大致地指定”就可以了。所谓“大致地指定”,是指像0.001到1000这样,以“10的阶乘”的尺度指定范围(也表述为“用对数尺度(logscale)指定”)。

More from this blog

<Programming with Types>随想: Chapter 2. Basic types

类型限制了一个变量可以接受的有效值的集合,对数据可以进行的操作,数据的意义。 空类型(The empty type) 根据类型的定义,类型定义了可以接受的有效值集合,那么这个集合有没有可能为空?答案是有可能的,TypeScirpt 的 never 就是这种类型。 需要注意的是,空类型不同与 void, 后者是有效值集合当中只有一个值,但这个值没有任何意义。而空类型的有效值集合本身是空的。 使用场景 控制流分析 在函数调用时,标志一个函数不会返回任何值: 在调用过程中抛出异常、死循环或者程序崩溃...

Mar 5, 2023
<Programming with Types>随想: Chapter 2. Basic types

精读《设计机器学习系统》-ch04: 训练数据

不同于 Chapter03 从系统的角度来处理数据,这一章从数据科学的视角来处理数据。这章的标题是“training Data”,而非“training dataset”,因为 数据集(dataset) 意味着有限(finite)和固定(stationary), 而现实生产环境中的 数据(data) 通常是 无限 并且 不固定 的。 抽样 抽样方法在 ML 项目的生命周期中无处不在,在这一节中,我们使用生成训练数据作为例子。 那为什么需要抽样?直接使用全部数据不可以吗? 首先,在现实世界中,并不...

Dec 10, 2022
精读《设计机器学习系统》-ch04: 训练数据
7

70 Talk

19 posts