大家好,我是红色石头!

在上两篇文章:

这可能是神经网络 LeNet-5 最详细的解释了!

我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)!

详细介绍了卷积神经网络 LeNet-5 的理论部分和使用 PyTorch 复现 LeNet-5 网络来解决 MNIST 数据集的识别问题。今天我们将使用 Pytorch 来继续实现 LeNet-5 模型,并用它来解决 CIFAR10 数据集的识别。

正文开始!

二、使用LeNet-5网络结构创建CIFAR-10识别分类器

LeNet-5 网络本是用来识别 MNIST 数据集的,下面我们来将 LeNet-5 应用到一个比较复杂的例子,识别 CIFAR-10 数据集。

CIFAR-10 是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集。一共包含 10 个类别的 RGB 彩色图 片:飞机( airlane )、汽车( automobile )、鸟类( bird )、猫( cat )、鹿( deer )、狗( dog )、蛙类( frog )、马( horse )、船( ship )和卡车( truck )。图片的尺寸为 32×32 ,数据集中一共有 50000 张训练圄片和 10000 张测试图片。

CIFAR-10 的图片样例如图所示。

2.1 下载并加载数据,并做出一定的预先处理

pipline_train = transforms.Compose([#随机旋转图片transforms.RandomHorizontalFlip(),#将图片尺寸resize到32x32transforms.Resize((32,32)),#将图片转化为Tensor格式transforms.ToTensor(),#正则化(当模型出现过拟合的情况时,用来降低模型的复杂度)transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
pipline_test = transforms.Compose([#将图片尺寸resize到32x32transforms.Resize((32,32)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])
#下载数据集
train_set = datasets.CIFAR10(root="./data/CIFAR10", train=True, download=True, transform=pipline_train)
test_set = datasets.CIFAR10(root="./data/CIFAR10", train=False, download=True, transform=pipline_test)
#加载数据集
trainloader = torch.utils.data.DataLoader(train_set, batch_size=64, shuffle=True)
testloader = torch.utils.data.DataLoader(test_set, batch_size=32, shuffle=False)
# 类别信息也是需要我们给定的
classes = ('plane', 'car', 'bird', 'cat','deer', 'dog', 'frog', 'horse', 'ship', 'truck')

2.2 搭建 LeNet-5 神经网络结构,并定义前向传播的过程

LeNet-5 网络上文已经搭建过了,由于 CIFAR10 数据集图像是 RGB 三通道的,因此 LeNet-5 网络 C1 层卷积选择的滤波器需要 3 通道,网络其它结构跟上文都是一样的。

class LeNetRGB(nn.Module):def __init__(self):super(LeNetRGB, self).__init__()self.conv1 = nn.Conv2d(3, 6, 5)   # 3表示输入是3通道self.relu = nn.ReLU()self.maxpool1 = nn.MaxPool2d(2, 2)self.conv2 = nn.Conv2d(6, 16, 5)self.maxpool2 = nn.MaxPool2d(2, 2)self.fc1 = nn.Linear(16*5*5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):x = self.conv1(x)x = self.relu(x)x = self.maxpool1(x)x = self.conv2(x)x = self.maxpool2(x)x = x.view(-1, 16*5*5)x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)output = F.log_softmax(x, dim=1)return output

2.3 将定义好的网络结构搭载到 GPU/CPU,并定义优化器

使用 SGD(随机梯度下降)优化,学习率为 0.001,动量为 0.9。

#创建模型,部署gpu
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = LeNetRGB().to(device)
#定义优化器
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)

2.4 定义训练过程

def train_runner(model, device, trainloader, optimizer, epoch):#训练模型, 启用 BatchNormalization 和 Dropout, 将BatchNormalization和Dropout置为Truemodel.train()total = 0correct =0.0#enumerate迭代已加载的数据集,同时获取数据和数据下标for i, data in enumerate(trainloader, 0):inputs, labels = data#把模型部署到device上inputs, labels = inputs.to(device), labels.to(device)#初始化梯度optimizer.zero_grad()#保存训练结果outputs = model(inputs)#计算损失和#多分类情况通常使用cross_entropy(交叉熵损失函数), 而对于二分类问题, 通常使用sigmodloss = F.cross_entropy(outputs, labels)#获取最大概率的预测结果#dim=1表示返回每一行的最大值对应的列下标predict = outputs.argmax(dim=1)total += labels.size(0)correct += (predict == labels).sum().item()#反向传播loss.backward()#更新参数optimizer.step()if i % 1000 == 0:#loss.item()表示当前loss的数值print("Train Epoch{} \t Loss: {:.6f}, accuracy: {:.6f}%".format(epoch, loss.item(), 100*(correct/total)))Loss.append(loss.item())Accuracy.append(correct/total)return loss.item(), correct/total

2.5 定义测试过程

def test_runner(model, device, testloader):#模型验证, 必须要写, 否则只要有输入数据, 即使不训练, 它也会改变权值#因为调用eval()将不启用 BatchNormalization 和 Dropout, BatchNormalization和Dropout置为Falsemodel.eval()#统计模型正确率, 设置初始值correct = 0.0test_loss = 0.0total = 0#torch.no_grad将不会计算梯度, 也不会进行反向传播with torch.no_grad():for data, label in testloader:data, label = data.to(device), label.to(device)output = model(data)test_loss += F.cross_entropy(output, label).item()predict = output.argmax(dim=1)#计算正确数量total += label.size(0)correct += (predict == label).sum().item()#计算损失值print("test_avarage_loss: {:.6f}, accuracy: {:.6f}%".format(test_loss/total, 100*(correct/total)))

2.6 运行

#调用
epoch = 20
Loss = []
Accuracy = []
for epoch in range(1, epoch+1):print("start_time",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))loss, acc = train_runner(model, device, trainloader, optimizer, epoch)Loss.append(loss)Accuracy.append(acc)test_runner(model, device, testloader)print("end_time: ",time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())),'\n')print('Finished Training')
plt.subplot(2,1,1)
plt.plot(Loss)
plt.title('Loss')
plt.show()
plt.subplot(2,1,2)
plt.plot(Accuracy)
plt.title('Accuracy')
plt.show()

经历 20 次 epoch 迭代训练之后:

start_time 2021-11-27 22:29:09
Train Epoch20 Loss: 0.659028, accuracy: 68.750000%
test_avarage_loss: 0.030969, accuracy: 67.760000%
end_time:  2021-11-27 22:29:44

训练集的 loss 曲线和 Accuracy 曲线变化如下:

2.7 保存模型

print(model)
torch.save(model, './models/model-cifar10.pth') #保存模型

LeNet-5 的模型会 print 出来,并将模型模型命令为 model-cifar10.pth 保存在固定目录下。

LeNetRGB((conv1): Conv2d(3, 6, kernel_size=(5, 5), stride=(1, 1))(relu): ReLU()(maxpool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(conv2): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))(maxpool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(fc1): Linear(in_features=400, out_features=120, bias=True)(fc2): Linear(in_features=120, out_features=84, bias=True)(fc3): Linear(in_features=84, out_features=10, bias=True)
)

2.8 模型测试

利用刚刚训练的模型进行 CIFAR10 类型图片的测试。

from PIL import Image
import numpy as npif __name__ == '__main__':device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model = torch.load('./models/model-cifar10.pth') #加载模型model = model.to(device)model.eval()    #把模型转为test模式#读取要预测的图片# 读取要预测的图片img = Image.open("./images/test_cifar10.png").convert('RGB') # 读取图像#img.show()plt.imshow(img) # 显示图片plt.axis('off') # 不显示坐标轴plt.show()# 导入图片,图片扩展后为[1,1,32,32]trans = transforms.Compose([#将图片尺寸resize到32x32transforms.Resize((32,32)),transforms.ToTensor(),transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])img = trans(img)img = img.to(device)img = img.unsqueeze(0)  #图片扩展多一维,因为输入到保存的模型中是4维的[batch_size,通道,长,宽],而普通图片只有三维,[通道,长,宽]# 预测 classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')output = model(img)prob = F.softmax(output,dim=1) #prob是10个分类的概率print("概率:",prob)print(predict.item())value, predicted = torch.max(output.data, 1)predict = output.argmax(dim=1)pred_class = classes[predicted.item()]print("预测类别:",pred_class)

输出:

概率:tensor([[7.6907e-01, 3.3997e-03, 4.8003e-03, 4.2978e-05, 1.2168e-02, 6.8751e-06, 3.2019e-06, 1.6024e-04, 1.2705e-01, 8.3300e-02]],
grad_fn=<SoftmaxBackward>)
5
预测类别:plane

模型预测结果正确!

以上就是 PyTorch 构建 LeNet-5 卷积神经网络并用它来识别 CIFAR10 数据集的例子。全文的代码都是可以顺利运行的,建议大家自己跑一边。

值得一提的是,针对 MNIST 数据集和 CIFAR10 数据集,最大的不同就是 MNIST 是单通道的,CIFAR10 是三通道的,因此在构建 LeNet-5 网络的时候,C1层需要做不同的设置。至于输入图片尺寸不一样,我们可以使用 transforms.Resize 方法统一缩放到 32x32 的尺寸大小。

所有完整的代码我都放在 GitHub 上,GitHub地址为:

https://github.com/RedstoneWill/ObjectDetectionLearner/tree/main/LeNet-5

也可以点击阅读原文进入~


推荐阅读

(点击标题可跳转阅读)

干货 | 公众号历史文章精选

我的深度学习入门路线

我的机器学习入门路线图

重磅

AI有道年度技术文章电子版PDF来啦!

扫描下方二维码,添加 AI有道小助手微信,可申请入群,并获得2020完整技术文章合集PDF(一定要备注:入群 + 地点 + 学校/公司。例如:入群+上海+复旦

长按扫码,申请入群

(添加人数较多,请耐心等待)

感谢你的分享,点赞,在看三  

我用 PyTorch 复现了 LeNet-5 神经网络(CIFAR10 数据集篇)!相关推荐

  1. 【小白学习PyTorch教程】六、基于CIFAR-10 数据集,使用PyTorch 从头开始​​构建图像分类模型...

    「@Author:Runsen」 图像识别本质上是一种计算机视觉技术,它赋予计算机"眼睛",让计算机通过图像和视频"看"和理解世界. 在开始阅读本文之前,建议先 ...

  2. 【小白学习PyTorch教程】六、基于CIFAR-10 数据集,使用PyTorch 从头开始​​构建图像分类模型

    @Author:Runsen 图像识别本质上是一种计算机视觉技术,它赋予计算机"眼睛",让计算机通过图像和视频"看"和理解世界. 在开始阅读本文之前,建议先了解 ...

  3. 【深度学习】我用 PyTorch 复现了 LeNet-5 神经网络(CIFAR10 数据集篇)!

    今天我们将使用 Pytorch 来继续实现 LeNet-5 模型,并用它来解决 CIFAR10 数据集的识别. 正文开始! 二.使用LeNet-5网络结构创建CIFAR-10识别分类器 LeNet-5 ...

  4. 我用 PyTorch 复现了 LeNet-5 神经网络(自定义数据集篇)!

    大家好,我是红色石头! 在上三篇文章: 这可能是神经网络 LeNet-5 最详细的解释了! 我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)! 我用 PyTorch ...

  5. 【深度学习】我用 PyTorch 复现了 LeNet-5 神经网络(自定义数据集篇)!

    在上三篇文章: 这可能是神经网络 LeNet-5 最详细的解释了! 我用 PyTorch 复现了 LeNet-5 神经网络(MNIST 手写数据集篇)! 我用 PyTorch 复现了 LeNet-5 ...

  6. Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet、AlexNet、VGG、NIN、GoogleNet、ResNet)——从代码认知CNN经典架构

    Pytorch之CNN:基于Pytorch框架实现经典卷积神经网络的算法(LeNet.AlexNet.VGG.NIN.GoogleNet.ResNet)--从代码认知CNN经典架构 目录 CNN经典算 ...

  7. 深度学习入门之PyTorch学习笔记:卷积神经网络

    深度学习入门之PyTorch学习笔记 绪论 1 深度学习介绍 2 深度学习框架 3 多层全连接网络 4 卷积神经网络 4.1 主要任务及起源 4.2 卷积神经网络的原理和结构 4.2.1 卷积层 1. ...

  8. 快速入门PyTorch(2)--如何构建一个神经网络

    2019 第 43 篇,总第 67 篇文章 本文大约 4600 字,阅读大约需要 10 分钟 快速入门 PyTorch 教程第二篇,这篇介绍如何构建一个神经网络.上一篇文章: 快速入门Pytorch( ...

  9. 深度学习:使用pytorch训练cifar10数据集(基于Lenet网络)

    文档基于b站视频:https://www.bilibili.com/video/BV187411T7Ye 流程 model.py --定义LeNet网络模型 train.py --加载数据集并训练,训 ...

最新文章

  1. 中文文本挖掘预处理流程总结
  2. List扩展方法出错,this关键词出错,解决方案
  3. java jsoup解析html标签_jsoup解析html
  4. BeagleBone Black QNX6.6 BSP中IPL的完善
  5. MySQL查询对NULL的处理
  6. 数据结构:用栈实现中缀表达式的求值(文字描述+详细步骤示例)
  7. SAP Spartacus开启SSR服务器端渲染之后,和默认客户端渲染的差异比较
  8. Sentinel 分布式系统的流量防卫兵
  9. 大家都为什么考博?采访了12名考生,发现最主要原因竟是这个
  10. YAFFS2移植到AliOS Things指南
  11. SSM+easyUI(框架的搭建)
  12. 坐等价格!小米Civi今日下午发布:女性用户青睐之选
  13. Qt实践录:非窗体代码片段
  14. 读书笔记 《TAOCP》 V1 S1.2
  15. 【181129】VC++ 屏幕截取(窗口截图、选区截图)、屏幕拾色器、放大镜源代码
  16. SLT 定义vetctor对象,vector构造函数
  17. Fiori学习:WEBIDE本地个人版安装
  18. 华东院进入华为智慧战略 其他院怎么办
  19. element ui el-table单元格按需合并
  20. 盘丝洞服务器维护,梦幻西游:明日维护公告解读!盘丝法宝调整,新增人物志玩法!...

热门文章

  1. cocos2d CCNode类(节点属性大全)
  2. 细节优化提升资源利用率
  3. Linux HOOK
  4. oracle 定时任务 job 调用存储过程有回到输出参数(含out参数)
  5. SSD固态存储大观(二)
  6. 第五届河南省大学生程序设计竞赛 题解
  7. zoj - 3502 Contest
  8. hud-1495--非常可乐 VS nyoj-21--三个水杯
  9. 动态规划之矩阵连乘讲解
  10. Zero-shot Learning / One-shot Learning / Few-shot Learning