深度学习训练 tricks(持续更新)

news2024/9/29 21:20:41

妈妈,我的炼丹炉子炸啦(不是)
妈妈,我的深度学习模型训练好了!

本文持续更新,如果有什么你知道的深度学习模型训练技巧,可以在评论区提出,我会加进来的。

文章目录

  • weight decay
    • weight decay 是什么
    • weight decay 与 L2 正则化
    • 作用
  • Warmup
  • Drop path
    • drop path 计算方法
    • 如何将 drop path 加入你的模型?
    • drop path 的作用
    • 待修改
  • 指数移动平均(EMA)
  • SGD 的 momentum
  • AdamW 的 eps 和 betas

weight decay

weight decay 是什么

weight_decay 作为一个超参数,传入 optimizer 的构造器中,所以这个参数显然是与梯度更新有关的。

梯度更新公式:
θ t ← θ t − 1 − λ ⋅ g t \theta_t \leftarrow \theta_{t-1} - \lambda\cdot g_t θtθt1λgt
其中 θ \theta θ 是参数, λ \lambda λ 是学习率, g t g_t gt 是 t 时刻的梯度

在梯度更新公式中加入一个衰减参数 β \beta β
θ t ← ( 1 − β ) ⋅ θ t − 1 − λ ⋅ g t \theta_t \leftarrow (1-\beta)\cdot\theta_{t-1} - \lambda\cdot g_t θt(1β)θt1λgt
这个 β \beta β 就是 weight decay 的参数,一般取值比较小,比如0.0005

在深度学习模型中,一般将衰减系数设置为 0.00010.001 之 间的值,这是一个比较常用的范围;
当你不确定模型复杂度和数据集大小的时候,最保守就是从1e-4周围开始尝试;
来源:https://zhuanlan.zhihu.com/p/607909453

weight decay 与 L2 正则化

来源:权重衰减(weight decay)与学习率衰减(learning rate decay)

L2正则化就是在代价函数后面再加上一个正则化项

代价函数,损失函数,目标函数区别

  • 损失函数(Loss Function )是定义在单个样本上的,算的是一个样本的误差。
  • 代价函数(Cost Function )是定义在整个训练集上的,是所有样本误差的平均,也就是损失函数的平均。
  • 目标函数(Object Function)定义为:最终需要优化的函数。等于经验风险+结构风险(也就是代价函数 + 正则化项)。(经验风险最小指,在训练集上的预测最准确;结构风险减低是指,模型简单,过于复杂的模型容易过拟合)

C = C 0 + α 2 n ∑ w w 2 C=C_0+\frac{\alpha}{2n}\sum_ww^2 C=C0+2nαww2
C 0 C_0 C0 是原始代价函数,后面那一项是 L2 正则化项:所有参数 w w w 的平方和,除训练集的样本大小 n n n α \alpha α 是正则项系数,分母中的 2 用于求导系数配平。

为什么说 weight decay 在某些情况下就是 L2 正则化?

对 L2 正则化后的代价函数求导:
∂ C ∂ w = ∂ C 0 ∂ w + α n w \frac{\partial C}{\partial w}=\frac{\partial C_0}{\partial w} + \frac{\alpha}{n}w wC=wC0+nαw
w ← w − λ ∂ C 0 ∂ w − λ α n w w \leftarrow w - \lambda \frac{\partial C_0}{\partial w} - \lambda \frac{\alpha}{n}w wwλwC0λnαw
w ← ( 1 − λ α n ) w − λ ∂ C 0 ∂ w w \leftarrow \left(1-\lambda \frac{\alpha}{n}\right)w - \lambda \frac{\partial C_0}{\partial w} w(1λnα)wλwC0

weight decay:
β = λ α n \beta = \lambda \frac{\alpha}{n} β=λnα

作用

直观上,weight decay 在权重参数上加了一个缩小因子,使得权重整体保持在一个较小在的值,顺便可以避免梯度爆炸。

weight decay 和 L2 正则化项有让 w w w 变小的效果,但是为什么 w w w 变小可以防止过拟合呢?

来源:权重衰减(weight decay)与学习率衰减(learning rate decay)

(1)从模型的复杂度上解释:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合更好(这个法则也叫做奥卡姆剃刀),而在实际应用中,也验证了这一点,L2正则化的效果往往好于未经正则化的效果。(2)从数学方面的解释:过拟合的时候,拟合函数的系数往往非常大,为什么?过拟合,就是拟合函数需要顾忌每一个点,最终形成的拟合函数波动很大。在某些很小的区间里,函数值的变化很剧烈。这就意味着函数在某些小区间里的导数值(绝对值)非常大,由于自变量值可大可小,所以只有系数足够大,才能保证导数值很大。而正则化是通过约束参数的范数使其不要太大,所以可以在一定程度上减少过拟合情况。

Warmup

来源:神经网络中 warmup 策略为什么有效;有什么理论解释么?

使用 SGD 训练神经网络时,在初始使用较大学习率而后期切换为较小学习率是一种广为使用的做法,在实践中效果好且最近也有若干文章尝试对其进行了理论解释。

而 warmup 策略则与上述 scheme 有些矛盾。warmup 需要在训练最初使用较小的学习率来启动,并很快切换到大学习率而后进行常见的 decay。那么最开始的这一步 warmup 为什么有效呢?

  • 有助于减缓模型在初始阶段对mini-batch的提前过拟合现象,保持分布的平稳
  • 有助于保持模型深层的稳定性

刚开始模型对数据的“分布”理解为零,或者是说“均匀分布”(当然这取决于你的初始化);在第一轮训练的时候,每个数据点对模型来说都是新的,模型会很快地进行数据分布修正,如果这时候学习率就很大,极有可能导致开始的时候就对该数据“过拟合”,后面要通过多轮训练才能拉回来,浪费时间。当训练了一段时间(比如两轮、三轮)后,模型已经对每个数据点看过几遍了,或者说对当前的batch而言有了一些正确的先验,较大的学习率就不那么容易会使模型学偏,所以可以适当调大学习率。这个过程就可以看做是warmup。那么为什么之后还要decay呢?当模型训到一定阶段后(比如十个epoch),模型的分布就已经比较固定了,或者说能学到的新东西就比较少了。如果还沿用较大的学习率,就会破坏这种稳定性,用我们通常的话说,就是已经接近loss的local optimal了,为了靠近这个point,我们就要慢慢来。
如果一开始就用0.1,虽然最终会收敛,但之后acc还是不会提高(使用了pateaus schedule);如果用了warmup,在收敛后还能有所提高。也就是说,用warmup和不用warmup达到的收敛点,对之后模型能够达到的suboptimal有影响。这说明什么?这说明不用warmup收敛到的点比用warmup收敛到的点更差。这可以从侧面说明,一开始学偏了的权重后面拉都拉不回来……

Drop path

DropPath/drop_path 是一种正则化手段,其效果是将深度学习模型中的多分支结构随机”删除“

drop path 计算方法

pytorch 源码,我对其进行注释:

def drop_path(x, drop_prob: float = 0., training: bool = False, scale_by_keep: bool = True):
    """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks).

    This is the same as the DropConnect impl I created for EfficientNet, etc networks, however,
    the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper...
    See discussion: https://github.com/tensorflow/tpu/issues/494#issuecomment-532968956 ... I've opted for
    changing the layer and argument names to 'drop path' rather than mix DropConnect as a layer name and use
    'survival rate' as the argument.

    """
    # drop_prob 是随机失活的比例,如果=0,则所有都不失活;如果=1,则所有都失活
    if drop_prob == 0. or not training:
        return x
    # keep_prob 是保留的比例,假设 drop_prob=0.1 则 keep_prob=0.9
    # 含义是,每个分支都有 0.9 的概率被保留,有 0.1 的概率被失活
    keep_prob = 1 - drop_prob
    shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # work with diff dim tensors, not just 2D ConvNets
    # 失活的方法是,生成一个随机 tensor,这个 tensor 的每一个值都是 0 或者 1,有 keep_prob 的概率为 1;
    # 等下这个随机 tensor 和 x 相乘,于是对应的位置 x 变成 0,实现失活的效果
    random_tensor = x.new_empty(shape).bernoulli_(keep_prob)
    if keep_prob > 0.0 and scale_by_keep:
        random_tensor.div_(keep_prob)
    return x * random_tensor

如何将 drop path 加入你的模型?

以 ViT 的 block 代码为例,ViT 的模型结构图:
在这里插入图片描述ViT block 的 pytorch 代码:

class Block(nn.Layer):
    def __init__(self,
                 dim,
                 num_heads,
                 mlp_ratio=4.,
                 qkv_bias=False,
                 qk_scale=None,
                 drop=0.,
                 attn_drop=0.,
                 drop_path=0.,
                 act_layer=nn.GELU,
                 norm_layer='nn.LayerNorm',
                 epsilon=1e-5):
        super().__init__()
        self.norm1 = eval(norm_layer)(dim, epsilon=epsilon)
        # Multi-head Self-attention
        self.attn = Attention(
            dim,
            num_heads=num_heads,
            qkv_bias=qkv_bias,
            qk_scale=qk_scale,
            attn_drop=attn_drop,
            proj_drop=drop)
        # DropPath
        self.drop_path = DropPath(drop_path) if drop_path > 0. else Identity()
        self.norm2 = eval(norm_layer)(dim, epsilon=epsilon)
        mlp_hidden_dim = int(dim * mlp_ratio)
        self.mlp = Mlp(in_features=dim,
                       hidden_features=mlp_hidden_dim,
                       act_layer=act_layer,
                       drop=drop)

    def forward(self, x):
        # Multi-head Self-attention, Add, LayerNorm
        x = x + self.drop_path(self.attn(self.norm1(x)))
        # Feed Forward, Add, LayerNorm
        x = x + self.drop_path(self.mlp(self.norm2(x)))
        return x

好好观察,ViT 中使用 drop path 的时候,返回的是:

return x + self.drop_path(self.mlp(self.norm2(x)))
# 这种写法是错误的
# return self.drop_path(self.mlp(self.norm2(x)))

drop path 的作用

DropPath 类似于Dropout,不同的是 Drop将深度学习模型中的多分支结构随机 “失效”,而Dropout 是对神经元随机 “失效”。

注:很多文章里说,dropout / drop path 是随机“删除”一些神经元 / 分支结构。这种说法很容易误导,让人疑惑这个“删除”是怎么个删除法?实际上模型结构并不会改变,只是让这个神经元的输出结果置零

在 dropout 中,比如原始网络的计算结构是:
y = a 1 ⋅ x 1 + a 2 ⋅ x 2 + a 3 ⋅ x 3 + a 4 ⋅ x 4 y=a_1\cdot x_1 + a_2\cdot x_2 + a_3\cdot x_3 + a_4\cdot x_4 y=a1x1+a2x2+a3x3+a4x4
令 dropout = 0.25,即每个神经元有 0.25 的概率,它的输出结果被置零。假设有个被失活的幸运儿是 a 1 a_1 a1,那么:
训练
y = 0 + a 2 ⋅ x 2 + a 3 ⋅ x 3 + a 4 ⋅ x 4 y=0 + a_2\cdot x_2 + a_3\cdot x_3 + a_4\cdot x_4 y=0+a2x2+a3x3+a4x4
测试
y = 0.75 ∗ ( a 1 ⋅ x 1 + a 2 ⋅ x 2 + a 3 ⋅ x 3 + a 4 ⋅ x 4 ) y=0.75 * (a_1\cdot x_1 + a_2\cdot x_2 + a_3\cdot x_3 + a_4\cdot x_4) y=0.75(a1x1+a2x2+a3x3+a4x4)

待修改

(Drop Path 让部分 multi-head 失活??(待做实验验证)

随机丢失不会趋于一致性(平凡化?或者说趋同进化?)

指数移动平均(EMA)

指数移动平均(Exponential Moving Average)也叫权重移动平均(Weighted Moving Average),是一种给予近期数据更高权重的平均方法。

计算方法白话版本解说:

一个模型在训练的时候,维护两套参数。一套参数叫 θ \theta θ ,用梯度下降正常更新:
θ t = θ t − 1 − g t − 1 \theta_t = \theta_{t-1} - g_{t-1} θt=θt1gt1
这里 g g g 是梯度

另一套参数叫影子参数,在这里记为 ν \nu ν,影子参数不用梯度更新,而是用 θ \theta θ 更新:
ν t = α ⋅ ν t − 1 + ( 1 − α ) ⋅ θ t \nu_t=\alpha\cdot \nu_{t-1} + (1-\alpha)\cdot\theta_t νt=ανt1+(1α)θt

然后导出训练结果的时候,不用 θ \theta θ 而是 ν \nu ν

原理的囫囵吞枣讲解,省略公式推导过程,直接看公式推导结果:
θ t = θ 1 − ∑ i = 1 t − 1 g i \theta_t=\theta_1-\sum^{t-1}_{i=1}g_i θt=θ1i=1t1gi
ν t = θ 1 − ∑ i = 1 t − 1 ( 1 − α t − 1 ) g i \nu_t=\theta_1-\sum^{t-1}_{i=1}\left(1-\alpha^{t-1}\right)g_i νt=θ1i=1t1(1αt1)gi
对比上下两个公式,很容易发现,差别就在于:每次通过梯度更新 ν \nu ν 这套参数的时候,加了个系数 ( 1 − α t − 1 ) \left(1-\alpha^{t-1}\right) (1αt1),使得:

  • t t t 越大
  • α t − 1 \alpha^{t-1} αt1 越小( 0 < α < 1 0<\alpha<1 0<α<1
  • ( 1 − α t − 1 ) \left(1-\alpha^{t-1}\right) (1αt1) 这个系数越大

也就是说,越是刚刚算出来的梯度( t t t 越小),对最终导出的结果影响越大。

基本的假设是,模型权重在最后的n步内,会在实际的最优点处抖动,所以我们取最后n步的平均,能使得模型更加的鲁棒。

想知道更详细的公式推导,请看:【炼丹技巧】指数移动平均(EMA)的原理及PyTorch实现

SGD 的 momentum

SGD是随机梯度下降(stochastic gradient descent)的首字母。设模型参数为 θ \theta θ,梯度为 g g g
θ t = θ t − 1 − g t ⋅ l r \theta_t = \theta_{t-1} - g_{t}\cdot lr θt=θt1gtlr
momentum 动量值,帮助参数更新离开盆地:
g t ′ = β ⋅ g t − 1 + ( 1 − β ) ⋅ g t g_t'= \beta\cdot g_{t-1} + (1-\beta)\cdot g_t gt=βgt1+(1β)gt
θ t = θ t − 1 − g t ′ ⋅ l r \theta_t =\theta_{t-1} - g_t'\cdot lr θt=θt1gtlr

AdamW 的 eps 和 betas

来源:优化器:Adam与AdamW
Adam: Adam使用了动量来加速梯度下降,它引入了两个动量参数 β 1 \beta_1 β1(用于一阶矩估计)和 b e t a 2 beta_2 beta2 (用于二阶矩估计)。这些动量参数决定了过去梯度的影响程度。

小标题中的 eps (float, 可选) – 为了增加数值计算的稳定性而加到分母里的项(默认:1e-8)即代码中的 epsilon

# Adam 更新规则
m = beta1*m + (1-beta1)*grad
v = beta2*v + (1-beta2)*(grad**2)
theta = theta - learning_rate * m / (sqrt(v) + epsilon)

AdamW: Adam with Weight Decay Fix

# AdamW 更新规则
m = beta1*m + (1-beta1)*(grad + lamb*theta)
v = beta2*v + (1-beta2)*(grad**2) 
theta = theta - learning_rate * m / (sqrt(v) + epsilon)

二者的区别在于,AdamW 中加入了 lamb,即 λ \lambda λ,weight decay 的参数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1283653.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

3DMM模型

目录 BFMBFM_200901_MorphableModel.matexp_pca.bintopology_info.npyexp_info.npy BFM BFM_2009 01_MorphableModel.mat from scipy.io import loadmat original_BFM loadmat("01_MorphableModel.mat") # dict_keys: [__header__, __version__, __globals__, # …

C++ 文件操作之配置文件读取

C 文件操作之配置文件读取 在项目应用时常常会涉及一些调参工作&#xff0c;如果项目封装成了.exe或者.dll&#xff0c;那么频繁调参多次编译是一件十分低效的事情&#xff0c;如果代码算法或者逻辑是一定的&#xff0c;那么参数完全可以通过读入配置文件来获取之前在用C - op…

SpringBoot药品进销存管理系统(诊所管理系统)(乡村药店管理系统)

SSM毕设分享 SpringBoot药品进销存管理系统(诊所管理系统)(乡村药店管理系统) 1 项目简介 Hi&#xff0c;各位同学好&#xff0c;这里是郑师兄&#xff01; 今天向大家分享一个毕业设计项目作品【SpringBoot药品进销存管理系统(诊所管理系统)(乡村药店管理系统)】 师兄根据实…

ROS-ROS通信机制-话题通信

文章目录 一、话题通信基础知识二、话题通信基本操作2-1 C2-2 Python2-3 C与python节点通信 三、自定义msg3-1 自定义msg3-2 C实现自定义msg调用3-3 Python实现自定义msg调用 一、话题通信基础知识 话题通信实现模型是比较复杂的&#xff0c;该模型如下图所示,该模型中涉及到三…

zxjy001-项目整体介绍

1、项目类型 全栈项目 前端&#xff1a;系统后台&#xff0c;系统前台后端&#xff1a;提供API接口 2、项目技术栈 前端 Vue,Element,Axios,NodeJs后端 Spring Boot,Spring Cloud,MybatisPlus,Spring Security,Redis,Maven,JWT,OAuth2其他技术 阿里云oss服务阿里云视频点播…

微服务实战系列之Cache(技巧篇)

前言 凡工具必带使用说明书&#xff0c;如不合理的使用&#xff0c;可能得到“意外收获”。这就好比每个人擅长的领域有所差异&#xff0c;如果放错了位置或用错了人&#xff0c;也一定会让 Leader 们陷入两难之地&#xff1a;“上无法肩负领导之重托&#xff0c;下难免失去伙伴…

设计模式之代理模式(1)

目录 概述定义应用场景主要角色类图 详述基本代码应用实例符合的设计原则 总结 概述 定义 代理模式是一种结构型设计模式&#xff0c;它允许通过一个代理对象来控制对原始对象的访问。代理对象可以在不改变原始对象的情况下&#xff0c;增加一些额外的功能&#xff0c;例如权限…

kubectl获取ConfigMap导出YAML时如何忽略某些字段

前言&#xff1a; 当我们在使用Kubernetes时&#xff0c;常常需要通过kubectl命令行工具来管理资源。有时我们也想将某个资源的配置导出为YAML文件&#xff0c;这样做有助于版本控制和资源的迁移。然而&#xff0c;默认情况下&#xff0c;使用kubectl get命令导出资源配置会包…

【IPv6】IPv6协议

一、IPv6数据报格式 这是与v4报头的对比 1.8bit的版本保留了&#xff0c;v4版本就是4&#xff0c;v6就是6。 2.v6去除了v4的首部长度字段&#xff0c;因为v6的首部长是固定的40字节。 3.服务类型&#xff08;Type of Service, ToS&#xff09;和通信类型&#xff08;Traffi…

【Linux下如何生成coredump文件】

一&#xff0c;什么是coredump 我们经常听到大家说到程序core掉了&#xff0c;需要定位解决&#xff0c;这里说的大部分是指对应程序由于各种异常或者bug导致在运行过程中异常退出或者中止&#xff0c;并且在满足一定条件下&#xff08;这里为什么说需要满足一定的条件呢&#…

贝叶斯网络 (人工智能期末复习)

文章目录 贝叶斯网络&#xff08;概率图模型&#xff09;定义主要考点例题- 要求画出贝叶斯网络图- 计算各节点的条件概率表- 计算概率- 分析独立性 贝叶斯网络&#xff08;概率图模型&#xff09; 定义 一种简单的用于表示变量之间条件独立性的有向无环图&#xff08;DAG&am…

操作系统概述及发展史、Linux内核、发行版及应用领域

一、 操作系统&#xff08;Operation System&#xff0c;OS&#xff09; 裸机&#xff1a;没有安装操作系统的计算机 如果想在 裸机 上运行自己所编写的程序&#xff0c;就必须用机器语言书写程序如果计算机上安装了操作系统&#xff0c;就可以在操作系统上安装支持的高级语言…

工程师业余生活之制作蔬菜盆景

工程师业余生活陶冶情操之制作蔬菜盆景 &#xff08;蔬 果 盆 景 裝 點 家 居&#xff09; 市場上好多蔬菜瓜果,稍用一些心思,將一些價廉的蔬果製成別致的盆景, 便能使家居充滿自然氣息&#xff0c;增添生活情趣。以下介紹幾種製作方法&#xff1a; 【番薯盆景】 (番薯又名地…

人工智能_机器学习060_核函数对应数学公式_数据空间错位分割_简单介绍_以及核函数总结---人工智能工作笔记0100

我们之前做的都是线性分类问题,那么需要一根线来分割类别,但是,如果出现了,环形数据,我们知道,在二维中我们就无法分割了,那么有没有什么办法分割呢? 实际上是有的,可以看到,我们可以把数据进行升维,可以看到,如果把数据升高到2维度以上,可以看到,神奇的一幕出现了,这个时候,因…

每日3道PWN(第一天)

环境准备 我现在用的是kali 现阶段工具&#xff1a;checkesc、IDA、比较完善的python环境 下载工具的话&#xff0c;我这里不提供了 buuctf——test_your_nc1 参考wp&#xff1a; BUUCTF PWN-----第1题:test_your_nc_buuctf test_your_nc-CSDN博客 查看的资料&#xff1a;…

风格迁移网络修改流程(自用版)

一. AdaAttN-Revisit Attention Mechanism in Arbitrary Neural Style Transfer&#xff08;ICCV2021&#xff09; 下载vgg_normalised.pth打开visdom python -m visdom.server在 train_adaattn.sh 中配置 content_path、style_path 和 image_encoder_path&#xff0c;分别表…

深入理解Zookeeper系列-4.Watcher原理

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理&#x1f525;如果感觉博主的文章还不错的话&#xff…

深入浅出理解kafka

1.Kafka简介 Kafka 本质上是一个 MQ&#xff08;Message Queue&#xff09;&#xff0c;使用消息队列的优点&#xff1a; 解耦&#xff1a;允许独立的扩展或修改队列两边的处理过程。可恢复性&#xff1a;即使一个处理消息的进程挂掉&#xff0c;加入队列中的消息仍然可以在系…

LinuxBasicsForHackers笔记 -- 控制文件和目录权限

对于每个文件和目录&#xff0c;我们可以指定文件所有者、特定用户组以及所有其他用户的权限状态。 不同类型的用户 在Linux中&#xff0c;root用户是拥有一切权力的。 root 用户基本上可以在系统上执行任何操作。 系统上的其他用户具有有限的能力和权限&#xff0c;并且几乎…