PyTorch: Add validation error in training
17,663
Here is an example how to split your dataset for training and validation, then switch between the two phases every epoch:
import numpy as np
import torch
from torchvision import datasets
from torch.autograd import Variable
from torch.utils.data.sampler import SubsetRandomSampler
# Examples:
my_dataset = datasets.MNIST(root="/home/benjamin/datasets/mnist", train=True, download=True)
validation_split = 0.1
dataset_len = len(my_dataset)
indices = list(range(dataset_len))
# Randomly splitting indices:
val_len = int(np.floor(validation_split * dataset_len))
validation_idx = np.random.choice(indices, size=val_len, replace=False)
train_idx = list(set(indices) - set(validation_idx))
# Contiguous split
# train_idx, validation_idx = indices[split:], indices[:split]
## Defining the samplers for each phase based on the random indices:
train_sampler = SubsetRandomSampler(train_idx)
validation_sampler = SubsetRandomSampler(validation_idx)
train_loader = torch.utils.data.DataLoader(my_dataset, sampler=train_sampler)
validation_loader = torch.utils.data.DataLoader(my_dataset, sampler=validation_sampler)
data_loaders = {"train": train_loader, "val": validation_loader}
data_lengths = {"train": len(train_idx), "val": val_len}
# Training with Validation (your code + code from Pytorch tutorial: https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html)
n_epochs = 40
net = ...
for epoch in range(n_epochs):
print('Epoch {}/{}'.format(epoch, n_epochs - 1))
print('-' * 10)
# Each epoch has a training and validation phase
for phase in ['train', 'val']:
if phase == 'train':
optimizer = scheduler(optimizer, epoch)
net.train(True) # Set model to training mode
else:
net.train(False) # Set model to evaluate mode
running_loss = 0.0
# Iterate over data.
for data in data_loaders[phase]:
# get the input images and their corresponding labels
images = data['image']
key_pts = data['keypoints']
# flatten pts
key_pts = key_pts.view(key_pts.size(0), -1)
# wrap them in a torch Variable
images, key_pts = Variable(images), Variable(key_pts)
# convert variables to floats for regression loss
key_pts = key_pts.type(torch.FloatTensor)
images = images.type(torch.FloatTensor)
# forward pass to get outputs
output_pts = net(images)
# calculate the loss between predicted and target keypoints
loss = criterion(output_pts, key_pts)
# zero the parameter (weight) gradients
optimizer.zero_grad()
# backward + optimize only if in training phase
if phase == 'train':
loss.backward()
# update the weights
optimizer.step()
# print loss statistics
running_loss += loss.data[0]
epoch_loss = running_loss / data_lengths[phase]
print('{} Loss: {:.4f}'.format(phase, epoch_loss))
Author by
Edamame
Updated on June 05, 2022Comments
-
Edamame about 2 years
I am using PyTorch to train a cnn model. Here is my Network architecture:
import torch from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.nn.init as I class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 5) self.pool = nn.MaxPool2d(2,2) self.conv1_bn = nn.BatchNorm2d(32) self.conv2 = nn.Conv2d(32, 64, 5) self.conv2_drop = nn.Dropout2d() self.conv2_bn = nn.BatchNorm2d(64) self.fc1 = torch.nn.Linear(53*53*64, 256) self.fc2 = nn.Linear(256, 136) def forward(self, x): x = F.relu(self.conv1_bn(self.pool(self.conv1(x)))) x = F.relu(self.conv2_bn(self.pool(self.conv2_drop(self.conv2(x))))) x = x.view(-1, 53*53*64) x = F.relu(self.fc1(x)) x = F.dropout(x, training=self.training) x = self.fc2(x) return x
Then I train the model like below:
# prepare the net for training net.train() for epoch in range(n_epochs): # loop over the dataset multiple times running_loss = 0.0 # train on batches of data, assumes you already have train_loader for batch_i, data in enumerate(train_loader): # get the input images and their corresponding labels images = data['image'] key_pts = data['keypoints'] # flatten pts key_pts = key_pts.view(key_pts.size(0), -1) # wrap them in a torch Variable images, key_pts = Variable(images), Variable(key_pts) # convert variables to floats for regression loss key_pts = key_pts.type(torch.FloatTensor) images = images.type(torch.FloatTensor) # forward pass to get outputs output_pts = net(images) # calculate the loss between predicted and target keypoints loss = criterion(output_pts, key_pts) # zero the parameter (weight) gradients optimizer.zero_grad() # backward pass to calculate the weight gradients loss.backward() # update the weights optimizer.step() # print loss statistics running_loss += loss.data[0]
I am wondering if it is possible to add the validation error in the training? I mean something like this (validation split) in
Keras
:myModel.fit(trainX, trainY, epochs=50, batch_size=1, verbose=2, validation_split = 0.1)
-
Shamoon over 4 yearsDoes it make sense to set the optimizer in each epoch as opposd to once before?