Implementation of early stopping in PyTorch, eval() considered as not propper Attribute of Tensor / model

Viewed 34

I have encountered some problems adding 'early stopping' functionality to CNN / MNIST project. I have used the whole function compute_acc() from Sebastian Raschka DL book, but project unfortunatelly raise Attribute Error:

Error I got:

Traceback (most recent call last): File "C:\Users\Ryzen\PycharmProjects\pyt-1\main.py", line 109, in acc = compute_acc(logits, y, compute_device=device).detach() File "C:\Users\Ryzen\PycharmProjects\pyt-1\main.py", line 52, in compute_acc data_model.eval() AttributeError: 'Tensor' object has no attribute 'eval'. Did you mean: 'equal'?

Here is my full code:

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils import data
from torchvision import datasets
from torchvision import transforms


class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()

        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6,
                               kernel_size=5, stride=1, padding=0)
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16,
                               kernel_size=5, stride=1, padding=0)
        self.conv3 = nn.Conv2d(in_channels=16, out_channels=120,
                               kernel_size=5, stride=1, padding=0)
        self.linear1 = nn.Linear(120, 84)
        self.linear2 = nn.Linear(84, 10)
        self.tanh = nn.Tanh()
        self.avgpool = nn.AvgPool2d(kernel_size=2, stride=2)

    def forward(self, x):
        x = self.conv1(x)
        x = self.tanh(x)
        x = self.avgpool(x)
        x = self.conv2(x)
        x = self.tanh(x)
        x = self.avgpool(x)
        x = self.conv3(x)
        x = self.tanh(x)
        x = x.reshape(x.shape[0], -1)
        x = self.linear1(x)
        x = self.tanh(x)
        x = self.linear2(x)
        return x


def compute_acc(data_model, data_loader, compute_device):
    correct_pred, num_examples = 0, 0
    data_model.eval()
    for i, (features, targets) in enumerate(data_loader):
        features = features.to(compute_device)
        targets = targets.to(compute_device)

        logits, probas = data_model(features)
        _, predicted_labels = torch.max(probas, 1)
        num_examples += targets.size(0)
        assert predicted_labels.size() == targets.size()
        correct_pred += (predicted_labels == targets).sum()
    return correct_pred.float() / num_examples * 100


if __name__ == '__main__':
    transforms = transforms.Compose([transforms.Resize((32, 32)),
                                     transforms.ToTensor()])

    mnist_train = datasets.MNIST(root='mnist_data',
                                 train=True,
                                 transform=transforms,
                                 download=False)

    mnist_validation = datasets.MNIST(root='mnist_data',
                                      train=False,
                                      transform=transforms)

    device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

    model = LeNet()
    cost = torch.nn.CrossEntropyLoss()
    opt = optim.Adam(model.parameters())

    train_loss = []
    validation_acc = []
    best_model = None
    best_acc = None
    best_epoch = None
    max_epoch = 10000
    no_improvement = 5
    batch_size = 512

    for n_epoch in range(max_epoch):
        model.train()
        loader = data.DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=1)
        epoch_loss = []
        for X_batch, y_batch in loader:
            opt.zero_grad()
            logits = model(X_batch)
            loss = cost(logits, y_batch)
            loss.backward()
            opt.step()
            epoch_loss.append(loss.detach())
        train_loss.append(torch.tensor(epoch_loss).mean())
        model.eval()
        loader = data.DataLoader(mnist_validation, batch_size=len(mnist_validation), shuffle=False)
        X, y = next(iter(loader))
        logits = model(X)
        acc = compute_acc(logits, y, compute_device=device).detach()
        validation_acc.append(acc)
        if best_acc is None or acc > best_acc:
            best_acc = acc
            best_model = model.state_dict()
            best_epoch = n_epoch
        if best_epoch + no_improvement <= n_epoch:
            break

    model.load_state_dict(best_model)
0 Answers
Related