【随机种子初始化】一个神经网络模型初始化的大坑

这篇具有很好参考价值的文章主要介绍了【随机种子初始化】一个神经网络模型初始化的大坑。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 问题起因和经过

半年前写了一个模型,取得了不错的效果(简称项目文件1),于是整理了一番代码,保存为了一个新的项目(简称项目文件2)。半年后的今天,我重新训练这个整理过的模型,即项目文件2,没有修改任何的超参数,并且保持完全一致的随机种子,但是始终无法完全复现出半年前项目文件1跑出来的结果(按道理来说,随机种子控制好后,整个训练过程都应该能够复现,第一个epoch的accuracy就应该对上)。我找到项目文件1,跑了跑,能复现之前的训练结果。并且,分别训练项目文件1和2的模型,都能重复自己的训练结果,而两个项目文件的结果无法对上。
花了半天的时间反复仔细检查数据集和训练超参数的设置后,也没能看出项目文件2有什么毛病。非常奇怪,为什么同样的模型、配置、服务器、随机种子,在不同的项目文件中出现不同的结果?!实在想不通。
于是,决定动手debug看看问题出在了哪里。
我发现第一个epoch的结果就对不上,所以我猜测问题出在了模型的初始化上,那初始化与什么相关呢?很自然地,我把问题聚焦在了随机种子上,是不是没有有效固定住随机性?所以我将两个项目文件构建model后的参数打印出来看了看,发现,完全不同!

【随机种子初始化】一个神经网络模型初始化的大坑
【随机种子初始化】一个神经网络模型初始化的大坑

项目文件1中的部分打印结果:
【随机种子初始化】一个神经网络模型初始化的大坑

项目文件2中的部分打印结果:
【随机种子初始化】一个神经网络模型初始化的大坑

很明显地说明了一件事:同样的随机种子,在这两个项目文件中,产生了完全不一样的初始化值! 这个结果是违背我的常识的,为什么会出现这样的情况?
于是,我 猜测是不是因为两个项目在同一服务器上发生了未知的冲突,所以我copy了一份项目文件1为项目文件3,然后跑项目文件3的初始化结果,发现和项目文件1的初始化结果一致,居然没问题!?那这个项目文件2怎么回事,凭空出现了不同的初始化值?
排除了项目冲突这个猜想后,我把视野放在了模型本身上。我试着print(model)进行观察,发现项目文件2相比项目文件1的模型架构多了一些参数,这些参数是我当初在整理代码并补充新算法时补充定义的(比如:self.gamma = Parameter(torch.randn((1, self.num_heads, 1, 1)))),但是后面并没有真正用上这个参数。
于是,我又有了一个新的猜想:是不是因为多出来的这些新定义的参数,导致在同一随机种子的设置下,仍然出现不一致的初始化行为?
顺着这个思路,我给项目文件1做了如下简单的尝试:直接给模型架构多定义一个模块,但无需使用它,看看初始化是否受影响。 这里我简单加了个nn.Linear()进去。
代码解释如下,原本的架构为:

class Attention(Module):
    """
    Obtained from timm: github.com:rwightman/pytorch-image-models
    """

    def __init__(self, dim, num_heads=8, attention_dropout=0.1, projection_dropout=0.1):
        super().__init__()
        self.num_heads = num_heads
        head_dim = dim // self.num_heads
        self.scale = head_dim ** -0.5

        self.qkv = Linear(dim, dim * 3, bias=False)
        self.attn_drop = Dropout(attention_dropout)
        self.proj = Linear(dim, dim)
        self.proj_drop = Dropout(projection_dropout)
 
        self.relu = ReLU()
        self.eps = 1e-8
        self.alpha = Parameter(torch.ones(1, self.num_heads, 1, 1), requires_grad=False)
        self.alpha.data.fill_(1.0)

    def forward(self, x):
        B, N, C = x.shape
        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]
        ...

我在init函数中多定义一行线性层后为:

class Attention(Module):
    """
    Obtained from timm: github.com:rwightman/pytorch-image-models
    """

    def __init__(self, dim, num_heads=8, attention_dropout=0.1, projection_dropout=0.1):
        super().__init__()
        self.num_heads = num_heads
        head_dim = dim // self.num_heads
        self.scale = head_dim ** -0.5

        self.qkv = Linear(dim, dim * 3, bias=False)
        self.attn_drop = Dropout(attention_dropout)
        self.proj = Linear(dim, dim)
        self.proj_drop = Dropout(projection_dropout)
 
        self.relu = ReLU()
        self.eps = 1e-8
        self.alpha = Parameter(torch.ones(1, self.num_heads, 1, 1), requires_grad=False)
        self.alpha.data.fill_(1.0)
        
        self.linear = Linear(dim, dim)  # 这里是新加的模块,但是无需使用

    def forward(self, x):
        B, N, C = x.shape
        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]
        ...

于是,打印初始化参数得到:
【随机种子初始化】一个神经网络模型初始化的大坑

初始化的结果仍然改变了!!! 看来果然是模型架构的不一致性导致了随机种子“失效”。

2 总结上述问题

两个项目文件,看似模型、超参数、数据集、随机种子、服务器完全一致时,发现训练时两者无法保持完全一致,并且进一步发现两个项目文件在初始化模型参数时就不一致了。
而单独地重复训练每一个项目文件,都能重复自身的结果。
直观感觉就是随机种子并没有有效地作用到另一个项目上,是一个很奇怪的问题,有点违背常识。

3 总结解决方案

训练过程不一致是表象,实际上是模型初始化就不一致了。
如果想要用随机种子控制模型初始化参数完全一致,就必须保证模型的架构完全一致! 但凡在model类的init函数里多定义一个无用参数比如Linear,都会改变整个初始化结果,从而影响后面的训练进程(应该是很微小的影响,但是对于我们复现项目时扣细节来说,会放大这个影响)。

4 可能的解释

咨询了一些遇到过这个问题的同学,大概有如下的可能的解释:在模型的定义中加入了新的模块后,不管是否真正使用,都会影响初始化(已控制了随机种子)。因为加入了新的模块后,整个初始化的顺序会发生改变,于是就乱套了。随机种子只能保证你调用后生成的随机数列是一样的,而在构建模型时的调用顺序,是会随着模型架构的改变而改变的。文章来源地址https://www.toymoban.com/news/detail-489769.html

到了这里,关于【随机种子初始化】一个神经网络模型初始化的大坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 神经网络基础-神经网络补充概念-40-神经网络权重的初始化

    神经网络权重的初始化是深度学习中的重要步骤,良好的权重初始化可以加速模型的训练收敛,提高模型的性能和稳定性。以下是一些常用的权重初始化方法: 零初始化(Zero Initialization):将权重初始化为零。然而,这种方法不太适合深层神经网络,因为它会导致所有神经

    2024年02月12日
    浏览(45)
  • 【机器学习300问】78、都有哪些神经网络的初始化参数方法?

            在训练神经网络时,权重初始化是确保良好收敛的关键步骤之一。不合适的初始化方法可能会导致梯度消失或爆炸,特别是在深层网络中。那么都有哪些神经网络的初始化参数方法呢?选择它这些方法的原则是什么?         关于随机初始化神经网络参数的方法

    2024年04月23日
    浏览(39)
  • MATLAB初始化种群-随机和一定的实数序列

    在智能算法的编码场景中,很多时候是需要用求和为一定的编码的, 比如分配问题, 配送问题等, 下面给出具体程序代码: clc;close all;clear all;warning off;%清除变量 rand(\\\'seed\\\', 100); randn(\\\'seed\\\', 100); format long g; N=5; % 设定优化问题维数 lb=0*ones(1,N);% 自变量上限 ub=1*ones(1,N);% 自变量下限

    2024年01月23日
    浏览(42)
  • MATLAB初始化智能算法编码-产生随机不重复整数序列矩阵

    产生随机不重复整数序列矩阵是智能算法最常用的操作之一,以下给出具体方法: clc;close all;clear all;warning off;%清除变量 rand(\\\'seed\\\', 100); randn(\\\'seed\\\', 100); format long g; N=10; % 设定优化问题维数 lb=0*ones(1,N);% 自变量上限 ub=1*ones(1,N);% 自变量下限 popsize=10;% 种群数 Chrom=mygenfun(popsize,N,lb,u

    2024年01月24日
    浏览(36)
  • react学习(一)之初始化一个react项目

    React 是一个用于构建用户界面(UI)的 JavaScript 库,用户界面由按钮、文本和图像等小单元内容构建而成。React 帮助你把它们组合成可重用、可嵌套的 组件 。从 web 端网站到移动端应用,屏幕上的所有内容都可以被分解成组件,即,可由react构建。 A JAVASCRIPT LIBRARY FOR BUILDING

    2024年04月26日
    浏览(33)
  • 初始化一个Gin框架的Go-Web项目

    使用到的第三方库 gin Gin 框架 viper 配置文件管理 cors 跨域资源请求配置 gorm ORM 库 zap 日志记录 Go 语言程序的入口点 main.go 文件 使用 flag 读取配置文件路径参数,默认当前目录下 使用 viper 读取 config.ini 配置文件初始化初始数据 初始化随机数种子 初始化数据库 声明启动程序

    2024年02月09日
    浏览(47)
  • 武林新秀(一)`git init` 初始化一个新的Git仓库

    git init 是 Git 版本控制系统中用于初始化一个新的 Git 仓库或重新初始化一个现有的仓库的命令。“init” 是 “initialize”(初始化)的缩写。执行此命令后,会创建一个名为 .git 的子目录,其中包含所有的仓库元数据,这使得目录成为一个 Git 仓库。 基本语法: --bare : 创建一

    2024年02月10日
    浏览(51)
  • 分享用 vector的vector实现一个二维数组并初始化的逆置矩阵问题

    目录 题目名称 867.转置矩阵 1.题目 2.题目分析 3.题目知识点 3.1vector的构造函数 3.2vector构造二维数组 最后💐 推荐阅读顺序: 1.题目-2.题目分析-3.题目知识点 如果矩阵 matrix为 m 行 n列,则转置后的矩阵 matrixT为 n行 m列,且对任意 0≤im和 0≤jn,都有 matrixT[j][i]=matrix[i][j] 创建一个

    2024年01月17日
    浏览(50)
  • 用React给XXL-JOB开发一个新皮肤(一):环境搭建和项目初始化

    一. 简述 二. Fork 项目 三. 搭建开发环境 四. 初始化皮肤项目 五. 添加相关依赖 六. 预览 大名鼎鼎的 xxl-job 任务调度中心我们应该都使用过,项目地址:xxl-job。它是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。 该项目中的页面是使用

    2024年02月01日
    浏览(28)
  • 用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

    一. 简述 二. 目录规划 三. Vite 配置 3.1. 配置路径别名 3.2. 配置 less 四. 页面 4.1. 入口文件 4.2. 骨架文件 4.3. 普通页面 五. 路由配置 六. 预览启动 上一篇文章我们介绍了项目初始化,此篇文章我们会先介绍下当前项目的目录规划,接着对 vite 配置以便我们后续的开发,最后会根

    2024年01月20日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包