首页 > 其他分享 >卷积神经网络理解(3)

卷积神经网络理解(3)

时间:2024-01-30 11:03:06浏览次数:26  
标签:nn 16 卷积 32 self torch 神经网络 理解

1、定义

LeNet是深度学习领域的一个经典卷积神经网络模型,由Yann LeCun等人于1998年提出,被广泛应用于手写数字识别和其他图像识别任务。

LeNet的网络结构相对简单,包含两个卷积层和三个全连接层,是卷积神经网络的基础。

LeNet对于现代的图像识别任务来说可能过于简单,但其对于深度学习的发展有着重要的贡献,是深度学习领域不可或缺的一部分。

总体来看,LeNet(LeNet-5)由两个部分组成:

卷积编码器:由两个卷积层组成;

全连接层密集块:由三个全连接层组成。

输入层:接收输入的图像数据,一般为灰度图或者RGB彩色图像。

第一个卷积层:对输入进行卷积操作,使用的卷积核的大小为5x5,输出通道数为6,不使用填充,步幅为1。

第一个池化层:对第一个卷积层的输出进行下采样,使用的窗口大小为2x2,步幅为2,池化方式为平均池化或最大池化。

第二个卷积层:对第一个池化层的输出进行卷积操作,使用的卷积核的大小为5x5,输出通道数为16,不使用填充,步幅为1。

第二个池化层:对第二个卷积层的输出进行下采样,使用的窗口大小为2x2,步幅为2,池化方式为平均池化或最大池化。

全连接层1:将第二个池化层的输出展开成向量,并经过一个全连接层,输出大小为120。

全连接层2:对第一层全连接层的输出进行处理,输出大小为84。

输出层:对第二层全连接层的输出进行处理,输出大小为分类任务的类别数目。

手写数字识别的架构如图所示。

             

 在此图示中,输入图片的尺寸为32*32,图示有误

C1层(卷积层):6@28×28
该层使用了6个卷积核,每个卷积核的大小为5×5,这样就得到了6个feature map(特征图)。
每个卷积核(5×5)与原始的输入图像(32×32)进行卷积,这样得到的feature map(特征图)大小为(32-5+1)×(32-5+1)= 28×28

S2层(下采样层,也称池化层):6@14×14
这一层主要是做池化或者特征映射(特征降维),池化单元为2×2,因此,6个特征图的大小经池化后即变为14×14。
回顾本文刚开始讲到的池化操作,池化单元之间没有重叠,在池化区域内进行聚合统计后得到新的特征值,因此经2×2池化后,每两行两列重新算出一个特征值出来,相当于图像大小减半,
因此卷积后的28×28图像经2×2池化后就变为14×14。 C3层(卷积层):16@10×10 C3层有16个卷积核,卷积模板大小为5×5。每个卷积核都与S2的6@14*14进行互关系运算,得到16个通道 与C1层的分析类似,C3层的特征图大小为(14-5+1)×(14-5+1)= 10×10 S4(下采样层,也称池化层):16@5×5 与S2的分析类似,池化单元大小为2×2,因此,该层与C3一样共有16个特征图,每个特征图的大小为5×5。 C5层(卷积层/全连接层):120 该层有120个卷积核,每个卷积核的大小仍为5×5,因此有120个特征图。由于S4层的大小为5×5,而该层的卷积核大小也是5×5,
因此特征图大小为(5-5+1)×(5-5+1)= 1×1。这样该层就刚好变成了全连接,这只是巧合,如果原始输入的图像比较大,则该层就不是全连接了。 F6层(全连接层):84 F6层有84个单元,之所以选这个数字的原因是来自于输出层的设计,对应于一个7×12的比特图。 OUTPUT层(输出层):10 Output层也是全连接层,共有10个节点,分别代表数字0到9。如果第i个节点的值为0,则表示网络识别的结果是数字i。

2、实现  

模型

 1 import torch
 2 from torch import nn
 3 from d2l import torch as d2l
 4 
 5 net = nn.Sequential(
 6     nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Sigmoid(),
 7     nn.AvgPool2d(kernel_size=2, stride=2),
 8     nn.Conv2d(6, 16, kernel_size=5), nn.Sigmoid(),
 9     nn.AvgPool2d(kernel_size=2, stride=2),
10     nn.Flatten(),
11     nn.Linear(16 * 5 * 5, 120), nn.Sigmoid(),
12     nn.Linear(120, 84), nn.Sigmoid(),
13     nn.Linear(84, 10))

或者是

 1 import torch.nn as nn
 2 import torch.nn.functional as F
 3 
 4 class LeNet(nn.Module):
 5     def __init__(self):
 6         super(LeNet, self).__init__()
 7         self.conv1 = nn.Conv2d(3, 16, 5) # in_channels=3 out_channels=16 kernel=5
 8         self.pool1 = nn.MaxPool2d(2, 2)
 9         self.conv2 = nn.Conv2d(16, 32, 5)
10         self.pool2 = nn.MaxPool2d(2, 2)
11         self.fc1 = nn.Linear(32*5*5, 120)
12         self.fc2 = nn.Linear(120, 84)
13         self.fc3 = nn.Linear(84, 10)
14     # 调用上面定义的函数
15     def forward(self, x):
16         x = F.relu(self.conv1(x))    # input(3, 32, 32) output(16, 28, 28)
17         x = self.pool1(x)            # output(16, 14, 14)
18         x = F.relu(self.conv2(x))    # output(32, 10, 10)
19         x = self.pool2(x)            # output(32, 5, 5)
20         x = x.view(-1, 32*5*5)       # output(32*5*5)
21         x = F.relu(self.fc1(x))      # output(120)
22         x = F.relu(self.fc2(x))      # output(84)
23         x = self.fc3(x)              # output(10)
24         return x

训练

 1 import torch
 2 import torchvision
 3 import torch.nn as nn
 4 
 5 from model import LeNet
 6 import torch.optim as optim
 7 import torchvision.transforms as transforms
 8 from torch.utils.data import DataLoader
 9 
10 def main():
11     transform = transforms.Compose(
12         [transforms.ToTensor(),
13          transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
14 
15     # 50000张训练图片
16     # 第一次使用时要将download设置为True才会自动去下载数据集
17     train_set = torchvision.datasets.CIFAR10(root='./data', train=True,
18                                              download=False, transform=transform)
19     train_loader = DataLoader(train_set, batch_size=36,
20                                                shuffle=True, num_workers=0)
21 
22     # 10000张验证图片
23     # 第一次使用时要将download设置为True才会自动去下载数据集
24     val_set = torchvision.datasets.CIFAR10(root='./data', train=False,
25                                            download=False, transform=transform)
26     val_loader = DataLoader(val_set, batch_size=5000,
27                                              shuffle=False, num_workers=0)
28     val_data_iter = iter(val_loader)
29     val_image, val_label = val_data_iter.next()
30 
31     # classes = ('plane', 'car', 'bird', 'cat',
32     #            'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
33 
34     # 定义模型和损失函数
35     net = LeNet()
36     loss_function = nn.CrossEntropyLoss()
37 
38     # 定义优化器
39     optimizer = optim.Adam(net.parameters(),lr=0.001)
40 
41     # 对训练集迭代5次
42     epochs = 5
43     for epoch in range(epochs):
44         running_loss = 0
45         for step,data in enumerate(train_loader,start=0): # step从start开始
46             inputs,labels = data
47             # 梯度清零
48             optimizer.zero_grad()
49 
50             outputs = net(inputs)
51             # 计算损失函数
52             loss = loss_function(outputs,labels)
53             # 反向传播并更新参数
54             loss.backward()
55             optimizer.step()
56 
57             running_loss += loss.item()
58             if step%500 == 499:
59                 with torch.no_grad():
60                     outputs = net(val_image)
61                     predict_y = torch.max(outputs,dim=1)[1]
62                     accuracy = (predict_y==val_label).sum().item() / val_label.size(0)
63                     print('[%d  %3d] train_loss: %.3f test_accuracy: %.3f' %
64                           (epoch+1,step+1,running_loss/500,accuracy))
65                     running_loss = 0
66 
67     print('Finished Training')
68     save_path = './Lenet.pth'
69     torch.save(net.state_dict(),save_path)
70 if __name__ == '__main__':
71     main()

这段代码是一个基于LeNet网络结构进行CIFAR10分类的训练代码,主要步骤如下:

导入必要的Python包,包括PyTorch中的torch、torchvision、torch.nn等模块,以及用于数据加载的DataLoader。
定义数据预处理,包括将图像转换为Tensor格式、标准化处理等操作。
加载训练集和验证集,使用DataLoader将数据分批次读取。
定义LeNet网络结构和损失函数,此处使用交叉熵损失函数。
定义Adam优化器。
进行训练,共进行5个epoch,每个epoch对训练集进行一次完整的遍历,每次遍历对数据分批次读取并进行网络的前向计算、反向传播、参数更新等操作。
每500个batch输出一次训练损失和测试精度。
保存训练好的模型参数。

测试

 1 import torch
 2 import torchvision.transforms as transforms
 3 from PIL import Image
 4 
 5 from model import LeNet
 6 
 7 
 8 def main():
 9     transform = transforms.Compose(
10         [transforms.Resize((32, 32)), # 对输入的图片尺寸进行调整
11          transforms.ToTensor(), # Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor. (H x W x C)->(C x H x W)
12          transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
13 
14     classes = ('plane', 'car', 'bird', 'cat',
15                'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
16     
17     net = LeNet()
18     net.load_state_dict(torch.load('Lenet.pth')) # 加载模型
19 
20     im = Image.open('data/plane.jpg')
21     im = transform(im)  # [C, H, W]
22     # 增加一个维度,batch
23     im = torch.unsqueeze(im, dim=0)  # [N, C, H, W] 增加一个batch维度
24 
25     with torch.no_grad():
26         outputs = net(im)
27         predict = torch.max(outputs, dim=1)[1].numpy()
28     print(classes[int(predict)])
29 
30 if __name__ == '__main__':
31     main()

 

 

标签:nn,16,卷积,32,self,torch,神经网络,理解
From: https://www.cnblogs.com/Zhouce/p/17996677

相关文章

  • NSQ理解
    最近实习需用到了NSQ消息队列,这里贴一点简单的介绍和学习资料,方便日后查阅。目录简介NSQ是一个基于Go语言的分布式实时消息平台,它基于MIT开源协议发布,由bitly公司开源出来的一款简单易用的消息中间件。NSQ可用于大规模系统中的实时消息服务,并且每天能够处理数亿级别的消息,......
  • 卷积神经网络理解(二)
    1、卷积神经网络的特点卷积神经网络相对于普通神经网络在于以下四个特点:局部感知域:CNN的神经元只与输入数据的一小部分区域相连接,这使得CNN对数据的局部结构具有强大的敏感性,可以自动学习到图像的特征。参数共享:在CNN中,同一个卷积核(filter)在整个输入图像上滑动,共享权重和偏置......
  • 深入理解 C# 编程:枚举、文件处理、异常处理和数字相加
    C#枚举枚举是一个特殊的“类”,表示一组常量(不可更改/只读变量)。要创建枚举,请使用enum关键字(而不是class或interface),并用逗号分隔枚举项:enumLevel{Low,Medium,High}您可以使用点语法访问枚举项:LevelmyVar=Level.Medium;Console.WriteLine(myVar);Enu......
  • 深入理解 C# 编程:枚举、文件处理、异常处理和数字相加
    C#枚举枚举是一个特殊的“类”,表示一组常量(不可更改/只读变量)。要创建枚举,请使用enum关键字(而不是class或interface),并用逗号分隔枚举项:enumLevel{Low,Medium,High}您可以使用点语法访问枚举项:LevelmyVar=Level.Medium;Console.WriteLine(myVar);En......
  • 深入理解 Flink(六)Flink Job 提交和 Flink Graph 详解
    FlinkProgram编程套路回顾1、获取执行环境对象StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();2、通过执行环境对象,注册数据源Source,得到数据抽象DataStreamds=env.socketTextStream(...)3、调用数据抽象的各种Transformation......
  • 理解Set集合数据结构
    一、Set的基本概念Set是一种包含不重复元素的集合。与List(列表)不同,Set中的元素是无序的,不能通过索引来访问。Set中的每个元素都是唯一的,重复的元素将被自动剔除。二、Set的常见操作1.添加元素:使用add()方法向Set中添加新元素。如果添加的元素已经存在于Set中,则不会有任何改变......
  • Kotlin扩展函数原理解析
    一、扩展函数扩展函数可以方便地给现有类增加属性和方法而不改动类地代码。二、原理funString.addTo(s:String):String{returnthis+s}反编译:@Metadata(mv={1,6,0},k=2,d1={"\u0000\n\n\u0000\n\u0002\u0010\u000e\n\u0002\b\u0002\u001a\u......
  • 卷积神经网络详解+Python实现卷积神经网络Cifar10彩色图片分类
    原文链接:https://blog.csdn.net/master_hunter/article/details/133156758卷积神经网络相对于普通神经网络在于以下四个特点:局部感知域:CNN的神经元只与输入数据的一小部分区域相连接,这使得CNN对数据的局部结构具有强大的敏感性,可以自动学习到图像的特征。参数共享:在CNN中,同一个......
  • 对于计算机体系结构的理解
    计算机体系结构是指根据属性和功能不同而划分的计算机理论组成部分及计算机基本工作原理、理论的总称。它包括计算机的软、硬件的系统结构,有两方面的含义:一是从程序设计者的角度所见的系统结构,研究计算机体系的概念性结构和功能特性,关系到软件设计的特性;二是从硬件设计者的角度所......
  • 一个例子形象地理解同步与异步
    请看一个示例:同步方式请求接口请求一次接口耗时大约100多毫秒代码一个for循环,循环500次,调用方法Request,Request方法中一个while(true)无限循环,同步方式请求url获取数据。代码点评:要是写一个while(true)没问题,这是想运行500个while(true),这代码是错误的,行不通。应该使用Thread或者T......