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

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

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日
    浏览(49)
  • 【机器学习300问】78、都有哪些神经网络的初始化参数方法?

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

    2024年04月23日
    浏览(45)
  • 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日
    浏览(50)
  • 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日
    浏览(42)
  • react学习(一)之初始化一个react项目

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

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

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

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

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

    2024年02月10日
    浏览(57)
  • 分享用 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日
    浏览(58)
  • 用React给XXL-JOB开发一个新皮肤(二):目录规划和路由初始化

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

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

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

    2024年02月01日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包