1.訓練集驗證集測試集
訓練集:訓練數據
驗證集:驗證不同算法(比如利用網格搜索對超參數進行調整等),檢驗哪種更有效
測試集:正確評估分類器的性能
正常流程:驗證集會記錄每個時間戳的參數,在加載test數據前會加載那個最好的參數,再來評估。比方說訓練完6000個epoch后,發現在第3520個epoch的validation表現最好,測試時會加載第3520個epoch的參數。
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
#超參數
batch_size=200
learning_rate=0.01
epochs=10
#獲取訓練數據
train_db = datasets.MNIST('../data', train=True, download=True, #train=True則得到的是訓練集
transform=transforms.Compose([ #transform進行數據預處理
transforms.ToTensor(), #轉成Tensor類型的數據
transforms.Normalize((0.1307,), (0.3081,)) #進行數據標準化(減去均值除以方差)
]))
#DataLoader把訓練數據分成多個小組,此函數每次拋出一組數據。直至把所有的數據都拋出。就是做一個數據的初始化
train_loader = torch.utils.data.DataLoader(train_db, batch_size=batch_size, shuffle=True)
#獲取測試數據
test_db = datasets.MNIST('../data', train=False,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))
]))
test_loader = torch.utils.data.DataLoader(test_db, batch_size=batch_size, shuffle=True)
#將訓練集拆分成訓練集和驗證集
print('train:', len(train_db), 'test:', len(test_db)) #train: 60000 test: 10000
train_db, val_db = torch.utils.data.random_split(train_db, [50000, 10000])
print('db1:', len(train_db), 'db2:', len(val_db)) #db1: 50000 db2: 10000
train_loader = torch.utils.data.DataLoader(train_db, batch_size=batch_size, shuffle=True)
val_loader = torch.utils.data.DataLoader(val_db, batch_size=batch_size, shuffle=True)
class MLP(nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.model = nn.Sequential( #定義網絡的每一層,
nn.Linear(784, 200),
nn.ReLU(inplace=True),
nn.Linear(200, 200),
nn.ReLU(inplace=True),
nn.Linear(200, 10),
nn.ReLU(inplace=True),
)
def forward(self, x):
x = self.model(x)
return x
net = MLP()
#定義sgd優化器,指明優化參數、學習率,net.parameters()得到這個類所定義的網絡的參數[[w1,b1,w2,b2,...]
optimizer = optim.SGD(net.parameters(), lr=learning_rate)
criteon = nn.CrossEntropyLoss()
for epoch in range(epochs):
for batch_idx, (data, target) in enumerate(train_loader):
data = data.view(-1, 28*28) #將二維的圖片數據攤平[樣本數,784]
logits = net(data) #前向傳播
loss = criteon(logits, target) #nn.CrossEntropyLoss()自帶Softmax
optimizer.zero_grad() #梯度信息清空
loss.backward() #反向傳播獲取梯度
optimizer.step() #優化器更新
if batch_idx % 100 == 0: #每100個batch輸出一次信息
print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
epoch, batch_idx * len(data), len(train_loader.dataset),
100. * batch_idx / len(train_loader), loss.item()))
#驗證集用來檢測訓練是否過擬合
val_loss = 0
correct = 0
for data, target in val_loader:
data = data.view(-1, 28 * 28)
logits = net(data)
val_loss += criteon(logits, target).item()
pred = logits.data.max(dim=1)[1]
correct += pred.eq(target.data).sum()
val_loss /= len(val_loader.dataset)
print('\nVAL set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
val_loss, correct, len(val_loader.dataset),
100. * correct / len(val_loader.dataset)))
#測試集用來評估
test_loss = 0
correct = 0 #correct記錄正確分類的樣本數
for data, target in test_loader:
data = data.view(-1, 28 * 28)
logits = net(data)
test_loss += criteon(logits, target).item() #其實就是criteon(logits, target)的值,標量
pred = logits.data.max(dim=1)[1] #也可以寫成pred=logits.argmax(dim=1)
correct += pred.eq(target.data).sum()
test_loss /= len(test_loader.dataset)
print('\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
test_loss, correct, len(test_loader.dataset),
100. * correct / len(test_loader.dataset)))
2.正則化
正則化可以解決過擬合問題。
2.1L2范數(更常用)
在定義優化器的時候設定weigth_decay,即L2范數前面的λ參數。
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate, weight_decay=0.01)
2.2L1范數
Pytorch沒有直接可以調用的方法,實現如下:

3.動量(Momentum)
Adam優化器內置了momentum,SGD需要手動設置。
optimizer = torch.optim.SGD(model.parameters(), args=lr, momentum=args.momentum, weight_decay=args.weight_decay)
4.學習率衰減
torch.optim.lr_scheduler 中提供了基于多種epoch數目調整學習率的方法。
4.1torch.optim.lr_scheduler.ReduceLROnPlateau:基于測量指標對學習率進行動態的下降
torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10, verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)
訓練過程中,optimizer會把learning rate 交給scheduler管理,當指標(比如loss)連續patience次數還沒有改進時,需要降低學習率,factor為每次下降的比例。
scheduler.step(loss_val)每調用一次就會監聽一次loss_val。

4.2torch.optim.lr_scheduler.StepLR:基于epoch
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1)
當epoch每過stop_size時,學習率都變為初始學習率的gamma倍。

5.提前停止(防止overfitting)
基于經驗值。
6.Dropout隨機失活
遍歷每一層,設置消除神經網絡中的節點概率,得到精簡后的一個樣本。
torch.nn.Dropout(p=dropout_prob)
p表示的示的是刪除節點數的比例(Tip:tensorflow中keep_prob表示保留節點數的比例,不要混淆)

測試階段無需使用dropout,所以在train之前執行net_dropped.train()相當于啟用dropout,測試之前執行net_dropped.eval()相當于不啟用dropout。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:- 在Pytorch中使用樣本權重(sample_weight)的正確方法
- Pytorch 如何實現常用正則化
- PyTorch 實現L2正則化以及Dropout的操作
- Python深度學習pyTorch權重衰減與L2范數正則化解析