官网说明:
Reproducibility — PyTorch 1.8.0 documentation
参考博客:
pytorch 固定随机数种子踩过的坑_yqf3838751的博客-CSDN博客
代码设置:
1. 训练文件:
把以下代码放在主文件的最开始部分。
#cuDnn中往往会并行跑多个算法来选择效果最好的那个,这里就可能引入噪声。因此,如果为了保证可复现性,可以将这个特性禁用,缺点就是会损失一定的性能。如果为了达到最优的效果,可以将开关打开:
def set_seed(seed):
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed) # if you are using multi-GPU.
np.random.seed(seed) # Numpy module.
random.seed(seed) # Python random module.
os.environ['PYTHONHASHSEED'] = str(seed)
torch.use_deterministic_algorithms(True)
torch.backends.cudnn.enabled = False
torch.backends.cudnn.benchmark = False #禁用benchmark,保证可复现
#torch.backends.cudnn.benchmark = True #恢复benchmark,提升效果
torch.backends.cudnn.deterministic = True
os.environ['CUBLAS_WORKSPACE_CONFIG'] = ':4096:8'
setup_seed(2021)
2. 数据加载器设置:
train_dataset = ImageList(opt.training_list,transform)
def seed_worker(worker_id):
worker_seed = torch.initial_seed() % 2**32
numpy.random.seed(worker_seed)
random.seed(worker_seed)
DataLoader(
train_dataset,
batch_size=batch_size,
num_workers=num_workers,
worker_init_fn=seed_worker
)
其他问题:
1.关于nn.SLTM的问题
实验中发现,如果设置了nn.LSTM的dropout参数,是无法通过随机种子的固定来复现实验结果的。这似乎是一个cuDNN的bug,在此记录一下。
相关讨论见nn.LSTM gives nondeterministic results with dropout and multiple layers。
示例如下:
lstm = nn.LSTM(input_size = 256,
hidden_size = 128,
num_layers = 1,
batch_first = True,
dropout = 0.5 )
2.关于nn.Embedding()的问题
在数据预处理阶段使用了随机初始化的nn.Embedding(),并将其通过持久化方式pickle保存了下来。
再次使用它时,通过pickle.load()读取,即使固定了随机数种子,此时读取到的nn.Embedding()中的weight与当初保存下来的weight是不同的。
暂不清楚原因。
3.numpy随机数与Dataloader多进程共用的问题
来源:PyTorch + NumPy这么做会降低模型准确率,这是bug还是预期功能?
描述:在 PyTorch 同时使用 NumPy 的随机数生成器和多进程数据加载会导致相同的扩充数据,只有专门设置 seed 才可以解决这个 bug,否则会降低模型的准确率。
个人评价:可能这就是上面个的数据加载器设置中需要有相关设置的原因。