Pytorch学习笔记(八)——AlexNet

一、构造 Experiment 类

卷积神经网络训练和测试的代码结构大部分都相同,为了方便今后更加简洁地书写代码,这里先构造一个 Experiment 类,并将其保存在 Experiment.py 文件中。

Pytorch学习笔记(八)——AlexNet

import torch
import numpy as np
import matplotlib.pyplot as plt


class Experiment:

    def __init__(self, train_loader, test_loader, model, num_epochs, lr, optimizer='SGD', quiet=False):
        self.train_loader = train_loader
        self.test_loader = test_loader
        self.model = model.cuda()
        self.num_epochs = num_epochs
        self.lr = lr
        self.loss_fn = torch.nn.CrossEntropyLoss()
        self.quiet = quiet
        self.train_loss, self.train_acc = [], []
        self.test_loss, self.test_acc = [], []
        if optimizer == 'SGD':
            self.optimizer = torch.optim.SGD(self.model.parameters(), lr=self.lr)
        elif optimizer == 'Adam':
            self.optimizer = torch.optim.Adam(self.model.parameters(), lr=self.lr)
        else:
            raise ValueError

    def train(self):
        correct, avg_loss = 0, 0
        for batch_idx, (X, y) in enumerate(self.train_loader):
            X, y = X.cuda(), y.cuda()
            pred = self.model(X)
            loss = self.loss_fn(pred, y)
            correct += (pred.argmax(dim=1) == y).sum().item()
            avg_loss += loss
            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()
        avg_loss /= (batch_idx + 1)
        correct /= len(self.train_loader.dataset)
        self.train_loss.append(avg_loss.item())
        self.train_acc.append(correct)
        if not self.quiet:
            print('Train Avg Loss: {:.6f},'.format(avg_loss), end=' ')
            print('Train Accuracy: {:.6f}'.format(correct))

    def test(self):
        correct, avg_loss = 0, 0
        with torch.no_grad():
            for batch_idx, (X, y) in enumerate(self.test_loader):
                X, y = X.cuda(), y.cuda()
                pred = self.model(X)
                loss = self.loss_fn(pred, y)
                correct += (pred.argmax(dim=1) == y).sum().item()
                avg_loss += loss
        avg_loss /= (batch_idx + 1)
        correct /= len(self.test_loader.dataset)
        self.test_loss.append(avg_loss.item())
        self.test_acc.append(correct)
        if not self.quiet:
            print('Test  Avg Loss: {:.6f},'.format(avg_loss), end=' ')
            print('Test  Accuracy: {:.6f}\n'.format(correct))

    def main(self):
        for epoch in range(self.num_epochs):
            if not self.quiet:
                print('Epoch {}\n'.format(epoch + 1) + '-' * 50)
            self.train()
            self.test()
        print("Done!")

    def show(self):
        x = np.arange(1, self.num_epochs + 1)
        plt.plot(x, self.train_loss, c='royalblue', label='train loss')
        plt.plot(x, self.train_acc, c='seagreen', label='train acc', ls='dashed')
        plt.plot(x, self.test_loss, c='darkorchid', label='test loss')
        plt.plot(x, self.test_acc, c='firebrick', label='test acc', ls='dashed')
        plt.legend(loc='best')
        plt.xlabel('epoch')
        plt.grid()
        plt.show()

具体使用方法:

from Experiment import Experiment as E

net = Net()  # 初始化我们的神经网络(无需移动到GPU,因为Experiment会自动将其移动到GPU上)
num_epochs = 20  # 决定有多少个Epoch
lr = 1e-2  # 学习率
e = E(train_loader, test_loader, net, num_epochs, lr)
e.main()  # 进行训练和测试
e.show()  # 绘制损失曲线和准确率曲线

Experiment 仅支持 SGD 和 Adam 优化器,默认使用 SGD 作为优化器,如需更换优化器,则需要为 optimizer 指定参数:

e = E(train_loader, test_loader, net, num_epochs, lr, optimizer='Adam')

默认情况下,执行 e.main() 会不断输出每一个 Epoch 的结果,如果只想看最后的曲线图而不看这些频繁生成结果,需要指定 quiet 参数的值为 True

e = E(train_loader, test_loader, net, num_epochs, lr, quiet=True)

二、AlexNet 简介

AlexNet 和 LeNet 的设计理念非常相似(可以粗略地认为 AlexNet 是更大更深的 LeNet),但依然存在显著差异。相比 LeNet,AlexNet 采用 ReLU 作为激活函数,平均池化换成了最大池化,全连接层中增加了 Dropout 用作正则,此外对于输入的数据集也进行了图像增强。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年5月13日
下一篇 2022年5月13日

相关推荐