Lecture6 训练神经网络(3)

1. 正则化

        有几种方法可以控制神经网络的表达能力,以防止过度拟合。

1.1 L2 正则化

        L2正则化可能是最常见的正则化形式。对于网络中的每一个权重 w,我们在损失函数中加入 1/2 λw² 项,其中 λ 是正则化强度。通常会看到前面有1/2  ,因为这样使得这一项相对于参数 w 的梯度就只是 λw,而不是2λw ,使得求导方便。L2 正则化的直观解释是严重惩罚较大的权重向量,而倾向于使得权重向量的值比较均衡。正如我们在线性分类部分所讨论的,由于权重和输入之间以乘法的方式相互作用,所以L2正则化实际上是在鼓励网络将全部的输入作为输出的影响因素,而不是将某些输入作为输出的主要影响因素,这是非常吸引人的一个特性。最后,注意到在使用梯度下降更新参数期间,使用 L2 正则化意味着每个权重最终都是线性衰减到零的,其形式为 W += -lambda * W

1.2 L1 正则化

        L1正则化是另一种比较常见的正则化形式,对于每个权重 w,我们在损失函数中加入λ∣w∣这个项。同时,我们还可以将 L1 正则化与 L2 正则化相结合:。L1正则化有一个有趣的特性,它会导致权重向量在优化过程中变得稀疏(即非常接近于零)。换句话说,具有L1正则化的神经元最终只使用输入数据中最重要部分的稀疏子集,并变得对 "嘈杂 "的输入几乎没有变化。相比之下,来自 L2 正则化的最终权重向量通常是分散的、小数字。在实践中,如果你不关心明确的特征选择,可以预期L2正则化会比L1正则化有更好的性能。

1.3 Maxnorm 正则化

        正则化的另一种形式是对每个神经元的权重向量的大小实施绝对的上限,并使用投影梯度下降法来实施该约束。在实践中,这相当于正常执行参数更新,然后通过限制每个神经元的权重向量  来强制执行约束,以满足 的要求。c 的典型值是 3 或 4 的数量级。有些人说,使用这种形式的正则化会有改进。它的一个吸引人的特性是,即使学习率设置得太高,梯度也不会 "爆炸",因为更新总是有界限的。

1.4 Dropout

        Dropout是一种极其有效、简单的正则化技术。在训练时,Dropout的实现方式是以某个概率 p(一个超参数)保留每个神经元,其余没被保留的就丢弃,即将其设置为零,不参与更新,示意图如下所示:

         在训练过程中,Dropout可以被解释为在整个神经网络中对一个子神经网络进行采样,并且根据输入数据,只更新被采样网络的参数。(然而,大部分被采样的网络并不独立,因为它们共享参数)。在测试模型时,没有使用dropout,其解释是为了评估所有子网络的集合的平均效果。

        在一个3层神经网络的例子中,原始的dropout将被实现如下:

                """ Vanilla Dropout: Not recommended implementation (see notes below) """
 
                p = 0.5 # probability of keeping a unit active. higher = less dropout
         
                def train_step(X):
                  """ X contains the data """
  
                  # forward pass for example 3-layer neural network
                  H1 = np.maximum(0, np.dot(W1, X) + b1)
                  U1 = np.random.rand(*H1.shape) < p # first dropout mask
                  H1 *= U1 # drop!
                  H2 = np.maximum(0, np.dot(W2, H1) + b2)
                  U2 = np.random.rand(*H2.shape) < p # second dropout mask
                  H2 *= U2 # drop!
                  out = np.dot(W3, H2) + b3
  
                  # backward pass: compute gradients... (not shown)
                  # perform parameter update... (not shown)
          
                def predict(X):
                  # ensembled forward pass
                  H1 = np.maximum(0, np.dot(W1, X) + b1) * p # NOTE: scale the activations
                  H2 = np.maximum(0, np.dot(W2, H1) + b2) * p # NOTE: scale the activations
                  out = np.dot(W3, H2) + b3

        在上面的代码中,在 train_step 函数中,我们进行了两次 dropout:在第一隐藏层和第二隐藏层。也可以在输入层上直接执行dropout,在这种情况下,我们也会为输入 X 创建一个二进制掩码。

        最重要的是,注意在 predict 函数中,我们不使用 dropout,而是对两个隐藏层的输出进行 p 的缩放。这很重要,因为在测试模型时,所有的神经元都得到了它们的所有输入,所以我们希望测试时神经元的输出与训练时的预期输出相同。例如,在 p=0.5 的情况下,神经元在测试时必须将其输出减半,以获得与训练时相同的输出的期望值。为了看到这一点,考虑一个神经元 x 的输出(dropout前),在使用 dropout 后,该神经元的预期输出将变成p*x+(1-p)*0 ,因为该神经元的输出将以 1-p 的概率被设置为零。在测试模型时,当我们保持该神经元始终处于活动状态时,我们必须调整 s->px 以保持相同的预期输出。

        上面提出的方案的不理想之处在于,我们必须在测试时将输出按 p 进行调整。由于测试模型时的计算性能非常关键,这样的调整会耗费计算性能。所以最好是使用倒置的dropout,它在训练时进行缩放,而在测试时不调整前向传播。此外,这还有一个吸引人的特性,即当你决定调整应用dropout的位置时,预测模型的代码可以保持不动(实现了降耦)。其代码如下:

                """ 
                Inverted Dropout: Recommended implementation example.
                We drop and scale at train time and don't do anything at test time.
                """
 
                p = 0.5 # probability of keeping a unit active. higher = less dropout
                 
                def train_step(X):
                  # forward pass for example 3-layer neural network
                  H1 = np.maximum(0, np.dot(W1, X) + b1)
                  U1 = (np.random.rand(*H1.shape) < p) / p # first dropout mask. Notice /p!
                  H1 *= U1 # drop!
                  H2 = np.maximum(0, np.dot(W2, H1) + b2)
                  U2 = (np.random.rand(*H2.shape) < p) / p # second dropout mask. Notice /p!
                  H2 *= U2 # drop!
                  out = np.dot(W3, H2) + b3
  
                  # backward pass: compute gradients... (not shown)
                  # perform parameter update... (not shown)
  
                def predict(X):
                  # ensembled forward pass
                  H1 = np.maximum(0, np.dot(W1, X) + b1) # no scaling necessary
                  H2 = np.maximum(0, np.dot(W2, H1) + b2)
                  out = np.dot(W3, H2) + b3

前向传播中的噪声:

        Dropout 以一个更普遍的方式在网络的前向传递中引入随机量。这些方法都是在训练的时候增加随机噪声,测试时通过分析法(在使用随机失活的本例中就是乘以 p )或数值法(例如通过抽样出很多子网络,随机选择不同子网络进行前向传播,最后对它们取平均)将噪音边缘化。这个方向的一个例子包括DropConnect,它在前向传递过程中,将一组随机的权重设置为零。作为预示,卷积神经网络也利用了这个方法,如随机池化、分数池化和数据增强。我们将在后面讨论这些方法的细节。

偏置项正则化:

        正如我们在线性分类部分已经提到的,对偏置参数进行正则化并不常见,因为它们不通过乘法与数据进行交互,因此不具有控制数据维度从而对最终目标产生影响的能力。然而,在实际应用中(并且有适当的数据预处理),对偏置项进行正则化很少会导致性能明显下降。这可能是因为与所有的权重相比,偏置项非常少。

分层正则化:

        对不同的层(也许输出层除外)采用不同的正则化并不是很常见。文献中发表的关于这一想法的结果相对较少。

在实践中:

        最常见的是使用单一的、全局的、经过交叉验证的L2正则化。在所有层之后将其与 dropout 结合起来也很常见。p=0.5的值是一个合理的默认值,但这可以在验证集上进行调参。

2. 迁移学习

        实际上,很少的人会训练整个卷积神经网络(使用随机的初始化),因为相对来说,很少有足够大的数据集可以用于训练。作为代替,常见的方式是在一个很大的数据集中预训练一个卷积神经网络(比如ImageNet,120万张1000类别图片),然后或者将这个训练后的网络参数作为初始化参数,或者直接作为一个特质提取器用于所关注的任务。三种常见的迁移学习类型如下所示:

2.2 作为固定的特征提取器

        获取一个使用ImageNet预训练的卷积神经网络,移除最后一个全连接层(这一层输出1000个类别得分),然后将剩余的卷积神经网络视为一个用于新数据集的特征提取器。在AlexNet中,这将为每张图像计算一个4096维的向量,其中包含紧接分类器之前的隐藏层的激活项。我们称这些提取得到的特征为 CNN code。 如果这些代码在ImageNet上训练的过程中也被阈值化(通常是这样),那么这些 CNN code 也需要进行ReLU,这对性能是很重要的。一旦你提取出了 4096维的结果,你就可以为这个新的数据集训练一个线性分类器(如线性SVM,Softmax分类器等)。

2.3 对卷积神经网络调优

        第二种策略是不仅在新的数据集上替换和重新训练卷积神经网络最后一层的分类器,而且还通过继续反向传播对预训练网络的权重进行微调。我们可以对卷积神经网络的所有层进行微调,也可以将前面的一些层固定下来(出于过拟合的考虑),只对网络的一些高层部分进行微调。这是由于通过观察发现,卷积神经网络的前面几层提取的特征包含更多的通用特征(如边缘特征或色块特征),这些特征对许多任务都有用,具有通用性。而网络的后面的层能对原始数据集中类别的细节特征进行更具体的提取。以ImageNet为例,它包含许多狗的品种,卷积神经网络的很大一部分表现力可能被用于区分狗的品种的具体特征。

2.4 预训练模型

        由于现在的卷积神经网络一般需要2-3周的时间在多个GPU上进行训练,所以人们会发布他们的模型参数,以利于其他人使用这些网络进行微调。例如,Caffe库有一个模型Zoo,人们在那里分享他们的网络权重。

2.5. 如何调优

        如何决定你应该在一个新的数据集上执行什么类型的迁移学习?这是由几个因素共同决定的,但最重要的两个因素是新数据集的大小(小或大),以及它与原始数据集的相似性(例如,在图像内容和类别方面类似于ImageNet,或非常不同,如显微镜图像)。考虑到卷积神经网络在前面的层中提取的特征比较通用,而在后面的层中提取的特征比较针对特定数据集,这里有一些通用的经验法则:

  • 新的数据集很小,与原始数据集相似。由于数据很小,出于过拟合的考虑,对卷积神经网络进行微调并不是一个好主意。由于数据与原始数据相似,我们希望卷积神经网络中更高层次的特征也能与这个数据集相关。因此,最好的办法可能是将模型作为特征提取器训练一个线性分类器。
  • 新的数据集很大,与原始数据集相似。由于我们有更多的数据,我们可以有更多的信心能在对网络微调的时候使得其不会发生过拟合,所以我们可以使用微调的方案。
  • 新的数据集很小,但与原始数据集有很大不同。由于数据很小,最好只训练一个线性分类器。由于新数据集与预训练的数据集非常不同,最好不要训练网络最后面一层的分类器,因为它包含了很多预训练时采用的数据集中的特定的特征。相反,从网络的靠前的几层就开始训练SVM分类器可能效果更好。
  • 新的数据集很大,而且与原始数据集有很大不同。由于数据集非常大,我们是可以对卷积神经网络进行从头训练的。然而,在实践中,用预训练过的模型的权重进行初始化,往往还是有好处的。在这种情况下,我们会有足够的数据来对整个网络进行微调。

2.6. 实用的建议

  • 来自预训练模型的约束:

    请注意,如果你想使用预训练的网络,你可能会在新数据集的架构方面受到一些限制。例如,你不能随意改变网络的结构,比如从预训练的网络中取出某个卷积层。然而,有些变化是可以的:由于参数共享,你可以很容易地在不同空间大小的图像上运行同一个预训练的网络。这在使用卷积层和池化层的情况下是很明显的,因为它们的前向函数与输入数据的大小无关(只要步长 "合适")。在使用全连接层的情况下,这一点仍然成立,因为全连接层可以被转换为卷积层。

  • 学习率:

    与用于计算新数据集的类别分数的线性分类器的(随机初始化的)权重相比,对正在微调的卷积神经网络的权重使用较小的学习率是比较好的。这是因为我们认为目前的卷积神经网络的权重已经相对够好了,只需要进行微调即可,所以我们不希望太快、太多扭曲它们(尤其是当新线性分类器正在从随机初始化开始训练时)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值