一、torch.dropout的定義
torch.dropout是PyTorch深度學習框架中的一種正則化方法,用於在深度神經網路訓練中防止過擬合。它沿著網路中的不同神經元隨機「丟棄」(即將權重設置為零)一些神經元,讓網路學習到更加魯棒的特徵,同時避免過度擬合。其函數原型為:
torch.nn.functional.dropout(x, p=0.5, training=True, inplace=False)
其中,參數x為輸入張量,p為丟棄概率,即將神經元丟棄的概率,training為是否在訓練模式,inplace為是否進行就地替換操作。下面我們將從不同方面來詳細介紹torch.dropout的應用和實現。
二、torch.dropout在深度神經網路中的應用
在深度神經網路中,過擬合是一個極大的問題。深度神經網路通常有很多參數需要訓練,如果網路過度擬合,學習到的特徵就會失去泛化能力,對於新的輸入數據預測效果就不太好。這時候,我們可以使用正則化方法來緩解過擬合。torch.dropout可以在深度神經網路中起著非常重要的正則化作用。下面的代碼示例是對於一個兩層神經網路的實現例子,其中應用了torch.dropout實現正則化:
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(784, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, 10)
def forward(self, x):
x = x.view(-1, 784)
x = F.dropout(F.relu(self.fc1(x)), training=self.training, p=0.2)
x = F.dropout(F.relu(self.fc2(x)), training=self.training, p=0.2)
x = self.fc3(x)
return F.log_softmax(x)
net = Net()
print(net)
在以上代碼中,我們定義了一個名為Net的兩層神經網路,並在其中設置了dropout層,參數p分別為0.2。可以看出,我們在網路的前兩層中使用了dropout層,丟棄了某些神經元,讓網路更加具有魯棒性。
三、torch.dropout在GAN中的應用
在生成對抗網路GAN中,我們通常需要同時對生成器和判別器進行訓練,但是由於兩者的訓練速度、收斂速度等因素不同,易造成訓練不平衡。為了緩解這一問題,我們可以使用dropout方法。如下利用GAN實現手寫數字生成的代碼:
import torch
import torch.nn as nn
import torch.nn.functional as F
import matplotlib.pyplot as plt
# 定義鑒別器模型
class Discriminator(nn.Module):
def __init__(self):
super(Discriminator, self).__init__()
self.layer_one = nn.Linear(784, 1024)
self.layer_two = nn.Linear(1024, 512)
self.layer_three = nn.Linear(512, 256)
self.layer_four = nn.Linear(256, 1)
self.dropout = nn.Dropout(0.1)
def forward(self, x):
x = F.leaky_relu(self.layer_one(x), 0.2)
x = self.dropout(x)
x = F.leaky_relu(self.layer_two(x), 0.2)
x = self.dropout(x)
x = F.leaky_relu(self.layer_three(x), 0.2)
x = self.dropout(x)
x = torch.sigmoid(self.layer_four(x))
return x
# 定義生成器模型
class Generator(nn.Module):
def __init__(self):
super(Generator, self).__init__()
self.layer_one = nn.Linear(100, 256)
self.layer_two = nn.Linear(256, 512)
self.layer_three = nn.Linear(512, 1024)
self.layer_four = nn.Linear(1024, 784)
def forward(self, x):
x = F.leaky_relu(self.layer_one(x), 0.2)
x = F.leaky_relu(self.layer_two(x), 0.2)
x = F.leaky_relu(self.layer_three(x), 0.2)
x = torch.tanh(self.layer_four(x))
return x
# 定義訓練過程
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
discriminator = Discriminator().to(device)
generator = Generator().to(device)
criterion = nn.BCELoss()
d_optimizer = torch.optim.Adam(discriminator.parameters(), lr=0.0003)
g_optimizer = torch.optim.Adam(generator.parameters(), lr=0.0003)
for epoch in range(200):
D_loss_list = []
G_loss_list = []
for i, (inputs, _) in enumerate(train_loader):
real = inputs.view(-1, 784).to(device)
real_label = torch.ones(real.size(0)).to(device)
fake_label = torch.zeros(real.size(0)).to(device)
# 訓練判別器
d_real = discriminator(real)
D_loss_real = criterion(d_real, real_label)
z = torch.randn(inputs.size(0), 100).to(device)
fake = generator(z)
d_fake = discriminator(fake)
D_loss_fake = criterion(d_fake, fake_label)
D_loss = D_loss_real + D_loss_fake
D_loss_list.append(D_loss.item())
discriminator.zero_grad()
D_loss.backward()
d_optimizer.step()
# 訓練生成器
z = torch.randn(inputs.size(0), 100).to(device)
fake = generator(z)
d_fake = discriminator(fake)
G_loss = criterion(d_fake, real_label)
G_loss_list.append(G_loss.item())
generator.zero_grad()
G_loss.backward()
g_optimizer.step()
print(f"[Epoch {epoch + 1:3d}] D_loss: {sum(D_loss_list) / len(D_loss_list):.4f} G_loss: {sum(G_loss_list) / len(G_loss_list):.4f}")
在以上代碼中,我們定義了生成器、判別器模型,並在其中加入dropout層,控制了訓練過程中的梯度流動,從而緩解了訓練不平衡的問題,提高了GAN的效果。
四、torch.dropout的實現原理
torch.dropout的實現原理是通過在神經網路的輸入、隱藏層中按照一定的概率隨機將一些神經元的權重置為零,達到防止過擬合的效果。其隨機失活的過程中,保留的神經元可以看作是被賦予了更高的重要性,因此訓練得到的模型具有較好的泛化能力。其偽代碼如下:
for each epoch:
for each mini-batch:
forward input through neural network
randomly zero out (i.e. 'dropout') some elements in the input
forward the modified input through the neural network
compute loss and backpropagate gradients
以上代碼中每一次迭代,我們會隨機選取一部分神經元進行隨機失活,實現dropout層的功能。同時,我們需要控制穩定性,因此我們在調用dropout層時,調用如下代碼:
if not training:
return input * (1-p)
noise = input.data.new(input.size()).bernoulli_(1-p).div_(1-p)
return noise * input
其中,if not training的部分用於控制dropout在訓練時失活,而在評估和測試時保持不變,保持隨機失活過程的穩定性。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/156504.html