基礎神經網絡模型搭建
【Pytorch】數據集的加載和處理(一)
【Pytorch】數據集的加載和處理(二)
損失函數計算模型輸出和目標之間的距離。通過torch.nn 包可以定義一個負對數似然損失函數,負對數似然損失對于訓練具有多個類的分類問題比較有效,負對數似然損失函數的輸入為對數概率,而在模型搭建的輸出層部分接觸過log_softmax,它能從模型中獲取對數概率
目錄
基礎模型搭建
數據集的加載和處理
定義損失函數
定義優化器
訓練并評估模型
基礎模型搭建
import torch
from torch import nn
import torch.nn.functional as F
class Net(nn.Module):def __init__(self):super(Net, self).__init__()def forward(self, x):pass
def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 20, 5, 1)self.conv2 = nn.Conv2d(20, 50, 5, 1)self.fc1 = nn.Linear(4*4*50, 500)self.fc2 = nn.Linear(500, 10)
def forward(self, x):x = F.relu(self.conv1(x))x = F.max_pool2d(x, 2, 2)x = F.relu(self.conv2(x))x = F.max_pool2d(x, 2, 2) x = x.view(-1, 4*4*50)x = F.relu(self.fc1(x))x = self.fc2(x)return F.log_softmax(x, dim=1)
Net.__init__ = __init__
Net.forward = forward
model = Net()
檢查搭建情況?
print(model)
原位置為cpu?
?轉移至所需CUDA設備
device = torch.device("cuda:0")
model.to(device)
print(next(model.parameters()).device)
數據集的加載和處理
導入MNIST訓練數據集和驗證數據集并處理
from torch import nn
from torchvision import datasets
from torch.utils.data import TensorDataset
path2data="./data"
train_data=datasets.MNIST(path2data, train=True, download=True)
x_train, y_train=train_data.data,train_data.targets
val_data=datasets.MNIST(path2data, train=False, download=True)
x_val,y_val=val_data.data, val_data.targets
if len(x_train.shape)==3:x_train=x_train.unsqueeze(1)
print(x_train.shape)
if len(x_val.shape)==3:x_val=x_val.unsqueeze(1)
print(x_val.shape)
train_ds = TensorDataset(x_train, y_train)
val_ds = TensorDataset(x_val, y_val)
for x,y in train_ds:print(x.shape,y.item())breakfrom torch.utils.data import DataLoader
train_dl = DataLoader(train_ds, batch_size=8)
val_dl = DataLoader(val_ds, batch_size=8)
定義損失函數
損失函數計算模型輸出和目標之間的距離。Pytorch 中的 optim 包提供了各種優化算法的實現,例如SGD、Adam、RMSprop 等。
通過torch.nn 包可以定義一個負對數似然損失函數,負對數似然損失對于訓練具有多個類的分類問題比較有效,負對數似然損失函數的輸入為對數概率,而在模型搭建的輸出層部分接觸過log_softmax,它能從模型中獲取對數概率。
loss_func = nn.NLLLoss(reduction="sum")
for xb, yb in train_dl:# move batch to cuda devicexb=xb.type(torch.float).to(device)yb=yb.to(device)out=model(xb)loss = loss_func(out, yb)print (loss.item())break
得到一個測試值?
定義優化器
定義一個Adam優化器,優化器的輸入是模型參數和學習率
from torch import optim
opt = optim.Adam(model.parameters(), lr=1e-4)
通過opt .step()自動更新模型參數,同時需要注意計算下一批的梯度之前需將梯度歸0
opt.step()
opt.zero_grad()
訓練并評估模型
定義一個輔助函數?loss_batch來計算每個小批量的損失值。函數的 opt 參數引用優化器,如果給定,則計算梯度并按小批量更新模型參數。
def loss_batch(loss_func, xb, yb,yb_h, opt=None): loss = loss_func(yb_h, yb) metric_b = metrics_batch(yb,yb_h) if opt is not None: loss.backward()opt.step()opt.zero_grad()return loss.item(),metric_b
?定義一個輔助函數metrics_batch來計算每個小批量的性能指標,這里以準確率作為分類任務的性能指標,并使用 output.argmax 來獲取概率最高的預測類
def metrics_batch(target, output):pred = output.argmax(dim=1, keepdim=True)corrects=pred.eq(target.view_as(pred)).sum().item()return corrects
定義一個輔助函數loss_epoch來計算整個數據集的損失和指標值。使用數據加載器對象獲取小批量,將它們提供給模型,并計算每個小批量的損失和指標,通過兩個運行變量來分別添加損失值和指標值。
def loss_epoch(model,loss_func,dataset_dl,opt=None):loss=0.0metric=0.0len_data=len(dataset_dl.dataset)for xb, yb in dataset_dl:xb=xb.type(torch.float).to(device)yb=yb.to(device)yb_h=model(xb)loss_b,metric_b=loss_batch(loss_func, xb, yb,yb_h, opt)loss+=loss_bif metric_b is not None:metric+=metric_bloss/=len_datametric/=len_datareturn loss, metric
最后,定義一個輔助函數train_val來訓練多個時期的模型。在每個時期使用驗證數據集評估模型的性能。訓練和評估需要分別使用 model.train()和 model.eval()模式。torch.no_grad()可以阻止 autograd 在評估期間計算梯度。
def train_val(epochs, model, loss_func, opt, train_dl, val_dl):for epoch in range(epochs):model.train()train_loss,train_metric=loss_epoch(model,loss_func,train_dl,opt)model.eval()with torch.no_grad():val_loss, val_metric=loss_epoch(model,loss_func,val_dl)accuracy=100*val_metricprint("epoch: %d, train loss: %.6f, val loss: %.6f,accuracy: %.2f" %(epoch, train_loss,val_loss,accuracy))
?設定時期數為5,調用函數進行訓練和評估
num_epochs=5
train_val(num_epochs, model, loss_func, opt, train_dl, val_dl)