首页 > 其他分享 >6.6 实现卷积神经网络LeNet训练并预测手写体数字

6.6 实现卷积神经网络LeNet训练并预测手写体数字

时间:2023-08-07 15:32:16浏览次数:44  
标签:nn torch 6.6 shape train device LeNet 手写体 net

模型架构

6.6 实现卷积神经网络LeNet训练并预测手写体数字_初始化

6.6 实现卷积神经网络LeNet训练并预测手写体数字_权重_02

代码实现

import torch
from torch import nn
from d2l import torch as d2l
net = nn.Sequential(
    nn.Conv2d(1,6,kernel_size=5,padding=2),nn.Sigmoid(),#padding=2补偿5x5卷积核导致的特征减少。
    nn.AvgPool2d(kernel_size=2,stride=2),
    nn.Conv2d(6,16,kernel_size=5),nn.Sigmoid(),
    nn.AvgPool2d(kernel_size=2,stride=2),
    nn.Flatten(),
    nn.Linear(16*5*5,120),nn.Sigmoid(),
    nn.Linear(120,84),nn.Sigmoid(),
    nn.Linear(84,10)
)
'''定义X,并打印模型的形状'''
# 第一个参数是样本
X = torch.rand(size=(1,1,28,28),dtype=torch.float32)
for layer in net:
    X = layer(X)
    print(layer.__class__.__name__,'output shape: \t',X.shape)
# 输出如下:
Conv2d output shape: 	 torch.Size([1, 6, 28, 28])
Sigmoid output shape: 	 torch.Size([1, 6, 28, 28])
AvgPool2d output shape: 	 torch.Size([1, 6, 14, 14])
Conv2d output shape: 	 torch.Size([1, 16, 10, 10])
Sigmoid output shape: 	 torch.Size([1, 16, 10, 10])
AvgPool2d output shape: 	 torch.Size([1, 16, 5, 5])
Flatten output shape: 	 torch.Size([1, 400])
Linear output shape: 	 torch.Size([1, 120])
Sigmoid output shape: 	 torch.Size([1, 120])
Linear output shape: 	 torch.Size([1, 84])
Sigmoid output shape: 	 torch.Size([1, 84])
Linear output shape: 	 torch.Size([1, 10])
'''定义训练批次并加载训练集和测试集'''
batch_size = 256
# 按照batch_size把数据集取出来。取出来之后是放到内存中的,后面要把它加载到GPU中
train_iter,test_iter = d2l.load_data_fashion_mnist(batch_size=batch_size)
# 计算预测正确的个数
def accuracy(y_hat,y):
    '''计算预测正确的数量'''
    if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
        # y_hat是下标表示类别,值是该类别的概率。模型结果是预测10个类的概率,谁的概率最大,就取谁的下标
        y_hat = y_hat.argmax(axis=1)
    #  y_hat.type(y.dtype):因为==对数据类型很敏感,因此我们将y_hat的数据类型转换为与y的数据类型一致。
    #  y_hat.type(y.dtype) == y,将预测值y_hat与真实值y比较,返回一个包含 0和1的张量,赋值给cam,最后求和会得到正确预测的数量。
    cam = y_hat.type(y.dtype) == y
    return float(cam.type(y.dtype).sum())
def evaluate_accuracy_gpu(net,data_iter,device=None):
    if isinstance(net,nn.Module):
        net.eval() # 将模型设置为评估模式
        if not device:
            '''
                iter(net.parameters())是将参数集合转换为迭代器,并获取其中的第一个元素
                next(iter(net.parameters())).device ,指取到net.parameters()的第一个元素,获取该元素的设备。
            '''
            device = next(iter(net.parameters())).device
        # Accumulator用于对多个变量进行累加,d2l.Accumulator(2) 是在Accumulator实例中创建了2个变量,分别用于存储正确预测的数量和预测的总数量。当我们遍历数据集时,两者都随着时间的推移而累加。
        metric = d2l.Accumulator(2) # 正确预测数,预测总数
        with torch.no_grad():
            for X,y in data_iter:
                if isinstance(X,list): # 详见文章最下面的补充内容
                    X = [x.to(device) for x in X] # 令X使用设备device
                else:
                    X = X.to(device)
                y = y.to(device)
                # y.numel()是批次中样本的数量,accuracy(net(X),y)是用于计算模型在输入数据X上的输出结果与标签Y之间的准确率。
                # metric.add函数将正确预测的数量 和 样本数量作为参数传递进去,用于记录和累计这些指标的值。
                metric.add(accuracy(net(X),y),y.numel())
        return metric[0]/metric[1] # 返回准确率,其中metric[0]存放的是正确预测的个数,metric[1]存放的是样本数量,
def train_ch6(net,train_iter,test_iter,num_epochs,lr,device):
    def init_weights(m):
        if type(m) == nn.Linear or type(m) == nn.Conv2d: # 对神经网络中的线性层和卷积层的权重进行初始化
            nn.init.xavier_uniform_(m.weight) #用于初始化权重的函数,
    net.apply(init_weights)
    print('training on',device)
    net.to(device) # 设置模型使用device
    optimizer = torch.optim.SGD(net.parameters(),lr=lr)
    loss = nn.CrossEntropyLoss()
    '''
        该代码创建了一个名为animator的动画器,用于在训练过程中可视化损失函数和准确率的变化情况
    '''
    animator = d2l.Animator(xlabel='epoch',xlim=[1,num_epochs],legend=['train loss','train acc','test acc'])
    timer,num_batches = d2l.Timer(),len(train_iter)
    for epoch in range(num_epochs):
        # 创建 Accumulator类,统计训练损失之和,正确预测个数之和,样本数
        metric = d2l.Accumulator(3)
        net.train()
        for i,(X,y) in enumerate(train_iter):
            timer.start()
            optimizer.zero_grad()
            X,y = X.to(device),y.to(device)
            y_hat = net(X)
            l = loss(y_hat,y)
            l.backward()
            optimizer.step()
            with torch.no_grad():
                metric.add(l*X.shape[0], d2l.accuracy(y_hat,y), X.shape[0])
            timer.stop()
            train_l = metric[0] / metric[2] # 损失之和 / 样本数
            train_acc = metric[1] / metric[2] # 正确预测个数 / 样本数
            if (i+1) % (num_batches//5)==0 or i == num_epochs-1:
                animator.add(epoch + (i+1)/num_epochs,(train_l,train_acc,None))
        test_acc = evaluate_accuracy_gpu(net,test_iter)
        animator.add(epoch+1,(None,None,test_acc))
    print(f'loss {train_l:.3f}, train acc {train_acc:.3f}, '
          f'test acc {test_acc:.3f}')
    print(f'{metric[2] * num_epochs / timer.sum():.1f} examples/sec '
          f'on {str(device)}')
# 定义学习率和批次 开始训练
lr,num_epochs = 0.9,10
train_ch6(net,train_iter,test_iter,num_epochs,lr,d2l.try_gpu())

6.6 实现卷积神经网络LeNet训练并预测手写体数字_初始化_03

使用训练好的模型进行预测

y_hat = net(x)

补充:

isinstance(net,nn.Module)

isinstance(net,nn.Module)是Python的内置函数,用于判断一个对象是否属于制定类或其子类的实例。如果net是nn.Module类或子类的实例,那么表达式返回True,否则返回False. nn.Module是pytorch中用于构建神经网络模型的基类,其他神经网络都会继承它,因此使用 isinstance(net,nn.Module),可以确定Net对象是否为一个有效的神经网络模型。

`nn.init.xavier_uniform_(m.weight)

nn.init.xavier_uniform_(m.weight) 是一个用于初始化权重的函数,采用的是 Xavier 均匀分布初始化方法。

在神经网络中,权重的初始化非常重要,合适的初始化可以帮助网络更好地学习和收敛。Xavier 初始化方法是一种常用的权重初始化方法之一,旨在使权重在前向传播过程中保持方差不变。

具体而言,nn.init.xavier_uniform_() 函数会对输入的权重张量 m.weight 进行操作,将其初始化为一个均匀分布中的随机值。这个均匀分布的范围根据权重张量的形状进行调整,以保持前向传播过程中特征的方差稳定。

通过使用 Xavier 初始化方法,可以加速神经网络的训练过程,并且有助于避免梯度消失或梯度爆炸等问题。

标签:nn,torch,6.6,shape,train,device,LeNet,手写体,net
From: https://blog.51cto.com/u_16207976/6994350

相关文章

  • GoogLeNet网络——pytorch版
    importtorchfromtorchimportnnfromtorch.nnimportfunctionalasFfromd2limporttorchasd2lclassInception(nn.Module):#c1-c4是每条路径的输出通道数def__init__(self,in_channels,c1,c2,c3,c4,**kwargs):super(Inception,self).__init__(......
  • LeNet卷积神经网络——pytorch版
    importtorchfromtorchimportnnfromd2limporttorchasd2lclassReshape(torch.nn.Module):defforward(self,x):#批量大小默认,输出通道为1returnx.view(-1,1,28,28)net=torch.nn.Sequential(#28+4-5+1=28输出通道为6Reshape()......
  • 卷积神经网络(LeNet)
    卷积神经网络(LeNet)卷积神经网络(LeNet)tensorflow..... pytorch实现LeNet5......
  • MobileNetV2 :Inverted Residuals and Linear Bottlenecks
    论文链接|https://arxiv.org/abs/1704.04861论文源码|https://github.com/Randl/MobileNet2-pytorch/摘要:介绍了一种新的移动端架构——MobileNetV2,其在多任务和基准以及不同模型大小的范围上进一步刷新了移动端模型的当前最佳性能。介绍了如何通过全新框架SSDLite将这......
  • 6.6 卷积神经网络LeNet
    LeNet,它是最早发布的卷积神经网络之一,因其在计算机视觉任务中的高效性能而受到广泛关注。这个模型是由AT&T贝尔实验室的研究员YannLeCun在1989年提出的(并以其命名),目的是识别图像中的手写数字。总体来看,LeNet由两个部分组成:卷积编码器:由两个卷积层组成;全连接层密集块:由三......
  • Linux 6.6+ Oracle RAC 12c搭建详解
    1. RedHatEnterpriseLinuxServerrelease6.6x86_64两台2. Oracle12.1.0.13. ASM存储方式4. 软件下载:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/oracle12c-linux-12201-3608234.html 5. 基础安装包yum-yinstallbinutils.x86......
  • Nexpose v6.6.208 for Linux & Windows - 漏洞扫描
    Nexposev6.6.208forLinux&Windows-漏洞扫描Rapid7VulnerabilityManagement,ReleaseJul27,2023请访问原文链接:https://sysin.org/blog/nexpose-6/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.org您的本地漏洞扫描程序搜集通过实时覆盖整个网络,随......
  • 苹果iOS 16.6 RC发布:或为iPhone X/8系列养老版本
    今天苹果向iPhone用户推送了iOS16.6RC更新(内部版本号:20G75),这是时隔两个月的首次更新。按照惯例RC版基本不会有什么问题,会在最近一段时间内直接变成正式版,向所有用户推送。需要注意的是,鉴于iOS17正式版即将到来,后续iOS16大概率不会带来任何新功能的更新,只是简单的小修小补和......
  • Linux Lite 6.6发行版的候选版(RC)可供公众测试
    Linux Lite的创建者JerryBezencon近日宣布,即将推出的LinuxLite6.6发行版的候选版(RC)开发版本可供公众测试。LinuxLite6.6仍然基于Ubuntu22.04.2LTS(JammyJellyfish)长期支持的操作系统系列,由长期支持的Linux5.15LTS内核系列提供动力,并采用Xfce4.16桌面环境系列,承......
  • Linux Lite 6.6发行版的候选版(RC)可供公众测试
    Linux Lite的创建者JerryBezencon近日宣布,即将推出的LinuxLite6.6发行版的候选版(RC)开发版本可供公众测试。LinuxLite6.6仍然基于Ubuntu22.04.2LTS(JammyJellyfish)长期支持的操作系统系列,由长期支持的Linux5.15LTS内核系列提供动力,并采用Xfce4.16桌面环境系列,承......