在加载模型后在加载cuda()之前应用torch.manual_seed时,结果是不同的

问题描述 投票:2回答:1

我试图确保我的代码可重复(总是得到相同的结果)

所以我在代码之前应用了以下设置。

os.environ['PYTHONHASHSEED'] = str(args.seed)
random.seed(args.seed)
np.random.seed(args.seed)
torch.manual_seed(args.seed)
torch.cuda.manual_seed(args.seed)
torch.cuda.manual_seed_all(args.seed) # if you are using multi-GPU.
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True

使用这些设置,我始终在相同的环境和GPU下获得相同的结果。

但是,当我在加载模型后应用torch.manual_seed()时。

torch.manual_seed(args.seed)
model = Net()
Net.cuda()
torch.manual_seed(args.seed)
model = Net()
torch.manual_seed(args.seed)
Net.cuda()

以上两个结果不同。我应该如何理解这种情况?

加载模型后种子会重新初始化吗?

python pytorch
1个回答
0
投票

Net.cuda()对随机数生成器没有影响。在后台,它只为所有模型参数调用cuda()。因此,基本上是对Tensor.cuda()的多次调用。

https://github.com/pytorch/pytorch/blob/ecd3c252b4da3056797f8a505c9ebe8d68db55c4/torch/nn/modules/module.py#L293

我们可以通过以下操作对此进行测试:

torch.random.manual_seed(42)
x = torch.rand(1)
x.cuda()
y = torch.rand(1)
y.cuda()
print(x, y)

# the above prints the same as below
torch.random.manual_seed(42)
print(torch.rand(1), torch.rand(1))

因此,这意味着Net()正在使用数字生成器初始化层内的随机权重。

torch.manual_seed(args.seed)
model = Net()
print(torch.rand(1))

# the below will print a different result
torch.manual_seed(args.seed)
model = Net()
torch.manual_seed(args.seed)
print(torch.rand(1))

我建议缩小Python源代码中如何管理随机数的范围。因此,模型外部的global代码块与internal值的生成方式无关。

简单地说,将seed作为参数传递给模型的__init__

model = Net(args.seed)
print(torch.rand(1))

这将迫使开发人员在使用模型时始终提供种子以保持一致性,如果不一定总是需要种子,则可以将参数设为可选。

我会一直避免使用相同的种子,因为您将学习使用最适合该种子的参数。

© www.soinside.com 2019 - 2024. All rights reserved.