卷积神经网络CNN + Cifar10 + letnet5 深度学习实战

卷积神经网络CNN + Cifar10 + letnet5 深度学习实战

本文使用 p y t o r c h pytorch pytorch C i f a r 10 Cifar10 Cifar10 数据集完成深度学习实战

基于卷积神经网络 C N N CNN CNN,网络结构为 l e t n e t 5 letnet5 letnet5

导入库

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np

对图片进行多种预处理操作

# 对训练集图片进行多种预处理操作
train_transform = transforms.Compose([
    # 数据增强
     # 根据概率对图片进行水平(左右)翻转,每次根据概率来决定是否执行翻转
    transforms.RandomHorizontalFlip(),
    # 根据一定概率将图片转换为灰度图
    transforms.RandomGrayscale(),
    # 将图片数组转成张量
    transforms.ToTensor(),  
    # 归一化操作
    transforms.Normalize((0.5,), (0.5,))  
])

# 对测试集图片进行多种预处理操作
test_transform = transforms.Compose([
    # 将图片数组转成张量
    transforms.ToTensor(),  
    # 归一化操作
    transforms.Normalize((0.5,), (0.5,))  
])

数据加载 (方法有别)

# 将路径下的图片自动加载
# 训练集的加载设置train项为True,download设置为True后,自动从网络下载并解压
train_dataset = datasets.CIFAR10(root="./data", train=True, download=True, transform=train_transform)
test_dataset = datasets.CIFAR10(root="./data", train=False, download=True, transform=test_transform)
# 定义数据加载器
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
# shuffle 用来打乱数据的顺序,防止过拟合提高模型的鲁棒性

查看数据集图片

for i, (images, _) in enumerate(train_loader):
    # print(images.shape)
    # 把一批数据的图片组成一张图片
    img = torchvision.utils.make_grid(images)
    # 调整图片维度,将通道数放在最后一维
    img = np.array(img).transpose(1, 2, 0)
    plt.imshow(img)
    plt.show()
    break

设备检查

# 定义训练设备, 检查是否使用GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

定义超参

# 批大小,训练时每次输入到模型的数据的数量
batch_size = 128
# 定义学习率0.001
learning_rate = 1e-3
# 训练循环次数
epochs = 10
# 分类数
num_classes = 10

定义随机数种子以确保可重复性,设置CPU生成随机数的种子,方便下次复现实验结果

seed = 42
torch.manual_seed(seed)

定义模型结构

class CNNNeuralNetwork(nn.Module):
    # 构造函数
    def __init__(self):
        # 访问父类的构造方法
        super().__init__()
        # Flatten层用来将二维图片reshape为一维向量
        self.flatten = nn.Flatten()
        # 在构造方法里,定义网络的结构。Sequential是一种容器,允许用户按顺序去定义神经网络的各个层
        # 卷积部分提取特征
        self.cnn_layer = nn.Sequential(
            # 卷积层,参数含义依次为输入通道、输出特征图数(卷积核数量)、卷积核大小、步长、填充padding
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=0),
            # 激活函数
            nn.ReLU(),
            # 池化层,选择最大池化
            nn.MaxPool2d(2),
            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=0),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(in_channels=64, out_channels=128, kernel_size=5, stride=1, padding=0),
            nn.ReLU()
        )
        # 全连接层,进行分类
        self.fc_layer = nn.Sequential(
            nn.Linear(in_features=128, out_features=128),
            nn.ReLU(),
            # 随机丢弃,缓解过拟合,参数为丢弃的概率
            nn.Dropout(0.5),
            nn.Linear(in_features=128, out_features=num_classes)
        )

    # 定义前向传播的过程,x是输入模型的数据
    def forward(self, x):
        x = self.cnn_layer(x)
        # view方法类似 numpy 的 reshape,用于改变张量的形状
        x = x.view(-1, 128)
        # logits用来描述模型未经处理(未经过激活层处理)的输出值
        logits = self.fc_layer(x)
        return logits

实例化模型

# 实例化模型
model = CNNNeuralNetwork().to(device)

定义损失函数和优化器

# 定义目标函数,使用交叉熵函数作为目标函数,即损失函数
loss_fn = nn.CrossEntropyLoss()
# 定义优化器(反向传播——随机梯度下降的实现)
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

定义训练过程

def train(dataloader, model, loss_fn, optimizer):
    # 训练集大小
    size = len(dataloader.dataset)
    model.train()
    for batch, (X, y) in enumerate(dataloader):
        X, y = X.to(device), y.to(device)
        # 计算预测值
        predict = model(X)
        # 计算损失值
        loss = loss_fn(predict, y)
        # 反向传播, backward()是用于自动计算梯度并进行反向传播的方法
        loss.backward()
        # 更新神经网络模型中的参数
        optimizer.step()
        # 清楚之前的计算梯度, torch中的梯度计算时,若不进行清除会导致梯度累加
        optimizer.zero_grad()

        # 显示当前训练了多少数据
        if batch % 100 == 0:
            loss, current = loss.item(), (batch + 1) * len(X)
            print(f"loss:{loss:>7f} [{current:>5d}/{size:>5d}]")

定义测试函数

def test(dataloader, model, loss_fn):
    # 训练集大小
    size = len(dataloader.dataset)
    num_batches = len(dataloader)
    # 设置为评估模式
    model.eval()
    test_loss, correct = 0, 0
    # 测试过程中不再进行梯度计算
    with torch.no_grad():
        for X, y in dataloader:
            X, y = X.to(device), y.to(device)
            # 计算预测值
            predict = model(X)
            # 计算整个数据集总的loss
            test_loss += loss_fn(predict, y).item()
            # 计算总正确率, argmax返回最大值的索引
            correct += (predict.argmax(1) == y).type(torch.float).sum().item()
            test_loss /= num_batches
            correct /= size
            print(f"Test Error: \nAccuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")
            return correct, test_loss

绘制图像

# 存储迭代次数
iterations = []
accuracies = []
losses = []

# 初始化图形
plt.ion()
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

ax1.set_title("Accuracy over iterations")
ax1.set_xlabel("Iterations")
ax1.set_ylabel("Accuracy")
accuracy_line, = ax1.plot([], [], 'b')

ax2.set_title("Loss over iterations")
ax2.set_xlabel("Iterations")
ax2.set_ylabel("Loss")
loss_line, = ax2.plot([], [], 'r')


# 实时更新图形的函数
def update_plot(iteration, accuracy, loss):
    # 添加元素到列表的最后面
    iterations.append(iteration)
    accuracies.append(accuracy)
    losses.append(loss)

    # 更新数据
    accuracy_line.set_data(iterations, accuracies)
    loss_line.set_data(iterations, losses)

    # 更新坐标轴范围
    ax1.set_xlim(0, max(iterations))
    ax1.set_ylim(0, 1)
    ax2.set_xlim(0, max(iterations))
    ax2.set_ylim(0, max(losses) if losses else 1)

    plt.draw()
    plt.pause(0.1)

运行测试 t r a i n train train t e s t test test

if __name__ == '__main__':
    for i in range(epochs):
        print(f"Epoch {i+1}\n--------------------------")
        train(train_loader, model, loss_fn, optimizer)
        acc, loss = test(test_loader, model, loss_fn)
        update_plot(i, acc, loss)
    plt.show()

输出
在这里插入图片描述

  • 23
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值