笔记:如何训练一个LeNet网络

本文介绍了如何使用PyTorch实现经典的LeNet网络,包括模型定义、数据预处理、训练流程及预测。通过CIFAR10数据集进行训练,展示了训练过程中的损失计算、准确率评估,并提供了离线加载数据的方法。此外,还提供了对图像进行预测的代码示例。
摘要由CSDN通过智能技术生成


前言

写在最开始,在B站发现一个很奈斯的Up主,跟着他学习到了很多深度网络的知识,在评论区又看见一个很奈斯的童鞋写了很奈斯的笔记,这让我备受鼓舞,在深度学习的道路上,希望记录下自己的点点滴滴。
Up主B站链接:霹雳吧啦Wz的B站主页
Up主CSDN链接:霹雳吧啦Wz的CSDN主页
爱学习的童鞋CSDN链接:评论区童鞋笔记


提示:以下是本篇文章正文内容,下面案例可供参考

一、图像分类:Pytorch官网Demo(LeNet)

注意:一定要学会查Pytorch官网
参考:

  1. pytorch英文Demo(LeNet)(中文链接)
  2. Pytorch卷积操作

二、demo流程

  1. model.py:定义LeNet
  2. train.py:加载数据,训练,计算Loss,测试集计算准确率,保存训练参数
  3. predict.py:对自己的图像进行预测

三、

1.model.py

代码如下:

"""
input:32*32*1
Conv1:Kernel_size=5*5,Channel=16,Stride=1,padding=0
Pooling1:Kernel_size=2*2,Stride=2
Conv2:kernel_size=5*5,Channel=32,Stride=1,padding=0
Pooling2:kernel_Size=2*2,stride=2
Fc1:input=32*10*10 ouput=120
Fc2:input=120 ouput=84
Dc3:input=84 output=10

pytorch Tensor的通道顺序:[Batch,Channel,H,W]
"""

import torch.nn as nn
import torch.nn.functional as F


class LeNet(nn.Module):
    """
    1.定义初始化函数 包括网络用到的各个层结构
    2.前向传播过程
    """
    def __init__(self):
        super(LeNet, self).__init__()      # 多继承用到super函数
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.fc1 = nn.Linear(32*5*5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)


    def forward(self, x):
        x = F.relu(self.conv1(x))    # input[3,32,32] output[16,28,28]
        x = self.pool1(x)            # output[16,14,14]
        x = F.relu(self.conv2(x))    # output[32,10,10]
        x = self.pool2(x)            # output[32,5 ,5 ]
        x = x.view(-1, 32*5*5)       # output[32*5*5] 展平后节点的个数
        x = F.relu(self.fc1(x))      # output[120]
        x = F.relu(self.fc2(x))      # output[84]
        x = self.fc3(x)      # output[10]


        return x
# 实例化的例子
# import torch
# input1 = torch.rand(32, 3, 32, 32)
# model = LeNet()
# print(model)
# output = model(input1)

需要注意:

  1. pytorch中Tensor的通道排序为:[Batch,Channel,Height,Weight]
  2. LeNet网络结构图

### 1.nn.Conv2d
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros')
  • in_channels:输入特征矩阵的深度。如输入一张RGB彩色图像,那in_channels=3
  • out_channels:输入特征矩阵的深度。也等于卷积核的个数,使用n个卷积核输出的特征矩阵深度就是n
  • kernel_size:卷积核的尺寸。可以是int类型,如3 代表卷积核的height=width=3,也可以是tuple类型如(3, 5)代表卷积核的height=3,width=5
  • stride:卷积核的步长。默认为1,和kernel_size一样输入可以是int型,也可以是tuple类型
  • padding:补零操作,默认为0。可以为int型如1即补一圈0,如果输入为tuple型如(2, 1) 代表在上下补2行,左右补1列。
    在这里插入图片描述

记得一定要会查原函数:CTRL+单机鼠标左键

2.Train.py

2.1 导入数据集

导入包
import torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import time
数据预处理

对输入的图像数据做预处理,即
shape (H x W x C) in the range [0, 255] →shape (C x H x W) in the range [0.0, 1.0]

    """
    数据预处理 转化为Tensor格式 and 标准化处理
    Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor
    """
    
    transform = transforms.Compose(
        [transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
数据集介绍

要会查数据集

Pytorch官网的torchvision.datasets介绍

在pycharm中可以看见常见的数据集“
在这里插入图片描述
本次用的是CIFA数据集,共有10个类别classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

在这里插入图片描述

导入加载训练集
    '''
    50000张训练图片  通过torchvision.datasets.CIFAR10下载
    '''
    train_set = torchvision.datasets.CIFAR10(root='./data',       # 训练集下载目录
                                             train=True,          # True为下载训练集
                                             download=False,      # 是否下载
                                             transform=transform  # 数据预处理
                                             )
    train_loader = torch.utils.data.DataLoader(train_set,         # 导入训练集
                                               batch_size=36,     # 每批训练样本数
                                               shuffle=True,      # 是否打乱训练集
                                               num_workers=0      # 线程数,windows下设置为0
                                               )
导入加载测试集
    # 10000张验证图片
    val_set = torchvision.datasets.CIFAR10(root='./data',
                                           train=False,        # False表示为测试集
                                           download=False,
                                           transform=transform)
    val_loader = torch.utils.data.DataLoader(val_set,
                                             batch_size=5000,  # 每批用于验证的样本数
                                             shuffle=False,
                                             num_workers=0)
    # 获取测试集中的图像和标签 用于计算accuracy
    val_data_iter = iter(val_loader)
    val_image, val_label = val_data_iter.next()
离线数据加载的方法

在线下载数据集会很麻烦,可以离线下载好CIFAR10数据集,但是运行的时候仍然会报错,这时可以通过修改torchvision.datasets.CIFAR10中的URL链接,具体操作如下:

  1. 提前下载好cifa10数据集,网上有很多链接

  2. 我将下载好的压缩包放至某文件夹下,保证该路径无中文
    在这里插入图片描述

  3. 将该路径复制黏贴至浏览器中,然后复制浏览器中的地址
    在这里插入图片描述

  4. 在代码中修改按住CTRL,同时鼠标左键单击datasets.CIFAR10在这里插入图片描述

  5. 进入该函数后,找到此URL修改,然后设置download=True,再次运行代码即可。在这里插入图片描述

数据集可视化

按照pytorch官网demo例程,可以可视化数据集,注意修改Batch_size即可,因为一次不可能显示很多图片

    def imshow(img):
        img = img / 2 + 0.5  # unnormalize
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg, (1, 2, 0)))
        plt.show()

    # print labels
    print(' '.join('%5s' % classes[val_label[j]] for j in range(4)))
    # show images
    imshow(torchvision.utils.make_grid(val_image))

在这里插入图片描述

这里显示了32张图片

2.2 训练过程

名词定义
epoch对训练集的全部数据进行一次完整的训练,称为 一次 epoch
batch由于硬件算力有限,实际训练时将训练集分成多个批次训练,每批数据的大小为 batch_size
iteration或step对一个batch的数据训练的过程称为 一个 iteration 或 step

本次demo中,训练集一共50000个样本,batch_size=500,一次完整的训练需要iteration=100,epoch=1

    net = LeNet()                                       # 实例化
    loss_function = nn.CrossEntropyLoss()               # 定义损失函数
    optimizer = optim.Adam(net.parameters(), lr=0.001)  # 定义优化器:训练参数,学习率

    for epoch in range(5):     # 一个epoch即对所以训练集样本进行一次训练

        running_loss = 0.0
        time_start = time.perf_counter()
        for step, data in enumerate(train_loader, start=0):

            inputs, labels = data                  # 获取训练图像和标签
            optimizer.zero_grad()                  # 清除历史梯度

            # forward + backward + optimize
            outputs = net(inputs)                  # 正向传播
            loss = loss_function(outputs, labels)  # 计算loss
            loss.backward()                        # 反向传播
            optimizer.step()                       # 优化器更新参数

            # print 耗时、损失、准确率
            running_loss += loss.item()
            if step % 500 == 499:                  # print every 500 mini-batches
                with torch.no_grad():              # with是一个上下文管理器
                    outputs = net(val_image)       # [batch, 10]
                    # 需要在输出的第1个维度上寻找最大值 即10个节点上  [1]表示只需要最大值的index
                    predict_y = torch.max(outputs, dim=1)[1]
                    # 预测 item()方法可以从tensor中拿到具体数值
                    accuracy = torch.eq(predict_y, val_label).sum().item() / val_label.size(0)

                    print('[%d, %5d] train_loss: %.3f  test_accuracy: %.3f' %
                          (epoch + 1, step + 1, running_loss / 500, accuracy))
                    print('%f s' % (time.perf_counter() - time_start))
                    running_loss = 0.0

    print('Finished Training')

    save_path = './Lenet.pth'
    # 保存网络所有参数
    torch.save(net.state_dict(), save_path)

3.predict

import torch
import torchvision.transforms as transforms
from PIL import Image

from Lenet_model import LeNet


def main():
    # 数据预处理
    transform = transforms.Compose(
        [transforms.Resize((32, 32)),    # 首先resize至和训练及图像一样的大小
         transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    # 导入要测试的图像
    im = Image.open('1.png')
    im = transform(im)  # [C, H, W]
    im = torch.unsqueeze(im, dim=0)  # [N, C, H, W] 对数据增加一个新的维度
    # 实例化网络
    net = LeNet()
    net.load_state_dict(torch.load('Lenet.pth'))
    # 预测标签
    classes = ('plane', 'car', 'bird', 'cat',
               'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

    with torch.no_grad():
        outputs = net(im)
        predict = torch.max(outputs, dim=1)[1].data.numpy()
    print(classes[int(predict)])


if __name__ == '__main__':
    main()
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值