初始化神经网络权重的方法总结 神经网络如果权重全部初始化为0会存在什么问题
ztj100 2024-12-18 18:19 38 浏览 0 评论
在本文中,评估了权值初始化的许多方法和当前的最佳实践
零初始化
将权值初始化为零是不行的。那我为什么在这里提到它呢?要理解权值初始化的需要,我们需要理解为什么将权值初始化为零是无效的。
让我们考虑一个类似于上面所示的简单网络。每个输入只是一个标量X?,X?X?。和每个神经元的权重是W?和W?。每次权重更新如下:
Out? = X?W? + X?W? + X?W?
Out? = X?W? + X?W? + X?*W?
正如你所看到的现在,如果权重矩阵W = [W?W?]被初始化为零,然后out1和out2都完全一样。
即使我们对两者都添加一个非零的随机偏差项,权值也会更新为非零,但它们仍将保持相同,因此隐藏单元的两个神经元都在计算相同的东西。换句话说,它们是对称的。
这是非常不可取的,因为这是浪费计算。这就是零初始化无法工作的原因。
随机初始化
现在我们知道权重必须是不同的,下一个想法是随机初始化这些权重。随机初始化比零初始化好得多,但是这些随机数可以是任意数吗?
假设你使用的是s型非线性。sigmoid函数如下所示。
我们可以看到,对于大到6的值,sigmoid的值几乎是1,对于小到-6的值,sigmoid的值为0。这意味着如果我们的权值矩阵被初始化为过大或过小的值,所有有用的信息都会在sigmoid函数中丢失。
如果我们使用ReLu非线性,这就不那么重要了,但是在将权重初始化为大值或小值时还有其他问题。有更好的方法来初始化权重。
Xavier初始化
Xavier初始化是由Xavier Glorot和Yoshua Bengio在2010年提出的。本文的主要目标是初始化权重,使激活的平均值为零,标准偏差为1。考虑如下所示计算的函数。
Z = WX + b
这里W是权值矩阵,X是来自前一层的输入,b是偏差。Z是一个层计算的输出,也称为激活。我们希望Z的均值是0,标准差是1。(从技术上讲,Z是ReLu等非线性激活后的结果)
为什么均值为0,标准差为1这么重要?
考虑一个有100层的深度神经网络。在每一步,权重矩阵乘以来自前一层的激活。如果每一层的激活大于1,当它们被重复乘以100次时,它们就会不断变大,爆炸到无穷大。类似地,如果激活值小于1,它们将消失为零。这叫做渐变爆炸和渐变消失问题。 我们可以从下图中看到这一点。甚至比1稍大一点的值也会爆炸成非常大的数字,而比1稍小一点的值也会消失为零。
为了避免梯度和激活的爆炸和消失,我们希望激活的平均值为0,标准偏差为1。我们可以通过仔细选择权重来实现这一点。
在本文发布期间,权值的最佳实践是从均匀分布[-1,1]中随机选取,然后除以输入维数的平方根。事实证明,这不是一个好主意,梯度消失了,如果可能的话,训练也非常缓慢。
这个问题通过Xavier的初始化得到了解决,Xavier的初始化建议我们从一个均匀分布中随机初始化权重,如下图所示。
Xavier 初始化的 Uniform分布
现在,Xavier的初始化是通过从标准正态分布中选择权重来完成的,每个元素都要除以输入维度大小的平方根。在PyTorch中,代码如下所示。
torch.randn(n_inp, n_out)*math.sqrt(1/n_inp)
Xavier的初始化工作相当好,对于对称非线性,如sigmoid和Tanh。然而,对于目前最常用的非线性函数ReLu,它的工作效果并不理想。
Kaiming 初始化
2015年,何凯明等人撰写了一篇名为《Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》的论文,在论文中,他们介绍了现在广为人知的Kaiming 初始化。
但是为什么我们需要Kaiming 初始话呢?关于ReLu非线性的Xavier Init有什么问题?
从上图中可以看出,ReLu对所有X<0给出了0,对所有X>给出了Y=X。ReLu并没有很好地定义0,但大多数程序都将其赋值为接近于0的近似,比如machine epsilon。
左:均值0,标准差1的正态分布。右:通过ReLu后的正态分布。
在上面我们可以看到2个散点图,左边是ReLu之前的数据,右边是ReLu之后的数据。从图像中可以清楚地看到,在ReLu之后,方差几乎是一半,平均值略高。这改变了激活,方差减少了一半,所以我们需要将方差加倍才能得到Xavier Init的原始效果。因此,我们将权重乘以一个额外的值√2。所以在PyTorch中,Kaiming 初始化如下所示。
torch.randn(n_inp, n_out)*math.sqrt(2/n_inp)
如果你仍然对上面的公式不太理解,那么记住:
方差=标准差的平方
方差翻倍所以需要乘以√2
Fixup初始化
Fixup是Zhang等人在2019年提出的初始化。根据他们的观察,Kaiming 的初始化和其他标准的初始化不能很好地用于有残差分支的网络(又叫残差网络)。他们发现,标准初始化的残差网络只有在BatchNorm下才能正常工作。
让我们看看为什么Kaiming Init不能在残差网络上更好的工作。考虑如下图所示的跳过连接。X2 = f(X1) X3 = f(X2) + X1。我们知道Kaiming init选择的权重使得每一层后的激活有0均值和1方差。我们知道X1的方差是1 X2的方差是1。但是Kaiming init不考虑跳过连接。因此,根据总方差定律,X3的方差翻倍。由残差分支添加的额外方差在Kaiming Init中没有考虑在内。因此残差网络不能很好地与标准初始化一起工作,除非它们有BatchNorm。没有BatchNorm,输出方差会随深度呈指数爆炸式增长。
Var[X???] ≈ 2Var[X? ]
残差网络中的跳过连接
该论文的作者提出了一个重要的观察结果,即SGD更新每个残差分支的权重会在高度相关的方向上更新网络输出。 这意味着,如果所有残差分支权重都由X更新,则网络输出也将在相同的权重更新方向上按比例地更改为X。
作者将所需的网络输出变化定义为Θ(η)。 如我们所知,平均每个残差分支对输出更新的贡献均等。如果我们称残差分支的数量为L,则每个残差分支平均应将输出改变Θ(η/ L),以实现总变化。 输出上的Θ(η)。
接下来,作者展示如何初始化m层的残差分支,以便SGD更新将输出更改Θ(η/ L)。 作者表明,可以通过以下方式重新调整这些权重层的标准初始化:
权重比例因子
作者还讨论了偏差和乘数的效用。 他们发现在每次卷积,添加一个初始值为0的偏置层,线性层和逐元素激活导致训练显着改善之前。 他们还发现,在每个残差分支上添加一个乘法标度有助于通过标准化来模仿网络的权重范数动态。
所以所有的而解决方案汇总如下
LSUV初始化
Mishkin等人在2016年的一篇论文《All you need is a good Init》中介绍了LSUV。LSUV Init是一种数据驱动的方法,它具有最小的计算量和非常低的计算开销。初始化是一个2部分的过程,首先初始化标准正交矩阵的权值(与高斯噪声相反,它只是近似正交)。下一部分是迭代一个小批处理并缩放权重,以便激活的方差为1。作者断言,在大范围内,小批量大小对方差的影响可以忽略不计。
在论文中,作者列出了以下初始化步骤。
1. 使用单位方差将权重初始化为高斯噪声。
1. 使用SVD或QR将它们分解为正交坐标。
1. 使用第一个微型批处理在网络中进行迭代,并在每次迭代比例时权重以使输出方差接近1。重复直到输出方差为1或发生最大迭代。
论文中,作者提出比例因子为√Var(BL),其中BL —它的输出Blob
作者还提出了最大迭代次数的值,以防止无限循环。但是,在他们的实验中,他们发现在1–5次迭代中实现了单位方差。
可以将LSUV Init看作是正交初始化和BatchNorm的组合,它仅在第一个迷你批处理中执行。 作者在实验中表明,与完整的BatchNorm相比,该方法在计算上非常高效。
转移学习
转移学习是一种在我们的新模型中使用已经训练有素的模型进行权重的方法,该模型已经针对相似的任务进行了训练。 这些权重已经学习了很多有用的信息,我们可以针对我们的特定目标进行微调! 我们有一个了不起的模型,没有初始化的麻烦。
每次使用来自另一个模型的预训练权重都是最好的方法。唯一需要我们自己初始化权值的情况是,我们在一个从未有人训练过的网络上工作。在大多数实际情况下,情况并非如此,所以一般情况下,我们使用一个与训练的模型作为我们训练的开始是一个很好的习惯。
作者 Akash Shastri
deephub翻译组
相关推荐
- sharding-jdbc实现`分库分表`与`读写分离`
-
一、前言本文将基于以下环境整合...
- 三分钟了解mysql中主键、外键、非空、唯一、默认约束是什么
-
在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。...
- MySQL8行级锁_mysql如何加行级锁
-
MySQL8行级锁版本:8.0.34基本概念...
- mysql使用小技巧_mysql使用入门
-
1、MySQL中有许多很实用的函数,好好利用它们可以省去很多时间:group_concat()将取到的值用逗号连接,可以这么用:selectgroup_concat(distinctid)fr...
- MySQL/MariaDB中如何支持全部的Unicode?
-
永远不要在MySQL中使用utf8,并且始终使用utf8mb4。utf8mb4介绍MySQL/MariaDB中,utf8字符集并不是对Unicode的真正实现,即不是真正的UTF-8编码,因...
- 聊聊 MySQL Server 可执行注释,你懂了吗?
-
前言MySQLServer当前支持如下3种注释风格:...
- MySQL系列-源码编译安装(v5.7.34)
-
一、系统环境要求...
- MySQL的锁就锁住我啦!与腾讯大佬的技术交谈,是我小看它了
-
对酒当歌,人生几何!朝朝暮暮,唯有己脱。苦苦寻觅找工作之间,殊不知今日之事乃我心之痛,难道是我不配拥有工作嘛。自面试后他所谓的等待都过去一段时日,可惜在下京东上的小金库都要见低啦。每每想到不由心中一...
- MySQL字符问题_mysql中字符串的位置
-
中文写入乱码问题:我输入的中文编码是urf8的,建的库是urf8的,但是插入mysql总是乱码,一堆"???????????????????????"我用的是ibatis,终于找到原因了,我是这么解决...
- 深圳尚学堂:mysql基本sql语句大全(三)
-
数据开发-经典1.按姓氏笔画排序:Select*FromTableNameOrderByCustomerNameCollateChinese_PRC_Stroke_ci_as//从少...
- MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?
-
大家好,是不是很多人都对MySQL加行级锁的规则搞的迷迷糊糊,一会是next-key锁,一会是间隙锁,一会又是记录锁。坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如何用命令分析加...
- 一文讲清怎么利用Python Django实现Excel数据表的导入导出功能
-
摘要:Python作为一门简单易学且功能强大的编程语言,广受程序员、数据分析师和AI工程师的青睐。本文系统讲解了如何使用Python的Django框架结合openpyxl库实现Excel...
- 用DataX实现两个MySQL实例间的数据同步
-
DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的...
- MySQL数据库知识_mysql数据库基础知识
-
MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...
- 如何为MySQL中的JSON字段设置索引
-
背景MySQL在2015年中发布的5.7.8版本中首次引入了JSON数据类型。自此,它成了一种逃离严格列定义的方式,可以存储各种形状和大小的JSON文档,例如审计日志、配置信息、第三方数据包、用户自定...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)