一、為什麼要固定隨機種子
在深度學習中,模型的性能經常收到隨機性的影響,如初始化、Dropout, BN等。這些隨機性導致相同的訓練過程,在不同的運行中可能會得到不同的結果或者訓練過程會發生不同的情況。這對於實驗的可重複性和比較來說是不可取的。為此,我們需要建立一般的方法來固定或控制這些隨機化元素,以確保實驗的可重複性。
二、PyTorch中隨機種子固定的方法
在PyTorch中,我們可以使用以下代碼來允許固定隨機種子:
import torch import random import numpy as np # Set the random seed manually for reproducibility. torch.manual_seed(0) # Set the random seed manually for reproducibility. np.random.seed(0) # Set the random seed manually for reproducibility. random.seed(0)
在上述代碼示例中,我們使用PyTorch、NumPy和Python內置隨機函數庫的函數分別調用了函數torch.manual_seed(0), np.random.seed(0)和random.seed(0)來設置隨機種子。
三、 PyTorch中隨機種子固定的方法詳解
1、torch.backends.cudnn.benchmark
在使用GPU進行訓練時,使用cudnn.benchmark可以自動尋求最優的cudnn算法來優化訓練速度,但同時也會引入隨機因素。因此,在使用可重複的實驗時,我們要將其關閉。示例:
import torch.backends.cudnn as cudnn # Turn off benchmark mode when not needed cudnn.benchmark = False torch.backends.cudnn.deterministic = True
2、針對卷積器權重和偏執設置隨機種子
在PyTorch中,通過nn.Conv2d類建立的卷積層,如果不顯式的設置卷積層的偏置以及權重,PyTorch會自動生成。生成方式參考其源碼,它會從均勻分布U(-stdv, stdv)中隨機取值,其中stdv為sqrt(1 / n),其中n等於權重的元素個數或者輸入通道數。對於這個變量的初始值的設置,會對模型的訓練有很大的影響,這也是一個重要的隨機因素。我們可以通過如下代碼來設置隨機種子:
torch.manual_seed(123) model = nn.Sequential(nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2), nn.Conv2d(16, 32, kernel_size=3, stride=1, padding=1), nn.ReLU(), nn.MaxPool2d(kernel_size=2, stride=2)) # Explicitly define the initialization of the conv parameters for p in model.parameters(): if len(p.shape) >=2: torch.nn.init.xavier_normal_(p)
3、隨機數據生成器的隨機種子
在模型訓練的過程中,我們需要考慮輸入的數據集是否容易受到隨機性的影響,如果是,則需要初始化其生成方法的隨機種子。示例代碼:
# Configure the data generator to have a stable randomization pattern train_loader = torch.utils.data.DataLoader( torchvision.datasets.ImageFolder(train_dir, transforms.Compose([ transforms.RandomHorizontalFlip(), transforms.RandomRotation(10), transforms.RandomResizedCrop(size), transforms.ToTensor(), normalize, ])), batch_size=args.batch_size, shuffle=True, num_workers=args.workers, pin_memory=True)
4、 Dropout和BN層的隨機種子
PyTorch中的Dropout和Batch Normalization層,同樣會影響神經網絡的性能。對於Dropout層的構建,可以手動設置隨機種子:
class Model(nn.Module): def __init__(self): super(Model, self).__init__() self.dropout = nn.Dropout(p=0.5) def forward(self, x): x = self.dropout(x) return x model = Model() model.train() # Explicitly define dropout's random seed torch.manual_seed(123) dropout_output1 = model(torch.randn([1, 3])) # If we set the random seed again, we should get the same result. torch.manual_seed(123) dropout_output2 = model(torch.randn([1, 3])) print(torch.all(torch.eq(dropout_output1, dropout_output2)))
對於Batch Normalization層,由於其屬於一個自適應的過程,其無法通過簡單的固定隨機種子的方法固定其均值和方差。但是我們可以修改內部的參考數據集,使之與訓練之前的數據保持一致,來實現模型的可復現性。代碼示例:
class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.bn = nn.BatchNorm2d(5) def forward(self, x): x = self.bn(x) return x model = MyModel() # In order to make the batch_norm layer deterministic, # we can manually set the running mean/std to a known value. # Assuming you have inputs of shape (batch_size, channel, height, width) inputs = torch.randn(32, 5, 24, 24) # Load the BN layer with data with fixed mean/std. model.eval() out = model(inputs) model.train() print(out.mean(), out.var())
四、 總結
在PyTorch中,固定隨機種子是非常關鍵的方法之一來確保實驗的可重複性。在實際的開發過程中,我們需要考慮到多個方面的隨機化元素,如Dropout、BatchNormalization層等等。只有統一設置好隨機種子,才能保證各種實驗之間的可比性和生產環境的穩定性。
原創文章,作者:BDDCH,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/332702.html