PyTorch:在训练中添加验证错误

Posted

技术标签:

【中文标题】PyTorch:在训练中添加验证错误【英文标题】:PyTorch: Add validation error in training 【发布时间】:2018-10-16 20:01:53 【问题描述】:

我正在使用 PyTorch 训练一个 cnn 模型。这是我的网络架构:

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

然后我像下面这样训练模型:

# 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]

我想知道是否可以在训练中添加验证错误?我的意思是Keras中的类似(验证拆分):

myModel.fit(trainX, trainY, epochs=50, batch_size=1, verbose=2, validation_split = 0.1)

【问题讨论】:

【参考方案1】:

这是一个示例,如何拆分数据集以进行训练和验证,然后在每个 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))

【讨论】:

将每个 epoch 中的优化器设置为之前一次是否有意义?

以上是关于PyTorch:在训练中添加验证错误的主要内容,如果未能解决你的问题,请参考以下文章

PyTorch:为啥在训练时期循环内部或外部调用验证准确性会发生变化?

pytorch踩坑之model.eval()和model.train()输出差距很大

Pytorch保留验证集上最好的模型

PyTorch 半精度训练踩坑

pytorch如何给预训练模型添加新的层

在 PyTorch 中使用 DataLoaders 进行 k 折交叉验证