You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch结果复现异常:单次运行Block1后多次运行Block2结果不一致

问题分析与解决方案

我帮你排查下这个复现性的问题——看起来你已经做了不少种子设置的工作,但单独运行Block2时结果还是不稳定,主要有这几个核心原因:

问题根源

你只在Block1里初始化了一次随机种子,但当你单独运行Block2时,之前的随机状态(包括PyTorch、NumPy、Python原生random模块的状态)已经被之前的运行打乱了。另外,GPU环境下的cuDNN库默认会使用一些非确定性算法,这也会悄悄导致结果波动。

具体修复步骤

你需要在每次运行Block2时都重新重置所有随机源,并启用cuDNN的确定性模式,具体修改如下:

1. 在Block2开头添加种子重置与确定性设置

把这段代码加到Block2的最开头,确保每次运行都从相同的随机状态起步:

# 重置所有随机种子
torch.manual_seed(123)
random.seed(123)
np.random.seed(123)
if cuda:
    torch.cuda.manual_seed(123)
    torch.cuda.manual_seed_all(123)  # 单GPU场景也加上,多GPU时必须设置

# 启用cuDNN确定性模式,避免非确定性算法干扰
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

2. 明确设置模型为训练模式

虽然PyTorch模型默认是train()模式,但如果之前有过测试操作(比如调用过eval()),可能会导致Dropout失效。在初始化模型后明确加上这句更稳妥:

net = Net()
if cuda:
    net.cuda()
net.train()  # 确保Dropout处于训练时的随机失活状态

修改后的完整Block2代码

# 重置随机种子与确定性设置
torch.manual_seed(123)
random.seed(123)
np.random.seed(123)
if cuda:
    torch.cuda.manual_seed(123)
    torch.cuda.manual_seed_all(123)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False

net=Net()
if cuda:
    net.cuda()
net.train()  # 明确设置训练模式

# create a stochastic gradient descent optimizer
optimizer = optim.Adam(net.parameters())
# create a loss function (mse)
loss = nn.MSELoss(size_average=False)
# run the main training loop
epochs =20
hold_loss=[]
for epoch in range(epochs):
    cum_loss=0.
    cum_records_epoch =0
    for batch_idx, (data, target) in enumerate(data_loader_trn):
        tr_x, tr_y = data.float(), target.float()
        if cuda:
            tr_x, tr_y = tr_x.cuda(), tr_y.cuda()
        # Reset gradient
        optimizer.zero_grad()
        # Forward pass
        fx = net(tr_x)
        output = loss(fx, tr_y) #loss for this batch
        cum_loss += output.item() #accumulate the loss
        # Backward
        output.backward()
        # Update parameters based on backprop
        optimizer.step()
        cum_records_epoch +=len(tr_x)
        if batch_idx % 1 == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
                epoch, cum_records_epoch, len(data_loader_trn.dataset),
                100. * (batch_idx+1) / len(data_loader_trn), output.item()))
    print('Epoch average loss: {:.6f}'.format(cum_loss/cum_records_epoch))
    hold_loss.append(cum_loss/cum_records_epoch)
#training loss
plt.plot(np.array(hold_loss))
plt.show()

为什么这样能解决问题?

  • 重置种子:每次运行Block2时,把所有随机源的状态都拉回初始值,确保Dropout的随机失活、Adam优化器的初始化等都用相同的随机序列。
  • cuDNN确定性模式:禁用cuDNN的自动算法选择(benchmark模式),强制使用确定性算法,避免GPU上的非确定性计算导致结果差异。

内容的提问来源于stack exchange,提问作者B_Miner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:35:31