PyTorch 如何設置隨機數種子使結果可復現
由於在模型訓練的過程中存在大量的隨機操作,使得對於同一份代碼,重復運行後得到的結果不一致。
因此,為瞭得到可重復的實驗結果,我們需要對隨機數生成器設置一個固定的種子。
CUDNN
cudnn中對卷積操作進行瞭優化,犧牲瞭精度來換取計算效率。如果需要保證可重復性,可以使用如下設置:
from torch.backends import cudnn cudnn.benchmark = False # if benchmark=True, deterministic will be False cudnn.deterministic = True
不過實際上這個設置對精度影響不大,僅僅是小數點後幾位的差別。所以如果不是對精度要求極高,其實不太建議修改,因為會使計算效率降低。
Pytorch
torch.manual_seed(seed) # 為CPU設置隨機種子 torch.cuda.manual_seed(seed) # 為當前GPU設置隨機種子 torch.cuda.manual_seed_all(seed) # 為所有GPU設置隨機種子
Python & Numpy
如果讀取數據的過程采用瞭隨機預處理(如RandomCrop、RandomHorizontalFlip等),那麼對python、numpy的隨機數生成器也需要設置種子。
import random import numpy as np random.seed(seed) np.random.seed(seed)
Dataloader
如果dataloader采用瞭多線程(num_workers > 1), 那麼由於讀取數據的順序不同,最終運行結果也會有差異。
也就是說,改變num_workers參數,也會對實驗結果產生影響。
目前暫時沒有發現解決這個問題的方法,但是隻要固定num_workers數目(線程數)不變,基本上也能夠重復實驗結果。
補充:pytorch 固定隨機數種子踩過的坑
1.初步固定
def setup_seed(seed): torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.cuda.manual_seed(seed) np.random.seed(seed) random.seed(seed) torch.backends.cudnn.deterministic = True torch.backends.cudnn.enabled = False torch.backends.cudnn.benchmark = False #torch.backends.cudnn.benchmark = True #for accelerating the running setup_seed(2019)
2.繼續添加如下代碼:
tensor_dataset = ImageList(opt.training_list,transform) def _init_fn(worker_id): random.seed(10 + worker_id) np.random.seed(10 + worker_id) torch.manual_seed(10 + worker_id) torch.cuda.manual_seed(10 + worker_id) torch.cuda.manual_seed_all(10 + worker_id) dataloader = DataLoader(tensor_dataset, batch_size=opt.batchSize, shuffle=True, num_workers=opt.workers, worker_init_fn=_init_fn)
3.在上面的操作之後發現加載的數據多次試驗大部分一致瞭
但是仍然有些數據是不一致的,後來發現是pytorch版本的問題,將原先的0.3.1版本升級到1.1.0版本,問題解決
4.按照上面的操作後雖然解決瞭問題
但是由於將cudnn.benchmark設置為False,運行速度降低到原來的1/3,所以繼續探索,最終解決方案是把第1步變為如下,同時將該部分代碼盡可能放在主程序最開始的部分,例如:
import torch import torch.nn as nn from torch.nn import init import pdb import torch.nn.parallel import torch.nn.functional as F import torch.backends.cudnn as cudnn import torch.optim as optim import torch.utils.data from torch.utils.data import DataLoader, Dataset import sys gpu_id = "3,2" os.environ["CUDA_VISIBLE_DEVICES"] = gpu_id print('GPU: ',gpu_id) def setup_seed(seed): torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) torch.cuda.manual_seed(seed) np.random.seed(seed) random.seed(seed) cudnn.deterministic = True #cudnn.benchmark = False #cudnn.enabled = False setup_seed(2019)
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- pytorch DataLoader的num_workers參數與設置大小詳解
- 詳解win10下pytorch-gpu安裝以及CUDA詳細安裝過程
- python深度學習標準庫使用argparse調參
- Pytorch數據讀取之Dataset和DataLoader知識總結
- pytorch鎖死在dataloader(訓練時卡死)