CNN卷积神经网络02--LeNet训练CIFAR10

目录

数据集准备(下载)

数据集加载(dataloader)

训练过程代码

相关链接


数据集准备(下载)

CIFAR-10数据集由10个类别的60000张32x32彩色图像组成,每个类别有6000张图像。有50000个训练图像和10000个测试图像。

使用torchvision自带的数据集

 # 定义图像的预处理方法
    transform = transforms.Compose(
        [
            transforms.ToTensor(),
            transforms.Normalize(
                mean=(0.5, 0.5, 0.5),
                std=(0.5, 0.5, 0.5),
            )
        ]
    )
    train_set = torchvision.datasets.CIFAR10(
        root=r'D:\Cproject\ex001\CIFAR10',  # 如果下载,下载的位置,也可以手动下载,放到这个位置来
        train=True,
        download=False,   # 下载地址  https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
        transform=transform
    )

transform.Compose()是网络加载数据集的时候对图像进行预处理操作的处理流程的打包

例子中先是把加载的图像转成Tensor,并且调整hwc为chw格式,然后执行一个归一化操作在标准化处理(rgb灰度值/255得到0-1,再减去0.5(均值) 再 除以0.5(标准差)) 对原始数据归一化及标准化有助于网络的训练收敛

此处的均值及标准差是先验的,是统计的结果,人为设定的,并不是训练网络必须要使用这个参数,重要的是要理解标准化的数据对于训练的帮助

比如 ImageNet  图像常用的参数为mean=(0.485, 0.456, 0.406),std=(0.229, 0.224, 0.225)。而对于特定的数据集,选择这个值结果可能并不理想

注意如果手动下载,要把压缩包手动解压,并正确组织目录

例如

数据集加载(dataloader)

实例化Dataset后就可以实例化Dataloader了 

from torch.utils.data import DataLoader

 dataloader = DataLoader(
        dataset=train_set,  # 指定从哪个数据集实例中加载
        batch_size=4,
        shuffle=True,  # 是否打乱顺序,训练一般开启,保证数据加载的随机性
        num_workers=0,  # 加载具体数据的时候工作线程数,因为一般读数据设计到大量io操作,比较耗时多线程加载可以加快速度,win下有bug
    )

batchsize的选择可以根据硬件来设置(显存),尽可能大一些

创建完dataloader对象后,就可以使用for i in dataloader:..语句从中得到每一个批次的数据了

也可以使用iter(dataloader)封装成一个迭代器,使用next()直接获取一组数据进行展示

dataiter = iter(dataloader)
images,labels = next(dataiter)

next(dataiter)语句的返回值和Dataset中的__getitem__()方法有关,

在CIFAR10中相关代码如下

可以看到返回给我们的数据实际上是经过了一些变换(transform)的数据,

为了展示,对其进行还原

对于图像的数据 4,3,32,32 表示的是4张样本图片,3通道,高宽都是32

对于label的数据 表示4个样本的类别索引(标签索引的含义可以通过train_set.classes获取)

使用

imgs torchvision.utils.make_grid(images)  把多张样本组合成一张图片

def im_show(img):
    img = img / 2 + 0.5  # 反标准化过程,处理完后值的范围为0-1
    npimg = img.numpy()  # tensor->numpy
    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # chw->hwc
    plt.show()

再调用im_show(imgs)展示

关于Dataset/Dataloader将整理在另一篇博客中

https://blog.csdn.net/zyy_0724/article/details/134724701

训练过程代码

训练代码的主要组织结构为

网络加载,损失函数反向传播优化器的设置,按batchsize取出数据,进行前向传播,计算损失,反向传播更新网络,评估代码,日志代码,保存网络等

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

from net import LeNet


def main():
    # 定义图像的预处理方法
    transform = transforms.Compose(
        [
            transforms.ToTensor(),
            transforms.Normalize(
                mean=(0.5, 0.5, 0.5),
                std=(0.5, 0.5, 0.5),
            )
        ]
    )
    train_set = torchvision.datasets.CIFAR10(
        root=r'D:\Cproject\ex001\CIFAR10',  # 如果下载,下载的位置,也可以手动下载,放到这个位置来
        train=True,
        download=False,  # 下载地址  https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
        transform=transform
    )
    train_dataloader = DataLoader(
        dataset=train_set,  # 指定从哪个数据集实例中加载
        batch_size=128,
        shuffle=True,  # 是否打乱顺序,训练一般开启,保证数据加载的随机性
        num_workers=0,  # 加载具体数据的时候工作线程数,因为一般读数据设计到大量io操作,比较耗时多线程加载可以加快速度,win下有bug
    )
    test_set = torchvision.datasets.CIFAR10(
        root=r'D:\Cproject\ex001\CIFAR10',  # 如果下载,下载的位置,也可以手动下载,放到这个位置来
        train=False,
        download=False,  # 下载地址  https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
        transform=transform
    )
    test_dataloader = DataLoader(
        dataset=test_set,  # 指定从哪个数据集实例中加载
        batch_size=128,
        shuffle=False,  # 是否打乱顺序,训练一般开启,保证数据加载的随机性
        num_workers=0,  # 加载具体数据的时候工作线程数,因为一般读数据设计到大量io操作,比较耗时多线程加载可以加快速度,win下有bug
    )
    # show_example(dataloader)

    model = LeNet(10)  # 实例化网络对象
    loss_function = nn.BCEWithLogitsLoss()  # 损失函数
    optimizer = optim.Adam(params=model.parameters(), lr=0.01)  # 优化器
    epochs = 100
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')  # 选择算法计算的硬件设置
    model = model.to(device)

    for epoch in range(epochs):
        running_loss = []
        training_acc = []
        # train
        model.train()
        for step, (images, labels) in enumerate(train_dataloader):
            images = images.to(device)
            labels = labels.to(device)
            labels = torch.nn.functional.one_hot(labels, num_classes=10).to(torch.float32)  # 对label进行onehot编码
            outputs = model(images)  # 网络前向传播
            loss = loss_function(outputs, labels)  # 计算损失

            optimizer.zero_grad()  # 优化器梯度清零
            loss.backward()  # 计算梯度
            optimizer.step()  # 更新网络权重
            running_loss.append(loss.detach().cpu().item())  # 保存当前 batch 的损失记录
            predict_y = torch.max(outputs, dim=1)[1]
            labels = torch.max(labels, dim=1)[1]
            training_acc.extend((predict_y == labels).cpu().numpy().tolist())  # 保存当前 batch 预测的正确性的记录
        # test
        testing_loss = []
        testing_acc = []
        model.eval()
        with torch.no_grad():
            for step, (images, labels) in enumerate(test_dataloader):
                images = images.to(device)
                labels = labels.to(device)
                labels = torch.nn.functional.one_hot(labels, num_classes=10).to(torch.float32)  # 对label进行onehot编码
                outputs = model(images)  # 网络前向传播
                loss = loss_function(outputs, labels)  # 计算损失
                testing_loss.append(loss.detach().cpu().item())  # 保存当前 batch 的损失记录
                predict_y = torch.max(outputs, dim=1)[1]
                labels = torch.max(labels, dim=1)[1]
                testing_acc.extend((predict_y == labels).cpu().numpy().tolist())   # 保存当前 batch 预测的正确性的记录

        # print log
        print(
            f'epoch:{epoch}/{epochs}  '
            f'train_loss:{sum(running_loss) / len(running_loss):.3f}  '
            f'test_loss:{sum(testing_loss) / len(testing_loss):.3f}  '
            f'train_acc:{sum(training_acc) / len(training_acc):.3f}  '
            f'test_acc:{sum(testing_acc) / len(testing_acc):.3f}  '
        )

    torch.save(model.state_dict(), 'model.pth')
    return 0


def show_example(dataloader):
    dataiter = iter(dataloader)
    images, labels = next(dataiter)
    imgs = torchvision.utils.make_grid(images)
    im_show(imgs)


def im_show(img):
    img = img / 2 + 0.5  # 反标准化过程,处理完后值的范围为0-1
    npimg = img.numpy()  # tensor->numpy
    plt.imshow(np.transpose(npimg, (1, 2, 0)))  # chw->hwc
    plt.show()


if __name__ == '__main__':
    main()

相关链接

pytorch Dataset/Dataloader

pytorch 损失函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值