深度学习实验(四)——卷积神经网络编程

news2025/1/16 13:50:13

深度学习实验四:卷积神经网络编程

本次实验练习使用torch.nn中的类设计一个卷积神经网络进行MNIST手写体数字图像分类。

name = 'x'#填写你的姓名
sid = 'B02014152'#填写你的学号

print('姓名:%s, 学号:%s'%(name, sid))
姓名:x, 学号:B02014152
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

1. 设计CNN类

从torch.nn.Module派生一个子类CNN,表示一个卷积神经网络;

请合理设计网络各个层,尝试使用不同的结构,比如skip connection, batch normalization,group convolution等。

你的网络模型中至少有2个卷积层、2个聚合层。

#在下面添加代码,实现卷积神经网络,用于识别MNIST手写体数字
# conv1 = nn.Conv2d(in_channels = 3, out_channels = 16, kernel_size = 3, padding = 0) # Valid Conv
# conv2 = nn.Conv2d(in_channels = 3, out_channels = 16, kernel_size = 3, padding = 1) # Same Conv
# conv3 = nn.Conv2d(in_channels = 3, out_channels = 16, kernel_size = 3, padding = 2) # Full Conv

class CNN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.convd1 = nn.Conv2d(in_channels = 1, out_channels = 10, kernel_size = 3, padding = 0)
        self.pool1 = torch.nn.MaxPool2d(kernel_size= 2, stride= 2)
        self.convd2 = nn.Conv2d(in_channels = 10, out_channels = 20, kernel_size = 3, padding = 0)
        self.pool2 = torch.nn.MaxPool2d(kernel_size= 2, stride= 2)
        self.fc = torch.nn.Linear(500, 10)

    def forward(self, x):
        x.cuda()
        batch_size = x.size(0)
        z1 = self.pool1(self.convd1(x))
        a1 = F.relu(z1)
        z2 = self.pool2(self.convd2(a1))
        a2 = F.relu(z2)
        a2 = a2.view(batch_size, -1)
        a2 = self.fc(a2)
        # a2 = F.softmax(a2, dim=0)
        return a2
#测试MLP类
X = torch.rand((32,1,28,28),dtype = torch.float32)
net = CNN()
Y = net(X)
print(Y)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In [482], line 4
      2 X = torch.rand((32,1,28,28),dtype = torch.float32)
      3 net = CNN()
----> 4 Y = net(X)
      5 print(Y)


File ~\AppData\Roaming\Python\Python38\site-packages\torch\nn\modules\module.py:727, in Module._call_impl(self, *input, **kwargs)
    725     result = self._slow_forward(*input, **kwargs)
    726 else:
--> 727     result = self.forward(*input, **kwargs)
    728 for hook in itertools.chain(
    729         _global_forward_hooks.values(),
    730         self._forward_hooks.values()):
    731     hook_result = hook(self, input, result)


Cell In [481], line 19, in CNN.forward(self, x)
     17 batch_size = x.size(0)
     18 x = nn.BatchNorm2d(num_features=1)
---> 19 z1 = self.pool1(self.convd1(x))
     20 a1 = F.relu(z1)
     21 z2 = self.pool2(self.convd2(a1))


File ~\AppData\Roaming\Python\Python38\site-packages\torch\nn\modules\module.py:727, in Module._call_impl(self, *input, **kwargs)
    725     result = self._slow_forward(*input, **kwargs)
    726 else:
--> 727     result = self.forward(*input, **kwargs)
    728 for hook in itertools.chain(
    729         _global_forward_hooks.values(),
    730         self._forward_hooks.values()):
    731     hook_result = hook(self, input, result)


File ~\AppData\Roaming\Python\Python38\site-packages\torch\nn\modules\conv.py:423, in Conv2d.forward(self, input)
    422 def forward(self, input: Tensor) -> Tensor:
--> 423     return self._conv_forward(input, self.weight)


File ~\AppData\Roaming\Python\Python38\site-packages\torch\nn\modules\conv.py:419, in Conv2d._conv_forward(self, input, weight)
    415 if self.padding_mode != 'zeros':
    416     return F.conv2d(F.pad(input, self._reversed_padding_repeated_twice, mode=self.padding_mode),
    417                     weight, self.bias, self.stride,
    418                     _pair(0), self.dilation, self.groups)
--> 419 return F.conv2d(input, weight, self.bias, self.stride,
    420                 self.padding, self.dilation, self.groups)


TypeError: conv2d(): argument 'input' (position 1) must be Tensor, not BatchNorm2d
Y.shape
torch.Size([32, 10])
#了解MLP中的参数
for name,param in net.named_parameters():
    print(name,':',param.size())
convd1.weight : torch.Size([10, 1, 3, 3])
convd1.bias : torch.Size([10])
convd2.weight : torch.Size([20, 10, 3, 3])
convd2.bias : torch.Size([20])
fc.weight : torch.Size([10, 500])
fc.bias : torch.Size([10])
#输出模型
print(net)
CNN(
  (convd1): Conv2d(1, 10, kernel_size=(3, 3), stride=(1, 1))
  (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (convd2): Conv2d(10, 20, kernel_size=(3, 3), stride=(1, 1))
  (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (fc): Linear(in_features=500, out_features=10, bias=True)
)
#用torchsummary输出模型结构
# !pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torchsummary
from torchsummary import summary

summary(net.cuda(), input_size = (1,28,28))
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Conv2d-1           [-1, 10, 26, 26]             100
         MaxPool2d-2           [-1, 10, 13, 13]               0
            Conv2d-3           [-1, 20, 11, 11]           1,820
         MaxPool2d-4             [-1, 20, 5, 5]               0
            Linear-5                   [-1, 10]           5,010
================================================================
Total params: 6,930
Trainable params: 6,930
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.09
Params size (MB): 0.03
Estimated Total Size (MB): 0.12
----------------------------------------------------------------

2.训练模型

2.1 第一步,对数据做预处理

MNIST图像的像素取值范围是[0,1],先把值域改变为[-1,1]. 在PyTorch中,可以使用torchvision.transforms.Normalize类处理。

from torchvision import datasets,transforms

#构造一个变换,将像素值范围变换到[-1,1]
normalizer =  transforms.Normalize((0.5,), (0.5,))#一行代码
#定义一个变换序列transform,包含两个变换:第一个将PIL图像转换为张量,第二个是normalizer

transform = transforms.Compose([transforms.ToTensor(), normalizer]) #一行代码

2.2 第二步,构造训练集,加入预处理

data_path = '../data/'
mnist_train = datasets.MNIST(data_path,download=False,train = True,transform = transform)
mnist_test =  datasets.MNIST(data_path,download=False,train = False,transform = transform)

2.3 第三步,构造加载器

batch_size = 32 #可以自己定义batch_size大小
train_loader = torch.utils.data.DataLoader(mnist_train, batch_size = batch_size, shuffle = True)
test_loader = torch.utils.data.DataLoader(mnist_test, batch_size = batch_size, shuffle = False)
#从加载器里获取一批样本,并输出样本张量的形状
imgs,labels = iter(train_loader).next()#一行样本
imgs.shape
torch.Size([32, 1, 28, 28])
labels.shape
torch.Size([32])

2.4 第四步,训练模型

注意:训练卷积神经网络时,网络的输入是四维张量,尺寸为 N × C × H × W N\times C \times H \times W N×C×H×W,分别表示张量

def Train(model, loader, epochs, lr = 0.1):
    epsilon = 1e-6
    
    #将model置于train模式
    #一行代码
    net.train()

    
    #定义合适的优化器
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)#一行代码
    
    #定义损失函数
    loss = F.cross_entropy#一行代码
    
    #请在下面完成训练代码
    #请在迭代过程中每100次迭代,输出一次损失
    loss0 = 0
    for epoch in range(epochs):
        for it,(imgs, labels) in enumerate(loader):
            #1. zero_grads
            #请用一行代码实现
            optimizer.zero_grad()
            imgs, labels = imgs.cuda(), labels.cuda()

            #2. F.P.前向传播
            #请用一行代码实现
            logits = model(imgs)

            #3. 计算损失            
            loss1 = loss(logits, labels)#请用一行代码实现
            
            if(abs(loss1.item() - loss0)<epsilon):
                break
                
            loss0 = loss1.item()
                
            if it%100==0:
                print('epoch %d, iter %d, loss = %f\n'%(epoch,it,loss1.item()))
                
            #4. 后向传播
            #请用一行代码实现
            loss1.backward()
            
            #5. 梯度下降
            #请用一行代码实现.
            optimizer.step()

    
            
    return model            
#训练模型

model = CNN()
model = model.cuda()

model = Train(model, test_loader, 10)
epoch 0, iter 0, loss = 2.317181

epoch 0, iter 100, loss = 1.612653

epoch 0, iter 200, loss = 0.475313

epoch 0, iter 300, loss = 0.267556

epoch 1, iter 0, loss = 0.272252

epoch 1, iter 100, loss = 0.387812

epoch 1, iter 200, loss = 0.248591

epoch 1, iter 300, loss = 0.130585

epoch 2, iter 0, loss = 0.101499

epoch 2, iter 100, loss = 0.289020

epoch 2, iter 200, loss = 0.127526

epoch 2, iter 300, loss = 0.072299

epoch 3, iter 0, loss = 0.069821

epoch 3, iter 100, loss = 0.237272

epoch 3, iter 200, loss = 0.073975

epoch 3, iter 300, loss = 0.052888

epoch 4, iter 0, loss = 0.055265

epoch 4, iter 100, loss = 0.210844

epoch 4, iter 200, loss = 0.046827

epoch 4, iter 300, loss = 0.046028

epoch 5, iter 0, loss = 0.044145

epoch 5, iter 100, loss = 0.192648

epoch 5, iter 200, loss = 0.031938

epoch 5, iter 300, loss = 0.042316

epoch 6, iter 0, loss = 0.036941

epoch 6, iter 100, loss = 0.179299

epoch 6, iter 200, loss = 0.023668

epoch 6, iter 300, loss = 0.039010

epoch 7, iter 0, loss = 0.032049

epoch 7, iter 100, loss = 0.168726

epoch 7, iter 200, loss = 0.018773

epoch 7, iter 300, loss = 0.036361

epoch 8, iter 0, loss = 0.027803

epoch 8, iter 100, loss = 0.158944

epoch 8, iter 200, loss = 0.015419

epoch 8, iter 300, loss = 0.034879

epoch 9, iter 0, loss = 0.024135

epoch 9, iter 100, loss = 0.149009

epoch 9, iter 200, loss = 0.012855

epoch 9, iter 300, loss = 0.033128

2.5 第五步,测试模型

#编写模型测试过程
def Evaluate(model, loader):
    model.eval()
    correct = 0
    counts = 0
    for imgs, labels in loader:
        imgs, labels = imgs.cuda(), labels.cuda()
        logits = model(imgs)
        yhat = logits.argmax(dim = 1)
        correct = correct + (yhat==labels).sum().item()
        counts = counts + imgs.size(0)
    
    accuracy = correct / counts
    
    return accuracy
acc = Evaluate(model,test_loader)
print('Accuracy = %f'%(acc))
Accuracy = 0.974000
imgs,labels  = next(iter(test_loader))
imgs, labels = imgs.cuda(), labels.cuda()

logits = model(imgs)

imgs, labels = imgs.cpu(), labels.cpu()

yhat = logits.argmax(dim = 1)

plt.figure(figsize = (16,10))
for i in range(imgs.size(0)):
    plt.subplot(4,8,i+1)
    plt.imshow(imgs[i].squeeze()/2+0.5,cmap = 'gray')
    plt.axis('off')
    plt.title('GT=%d, Pred = %d'%(labels[i],yhat[i]))
    
plt.show()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/106865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

完全背包问题(超级详细地讲解优化过程)

完全背包问题一、问题描述二、思路分析1、状态转移方程2、循环设计三、代码模板1、朴素版2、优化版&#xff08;1&#xff09;时间优化&#xff08;2&#xff09;空间优化一、问题描述 二、思路分析 完全背包和01背包的区别就在于01背包中&#xff0c;每个物品只能选择一次&am…

Java架构师大厂面试致命十连问,你接得住吗?

1.什么是缓存雪崩&#xff1f;怎么解决&#xff1f; ​ 编辑切换为居中 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 通常&#xff0c;我们会使用缓存用于缓冲对 DB 的冲击&#xff0c;如果缓存宕机&#xff0c;所有请求将直接打在 DB&#xff0c;造…

故事分享|27岁的Leader:要成为别人的灯塔,自己得先会“发光”

学习编程的年龄跨度很大&#xff0c;有还在读小学的10后小朋友&#xff0c;也有子孙满堂的八十岁老太太&#xff0c;但主力军&#xff0c;当属90后。 很多年前&#xff0c;90后还是许多人口中“垮掉的一代”。 许多年过去了&#xff0c;当90后逐渐摘掉不成熟的标签&#xff0…

ssh前置代理

ssh前置代理ssh前置代理Linux和mac配置ssh前置proxyUbuntu和mac的ncCentos的ncWindows的ssh前置proxyssh前置代理 适用于服务器无法直接连接过去,需要用proxy才可以连接的场景. Linux和mac配置ssh前置proxy nc属命令属于nmap-ncat包 Centos的nmap-ncat版本太低了,需要到https:…

学习笔记 - MapStruct 映射工具

学习笔记 - MapStruct 映射工具简介Maven 依赖实体类 Entity数据传输对象 DTO映射接口测试类IDEA 插件与 Lombok 一起使用参考资料简介 MapStruct是一个代码生成器&#xff0c;它基于约定优于配置的方法&#xff0c;极大地简化了Java bean类型之间映射的实现。 生成的映射代码使…

第8章 关系数据库设计

第8章 关系数据库设计 考试范围&#xff1a; 8.1-8.5&#xff0c;8.8&#xff0c;8.9 考试题型: 模式分解 考试内容&#xff1a; INF概念 非规范化设计的问题&#xff1a;数据冗余&#xff0c;插入/删除/更新异常 函数依赖的概念 平凡函数依赖 函数依赖集 最小(正则)覆…

数据结构和算法学习笔记之 03.单向双向链表和环形链表构建

5.单向链表 把一个节点Node当做是一个对象&#xff0c;改对象里面包含了数据和指向下一个节点的引用指针 5.1 链表的添加和遍历 5.1.1 思路分析 添加 创建一个head头节点表示链表的头节点&#xff0c;里面的存放数据的data null每添加一个元素就直接添加到链表的最后(尾插法…

Practise test day9

另类加法_牛客网 解题思路&#xff1a;位运算符 1 0001 2 0010 按位与&&#xff1a;如果两个二进制位都为1&#xff0c;则返回1&#xff0c;否则返回0 按位异或&#xff1a;两个二进制位相同返回0&#xff0c;不同返回1。 1.二进制位异或的结果&#xff0c;是两个数对应相加…

https-OPenSSL证书生成及自签名证书

目录 SSL/TLS 1、搭建OPenssl服务器 1.1、下载 1.2、安装下载好的exe程序 2、服务器端证书-生成key、CSR、CRT 2.1、进入如下目录&#xff0c;执行cmd 2.2、生成一个私钥key 2.3、由生成的私钥key生成一个待签名的CSR证书文件(公钥) 2.4、查看证书内容 3、自建CA证书 3.1…

跨境电商卖家如何创建客户参与的 Facebook 广告?

关键词&#xff1a;跨境电商卖家、客户参与、Facebook广告 想要从您的 Facebook 广告中获得更多潜在客户或转化&#xff1f;正在寻找为您自己的广告建模的成功秘诀&#xff1f; 在本文中&#xff0c;您将了解创建消费者响应的 Facebook 广告的八个技巧。 将您现有的 Facebook 受…

零基础能否转行做程序员,那些半路出家的程序员大神给你做了榜样

这些年&#xff0c;随着中国互联网产业的高速发展&#xff0c;对程序员这个职业的需求越来越大。而相对较高的薪水、简单的人际关系、入行不需要靠拼爹这些优点&#xff0c;也让越来越多的年轻人选择了这个职业。甚至很多本来已经从事了其他行业的年轻人&#xff0c;也都想转行…

Promise(三) promise自定义封装25-35

1.初始结构搭建 2.resolve和reject结构搭建 3.throw抛出异常改变状态 4.promise对象状态只能修改一次 5.then方法执行回调 6.指定多个回调的实现 7.同步修改状态then方法结果返回 8.异步修改状态then方法结果返回 9.then方法完善与优化 10.catch方法——异常穿透与值管…

网络技术基础复习——计算机网络基本概念七层模型

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 前言 本章将会复习网络技术的一些知识&#xff0c;了解网络基础概念&#x…

如何学习python?python该怎么学?如何高效率学习python?分享python的学习资料和网站

如何学习python&#xff1f; 1、学好python的第一步&#xff0c;就是马上到网站上下载一个python版本。我建议初学者&#xff0c;不要下载具有IDE功能的集成开发环境&#xff0c;比如Eclipse插件等。 2、下载完毕后&#xff0c;就可以开始学习了。学习过程中&#xff0c;我建议…

商业报表工具-FineReport JS 实现动态隐藏参数以及控制参数面板高度

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 -- 1.2 预期效果 开发报表的时&#xff0c;经常会遇到使用的参数控件较多的情况&#xff0c;这时候可以对一些不常用、不需要展现出来的的控件进行隐藏&#xff0c;当需要展示的时候再使其展示出来&#xff0c;如下图所示&…

数字化信道

数字化信道 数字化信道主要包括多相滤波和DFT两个模块。 多相滤波 多相滤波&#xff0c;就是将滤波器系数按照相数进行重排。在D倍抽取后&#xff0c;整个频带的频谱将混叠在0频附近[−Fs2D,Fs2D)[-\frac{F_s}{2D} ,\frac{F_s}{2D})[−2DFs​​,2DFs​​)。因此&#xff0c;…

超标量处理器设计——第四章_分支预测

超标量处理器设计——第四章_分支预测 参考《超标量处理器》姚永斌著 4.1 简述 分支预测主要与预测两个内容, 一个是分支方向, 还有一个是跳转的目标地址首先需要识别出取出的指令是否是分支指令, 如果是需要送入方向和地址预测模块: 分支预测最好的时机就是当前周期取到指令地…

【C++】拷贝构造函数

目录 默认拷贝构造函数 拷贝构造函数的原型&#xff1a; 为什么不用值传递&#xff1f; 为什么不用指针传递&#xff1f; 调用拷贝构造函数的3种情况 (旧对象去构造新对象) 我们熟悉的类型有以下操作&#xff1a; 1.声明&#xff1a;int a; 2.声明并初始化&#xff1a;in…

圣诞节怎么能缺少圣诞树呢?Python+HTML打造专属于你的圣诞树

前言&#xff1a; 美酒一杯让人醉&#xff0c;温馨陪伴浪漫随;雪花片片惹人爱&#xff0c;烦恼忧伤全不见;字里行间藏真情&#xff0c;文短情深送心愿:圣诞佳节快来到&#xff0c;祝大家永远开心幸福! Hello大家好&#xff0c;我是Dream。 圣诞节马上到了&#xff0c;一些朋友问…

非零基础自学Golang 第14章 反射 14.2 基本用法 14.2.1 获取类型信息

非零基础自学Golang 文章目录非零基础自学Golang第14章 反射14.2 基本用法14.2.1 获取类型信息第14章 反射 14.2 基本用法 在使用反射时&#xff0c;我们会经常使用到反射的种类&#xff08;Kind&#xff09;&#xff0c;reflect.Kind在Go语言reflect包中的定义如下&#xff…