解决随机数引发的可复现问题
seed_everything
在import之后,代码之前,用下面的代码固定随机数种子。这个方法可以解决几乎所有不可复现的问题。
def seed_everything(seed):
torch.manual_seed(seed) # Current CPU
torch.cuda.manual_seed(seed) # Current GPU
np.random.seed(seed) # Numpy module
random.seed(seed) # Python random module
torch.backends.cudnn.benchmark = False # Close optimization
torch.backends.cudnn.deterministic = True # Close optimization
torch.cuda.manual_seed_all(seed) # All GPU (Optional)
dataloader
最简单有效的方法就是在每次 DataLoader 的 in 操作调用之前都固定一下随机数种子。
def stable(dataloader, seed):
seed_everything(seed)
return dataloader
for inputs, labels in stable(DataLoader(...), seed):
pass
**这里需要格外注意的是,stable 函数会使训练时每个 epoch 内部的 shuffle 规律相同!**之前我们提到 shuffle 训练集可以减轻模型过拟合,是至关重要的,当每个 epoch 内部第 i 个 batch 的内容都对应相同时,模型会训不起来。所以,一个简单的技巧,在传入随机数种子的时候加上一个 epoch 序号。
for epoch in range(MAX_EPOCH): # training
for inputs, labels in stable(DataLoader(...), seed + epoch):
pass