无穷大的安全初始化

如果问题中各数据的范围明确,那么无穷大的设定不是问题,在不明确的情况下,很多程序员都取0x7fffffff作为无穷大,因为这是32-bit int的最大值。如果这个无穷大只用于一般的比较(比如求最小值时min变量的初值),那么0x7fffffff确实是一个完美的选择,但是在更多的情况下,0x7fffffff并不是一个好的选择。

很多时候我们并不只是单纯拿无穷大来作比较,而是会运算后再做比较,例如在大部分最短路径算法中都会使用的松弛操作:

                    if (d[u]+w[u][v]<d[v]) d[v]=d[u]+w[u][v]; 

重点内容我们知道如果u,v之间没有边,那么w[u][v]=INF,如果我们的INF取0x7fffffff,那么d[u]+w[u][v]会溢出而变成负数,我们的松弛操作便出错了,更一般的说,0x7fffffff不能满足“无穷大加一个有穷的数依然是无穷大”,它变成了一个很小的负数。


除了要满足加上一个常数依然是无穷大之外,我们的常量还应该满足“无穷大加无穷大依然是无穷大”,至少两个无穷大相加不应该出现灾难性的错误,这一点上0x7fffffff依然不能满足我们。

所以我们需要一个更好的家伙来顶替0x7fffffff,最严谨的办法当然是对无穷大进行特别处理而不是找一个很大很大的常量来代替它(或者说模拟它),但是这样会让我们的编程过程变得很麻烦。在我读过的代码中,最精巧的无穷大常量取值是0x3f3f3f3f,我不知道是谁最先开始使用这个精妙的常量来做无穷大,不过我的确是从一位不认识的ACMer(ID:Staginner)的博客上学到的,他/她的很多代码中都使用了这个常量,于是我自己也尝试了一下,发现非常好用,而当我对这个常量做更深入的分析时,就发现它真的是非常精巧了。

0x3f3f3f3f的十进制是1061109567,也就是10^9级别的(和0x7fffffff一个数量级),而一般场合下的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。
另一方面,由于一般的数据都不会大于10^9,所以当我们把无穷大加上一个数据时,它并不会溢出(这就满足了“无穷大加一个有穷的数依然是无穷大”),事实上0x3f3f3f3f+0x3f3f3f3f=2122219134,这非常大但却没有超过32-bit int的表示范围,所以0x3f3f3f3f还满足了我们“无穷大加无穷大还是无穷大”的需求。
最后,0x3f3f3f3f还能给我们带来一个意想不到的额外好处:如果我们想要将某个数组清零,我们通常会使用memset(a,0,sizeof(a))这样的代码来实现(方便而高效),但是当我们想将某个数组全部赋值为无穷大时(例如解决图论问题时邻接矩阵的初始化),就不能使用memset函数而得自己写循环了(写这些不重要的代码真的很痛苦),我们知道这是因为memset是按字节操作的,它能够对数组清零是因为0的每个字节都是0,现在好了,如果我们将无穷大设为0x3f3f3f3f,那么奇迹就发生了,0x3f3f3f3f的每个字节都是0x3f!所以要把一段内存全部置为无穷大,我们只需要memset(a,0x3f,sizeof(a))。

<think> 嗯,用户想了解深度学习的初始化相关知识,包括方法和作用等。用户之前已经提供了五篇相关的引用文献,我需要整合这些内容,给出系统清晰的解答。 用户提供的资料内容非常丰富:引用[1]提到初始化能避免梯度消失或爆炸问题;引用[2]和[3]列举了零初始化、随机初始化、Xavier和Kaiming等方法;引用[4]提到自适应初始化这种新方法;引用[5]则详细解释了Xavier初始化学原理。 先考虑从基础概念讲起:初始化的核心作用应该是为训练确定合适的起点。引用[3]强调这是模型训练的关键环节,引用[1]也指出这是深度学习的基础技术。 关于具体方法,可以这样组织: 第一层讲传统方法:零初始化效果差(引用[2][3]);随机初始化需要调整方差(引用[1]);Xavier初始化适合sigmoid/tanh(引用[5]的方差一致性原则);Kaiming初始化专为ReLU设计(引用[1][3])。 第二层讲新方法:引用[4]提到的自适应初始化值得单独说明,虽然计算复杂但效果显著。 最后要强调实践要点:引用[3]建议根据激活函选择方法(如ReLU用Kaiming);引用[1]提到初始化影响收敛速度。 用户可能是学习者或研究者,需要既理解原理又掌握实践。考虑在回答中加入学表达式:比如Xavier的$W \sim \mathcal{U}(-\frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}}, \frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}})$和Kaiming的$\sigma = \frac{\sqrt{2}}{\sqrt{n_{in}}}$,但会放在独立公式块里避免干扰阅读。 准备设计相关问题覆盖理论(如梯度消失原理)和实战(如选择初始化方法)。 </think>好的,深度学习中的参初始化是模型训练成功的关键第一步。它决定了模型训练的起点,直接影响梯度传播的稳定性、收敛速度和最终性能。以下是核心知识的系统梳理: **1. 初始化的核心作用** * **打破对称性:** 如果所有权重初始化为相同值(包括零),那么同一层的所有神经元在每次迭代中会计算出相同的梯度并进行相同的更新。这会使网络失去表达能力,无法学习不同的特征。初始化引入的随机性确保了神经元可以学习不同的模式。 * **控制梯度传播:** 不合适的初始化(如过大或过小)极易导致训练过程中出现: * **梯度消失 (Vanishing Gradients):** 梯度在反向传播时逐层急剧减小(趋于零),导致深层网络的权重几乎不更新,学习停滞。 * **梯度爆炸 (Exploding Gradients):** 梯度在反向传播时逐层急剧增大(趋于无穷),导致权重更新过大,模型参剧烈震荡甚至溢出,无法收敛。 * **加速收敛:** 合适的初始化将各层的激活值(输出)和梯度的方差控制在合理的范围内,使得信号在前向传播和梯度在反向传播时能保持相对稳定,避免极端的值问题,从而让优化器(如SGD、Adam)能更有效地工作,加快收敛速度。 * **提供有效学习起点:** 初始化决定了模型训练开始时的“位置”。一个好的起点能让模型更快地接近好的局部最优解或全局最优解。 **2. 常见初始化方法及其原理** * **零初始化 (Zero Initialization):** `W = 0`, `b = 0` * **原理:** 最简单的方式。 * **问题:** 导致对称性问题,所有神经元学习相同的特征,网络能力退化。实践中**几乎不使用**。引用[3]明确指出其局限性和很少使用的现实。 * **随机初始化 (Random Initialization):** * **小随机:** 从均匀分布`U(-ε, ε)`或正态分布`N(0, ε²)`中采样,`ε`是一个很小的(如0.01)。 * **问题:** `ε`的选择至关重要。 * `ε`太小:激活值和梯度可能过小,导致梯度消失(尤其深层网络)。 * `ε`太大:激活值和梯度可能过大,导致梯度爆炸或激活函(如Sigmoid、Tanh)饱和(输出趋近于边界值,梯度接近零)。 * **Xavier / Glorot 初始化:** 专为配合 Sigmoid、Tanh 等饱和激活函设计。 * **目标:** 保持前向传播的激活值方差和反向传播的梯度方差在网络各层之间大致稳定。 * **原理:** 假设激活函是线性的(或在其线性区域内),推导出权重方差应与该层输入神经元`n_in`和输出神经元`n_out`相关。 * **公式:** * **均匀分布:** $W \sim \mathcal{U}\left(-\frac{\sqrt{6}}{\sqrt{n_{in} + n_{out}}}, \frac{\sqrt{6}}{\sqrt{n_{in} + n_{out}}}\right)$ * **正态分布:** $W \sim \mathcal{N}\left(0, \sqrt{\frac{2}{n_{in} + n_{out}}}\right)$ 或 $W \sim \mathcal{N}\left(0, \frac{\sqrt{2}}{\sqrt{n_{in} + n_{out}}}\right)$ * **优点:** 显著缓解使用Sigmoid/Tanh时的梯度消失/爆炸问题。 * **局限:** 对于 ReLU 及其变种等非对称、非零均值的激活函效果不佳(因为ReLU会使一半的激活值为零,破坏了方差假设)。引用[1], [3], [5] 详细阐述了其原理、目标和适用场景。引用[5]尤其强调了其“保持方差一致”的核心思想[^5]。 * **He / Kaiming 初始化:** 专为配合 ReLU 及其变种(Leaky ReLU, PReLU)等激活函设计。 * **目标:** 同样是为了保持各层激活值和梯度的方差稳定,但考虑了ReLU将负值置零的特性(导致输出的均值不为零,方差减半)。 * **原理:** 修正了Xavier的假设,考虑ReLU的影响。 * **公式:** * **正态分布:** $W \sim \mathcal{N}\left(0, \sqrt{\frac{2}{n_{in}}}\right)$ * **均匀分布:** $W \sim \mathcal{U}\left(-\sqrt{\frac{6}{n_{in}}}, \sqrt{\frac{6}{n_{in}}}\right)$ * **优点:** 是目前使用 ReLU 族激活函的深度神经网络(尤其是CNN)的标准初始化方法,能有效解决ReLU网络的梯度问题。引用[1], [2], [3] 都将其作为ReLU网络的标准初始化方法进行了重点介绍[^1][^2][^3]。 * **自适应初始化方法:** * **原理:** 不是使用固定的公式,而是根据模型架构、激活函,甚至使用一小批实际据(或生成据)来动态计算初始权重的分布参(如方差)。目的是更精确地满足特定模型在初始状态下的稳定性要求。 * **优点:** 理论上可以提供更优、更个性化的起点,尤其对于复杂或非标准架构。 * **缺点:** 计算成本增加(需要额外的前向/反向传播),实现更复杂,对用于计算初始化的小批量据敏感。引用[4] 对这种新兴方法及其优缺点进行了概述[^4]。 **3. 初始化的实践要点** * **激活函是关键:** 选择初始化方法最重要的依据是**使用的激活函**。ReLU用Kaiming,Sigmoid/Tanh用Xavier通常是安全的选择。引用[1], [3] 都强调了根据激活函选择初始化方法的重要性[^1][^3]。 * **偏置项初始化:** 通常初始化为零即可。 * **Batch Normalization (BN) 的影响:** BN层能显著减轻网络对初始化的敏感性。BN通过强制每层的输入(激活值)具有零均值和单位方差,极大地缓解了梯度消失/爆炸问题。即使初始化不是最优,BN也能帮助网络更快地收敛。但良好的初始化与BN结合通常效果更佳。 * **层类型:** 卷积层和全连接层通常使用上述方法初始化。循环神经网络(RNN)有专门的初始化策略(如正交初始化)来缓解其特有的梯度问题。 * **框架支持:** 现代深度学习框架(如PyTorch, TensorFlow)通常为不同层和激活函提供了合理的默认初始化(如`linear`层默认常用Kaiming均匀,`conv`层默认常用Kaiming均匀)。了解原理有助于在需要时覆盖默认设置。 **4. 总结** 深度学习中的参初始化远非简单的随机赋值。它通过精心设计的随机分布(如Xavier, Kaiming),旨在为神经网络训练提供一个稳定、非对称的起点,有效避免梯度消失/爆炸问题,加速收敛,并最终影响模型性能。理解不同初始化方法的原理和适用场景(尤其是与激活函的匹配关系)是构建和训练成功深度学习模型的重要基础。在实践中,Kaiming初始化(ReLU族)和Xavier初始化(Sigmoid/Tanh)是广泛应用且效果良好的标准方法,而自适应初始化代表了更精细化调整的方向[^1][^2][^3][^4][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值