基于深度学习的图像分类任务实现(二)卷积神经网络分类器&基于Residual Bolck的卷积神经网络分类器

2023-11-07


实现多种对Cifar-10数据集的分类器,并比较其算法精度。要求基于PyTorch设计并实现四种分类器,并利用Cifar-10的测试集评估各分类器的性能:

1.代码编写思路

在利用pytorch进行模型构造与训练时,总体思路分为四个阶段:
数据集准备、用类设计模型、构造损失函数和优化器、训练模型+测试。
如下图所示

2.卷积神经网络分类器

2.1基本原理

卷积神经网络一般特征提取和全连接神经网络训练。
特征提取包括卷积、池化(两个部分可以重复进行),经过卷积、池化数据达到了特征提取和降维的目的。将提取出的特征扁平化处理后输入至全连接神经网络中通过学习训练模型获得预测标签。在这里插入图片描述

2.2 代码实现

#导入包
import torch
import torchvision
#transforms 定义了一系列数据转化形式,并对数据进行预处理。
import torchvision.transforms as transforms
#matplotlib inline
# 下载数据集并对数据进行处理
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.05,0.05,0.05))])
batch_size=128
trainset= torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform)
trainloader=torch.utils.data.DataLoader(trainset, batch_size, shuffle=True, num_workers=1)
testset=torchvision.datasets.CIFAR10(root='./data',train=False,download=True,transform=transform)
testloader=torch.utils.data.DataLoader(testset, batch_size, shuffle=False, num_workers=1)
# 定义神经网络
import torch.nn as nn
import torch.nn.functional as F
class CNNNet(nn.Module):
    def __init__(self):
        super(CNNNet, self).__init__()
        self.conv1 = nn.Conv2d(3,64,5)  #卷积层,分别是输入通道、输出通道和卷积核大小
        self.pool = nn.MaxPool2d(2,2)  #池化层,对应池化大小和步长。
        self.conv2 = nn.Conv2d(6,16,5) 
        self.fc1 = nn.Linear(16*5*5, 384)
        self.fc2 = nn.Linear(384,192)
        self.fc3 = nn.Linear(192,10)
        self.dropout = nn.Dropout(p=0.6)  #为了防止过拟合使用的drought层
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))  #3*32*32 -- 64*28*28 -- 64*14*14
        x = self.pool(F.relu(self.conv2(x)))  #64*14*14 -- 16*10*10 -- 16*5*5
        #print(x)
        #print(x.shape[0])
        x = x.view(-1,16*5*5) #扁平化处理
        x = F.relu(self.fc1(x))
        x = self.dropout(x)
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
cnnnet=CNNNet()
print('信计181-181294-齐佳静')
print(cnnnet)
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
cnnnet.to(device)
# 假设在一台CUDA机器上运行,那么这里将输出一个CUDA设备号:
print(device)
#定义损失函数和优化器
import torch.optim as optim
loss=nn.CrossEntropyLoss()
optimizer= optim.SGD(cnnnet.parameters(),lr=0.001,momentum=0.99)

#数据准确度评估
def evaluate_accuracy(data_iter, net):
    acc_sum, n = 0.0, 0
    for data in data_iter:
        X, y=data
        X, y=X.to(device),y.to(device)
        acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
        n += y.shape[0]
    return acc_sum / n
#模型训练及训练过程和预测
epochs=200
def train_model(optimizer):
    for epoch in range(epochs):
        train_loss_sum, train_acc_sum, n = 0.0, 0.0, 0
        for data in trainloader:
            inputs, y=data
            inputs, y=inputs.to(device),y.to(device)
            #print(inputs)
            y_hat = cnnnet(inputs)
            cost = loss(y_hat, y).sum()
 
            optimizer.zero_grad()
            cost.backward()
            optimizer.step()
 
            train_loss_sum += cost.item()
            train_acc_sum += (torch.argmax(y_hat, dim=1) == y).float().sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(testloader, cnnnet)
        print('epoch %d, loss %.4f, train acc %.4f, test acc %.4f' % (epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc))
#调用函数进行模型训练
train_model(optimizer)

2.3 运行结果

在这里插入图片描述

#结果可视化
#准确度绘制
import matplotlib.pyplot as plt
# 绘制训练%验证的精度
Trainacc=[] #请输入上述训练过程中保存的数据
Testacc=[] ##请输入上述训练过程中保存的数据
plt.plot(Trainacc)
plt.plot(Testacc)
plt.title('qijiajing')
plt.xlabel('Epoch')
plt.ylabel('Accuracy')
plt.legend(['Train acc', 'Test acc'], loc='upper left')
plt.show()
#loss绘制
import matplotlib.pyplot as plt
loss=[]
plt.plot(loss)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('qijiajing-Model accuracy') 

在这里插入图片描述
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.05,0.05,0.05))]),使得特征具有0.5的均值和0.05方差。我们使用64通道和16通道的55卷积核,22步长为2的池化层,线性层分别为(1655,384)、(384,192)、(192,10)。batch_size=128,使用交叉熵损失函数和SGD优化器,其中lr=0.001,momentum=0.99。
我们选取epoch=100,我们对比了学习率分别为0.01和0.001时模型的训练效果,显然lr=0.001模型表现更佳,也许是因为学习率较高时模型陷入了局部最优解。最终训练集精度稳定在76%左右,测试集精度稳定在65%左右。卷积神经网络经过特征提取保留了图像的空间特征(结构),故训练效果比线性分类器和全连接神经网络分类器都要好。

3.基于Residual Bolck的卷积神经网络分类器

3.1基本原理

全连接神经网络和卷积神经网络在网络的架构上是串行的结构,每一层输出是下一层的输入,我们用的是反向传播算法,用链式法则把一系列偏导数相乘得到总梯度,若每个偏导数都小于1,相乘后的结果会越来越小,甚至趋近于0。当梯度趋于0时,权重得不到更新,随着网络深度的增加,离输入较近的权重无法得到充分的训练。这种现象叫做梯度消失现象。
引入Residual Net:有很多支线将输入跳过中间层直接连接至后面的层,使得后面的层可以直接学习残差(即加一个跳连接),逐层训练,以解决梯度消失问题。在这里插入图片描述
残差块将输入x经过两个权重层,与x相加,再激活。(使得导数在原来基础上加一,进而梯度>1)

3.2代码实现

#导入包
import torch
import torchvision
#transforms 定义了一系列数据转化形式,并对数据进行预处理。
import torchvision.transforms as transforms
#matplotlib inline

#导入数据
transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,0.5,0.5),(0.05,0.05,0.05))])
batch_size=128
trainset= torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform)
trainloader=torch.utils.data.DataLoader(trainset, batch_size, shuffle=True, num_workers=1)
#测试数据集
testset=torchvision.datasets.CIFAR10(root='./data',train=False,download=True,transform=transform)
testloader=torch.utils.data.DataLoader(testset, batch_size, shuffle=False, num_workers=1)
#定义ResidualBlock模型
import torch.nn as nn
import torch.nn.functional as F
class ResidualBlock(nn.Module):
    def __init__(self,channels):
        super(ResidualBlock, self).__init__()
        self.channels = channels
        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
    def forward(self, x):
        y=F.relu(self.conv1(x))
        y=self.conv2(y)
        return F.relu(x+y)
residualblock=ResidualBlock(32)
print(residualblock)
#定义网络模型
import torch.nn as nn
import torch.nn.functional as F
class CNNNet(nn.Module):
    def __init__(self):
        super(CNNNet, self).__init__()
        self.conv1 = nn.Conv2d(3,16,5) 
        self.pool = nn.MaxPool2d(2)
        self.conv2 = nn.Conv2d(16,32,5) 
        self.rblock1=ResidualBlock(16)
        self.rblock2=ResidualBlock(32)
        self.fc = nn.Linear(32*5*5 ,10)
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x))) #3*32*32 -- 16*14*14
        x = self.rblock1(x)
        x = self.pool(F.relu(self.conv2(x))) #16*14*14 -- 32*5*5
        x = self.rblock2(x)
        x = x.view(-1, 32 * 5 * 5)
        x = self.fc(x)
        return x
cnnnet=CNNNet()
print(cnnnet)
device = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")
cnnnet.to(device)
#定义损失函数和优化器
import torch.optim as optim
loss=nn.CrossEntropyLoss()
optimizer= optim.SGD(cnnnet.parameters(),lr=0.01)#,momentum=0.9)

#数据准确度评估
def evaluate_accuracy(data_iter, net):
    acc_sum, n = 0.0, 0
    for data in data_iter:
        X, y=data
        X, y=X.to(device),y.to(device)
        acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
        n += y.shape[0]
return acc_sum / n
epochs=200
def train_model(optimizer):
    for epoch in range(epochs):
        train_loss_sum, train_acc_sum, n = 0.0, 0.0, 0
        for data in trainloader:
            inputs, y=data
            inputs, y=inputs.to(device),y.to(device)
            #print(inputs)
            y_hat = cnnnet(inputs)
            cost = loss(y_hat, y).sum()
 
            optimizer.zero_grad()
            cost.backward()
            optimizer.step()
 
            train_loss_sum += cost.item()
            train_acc_sum += (torch.argmax(y_hat, dim=1) == y).float().sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(testloader, cnnnet)
        print('epoch %d, loss %.4f, train acc %.4f, test acc %.4f' % (epoch + 1, train_loss_sum / n, train_acc_sum / n, test_acc))
train_model(optimizer)

3.3模型结构可视化

在这里插入图片描述

3.4运行结果

对数据特征进行归一化处理成均值为0.5,方差为0.05。除了上述模型的参数,我们使用交叉熵损失函数和SGD优化器,其中lr=0.01,batch_size=128。
在这里插入图片描述
经过100个epoch后,训练集的准确度在86%左右,测试集的准确度在71%左右。与卷积神经网络模型的64%准确度相比有了较大的提升。Residual Block属于高级卷积神经网络的一种,使用残差块来解决因为深度增加而导致模型性能下降的问题,对于此数据集进行训练,提高了网络的性能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于深度学习的图像分类任务实现(二)卷积神经网络分类器&基于Residual Bolck的卷积神经网络分类器 的相关文章

  • Java常见的几种设计模式

    单例设计模式 一个类只允许创建一个对象 或者实例 那这个类就是一个单例类 这种设计模式就叫做单例设计模式 1 如何实现一个单例 构造函数需要是 private 访问权限的 这样才能避免外部通过 new 创建实例 考虑对象创建时的线程安全问题
  • 密码学课设实验——序列密码c++实现

    一 实验目的 通过实现简单的线性反馈移位寄存器 LFSR 理解LFSR的工作原理 本原多项式的重要意义 二 实验内容 1 利用C C 语言实现给定的LFSR 2 通过不同初始状态生成相应的序列 并观察它们的周期有什么特点 3 利用生成的序列
  • git 中获取短的 commit hash 值

    本文摘至 http www open open com lib view open1328070367499 html Git 很聪明 它能够通过你提供的前几个字符来识别你想要的那次提交 只要你提供的那部分 SHA 1 不短于四个字符 并且

随机推荐

  • which——查看所使用的一系列命令的程序文件的存放位置

    which命令 1 作用 查看所使用的一系列命令的程序文件的存放位置 2 语法 which 要查找的命令
  • 字节跳动实习记录

    秋招 秋招能拿到字节跳动offer是我没有想到的 暑期只是拿到深圳一家小公司的offer 没有大厂实习经验 秋招迅雷一面挂 腾讯二面挂 能拿到的只有富途和深信服的offer 本打算去富途 但是后面又接到字节跳动的面试通知 原来笔试过了 但是
  • STM32 DMA传输 中断方式配置 源代码

    stm32单片机源程序 include pbdata h void RCC Configuration void void GPIO Configuration void void NVIC Configuration void void
  • jenkins 集成单元测试

    1 jenkins 集成单元测试 1 1先来一张图 趋势图和最新测试结果 出现的前提必须有一次成功的测试通过才能出现 1 2 点击红色 可以看到具体那个单元测试类报错 点到具体的测试类 会显示对应方法 和错误原因 2 配置 pip流水线代码
  • Mysql5.7报错get db conn fail this authentication plugin is not supported

    系统环境CentOS 6 x Mysql5 7 1 前言 在部署open falcon的时候 第一启动有很多模块都失败 查看log日志有如下报错 2019 01 04 10 33 13 db go 22 g InitDB get db co
  • 完全平方数算法题

    题目描述 对于一个序列 牛牛每次可以将序列中任意一个位置上的数乘上任意一个质数 现在他想知道至少需要多少次操作才能使得该序列中的任意两个不同位置的数相乘都为完全平方数 完全平方数 对于x 若其可以写成 i i x i i x
  • 目标检测——Bridging the Gap Between Anchor-based and Anchor-free Detection via ATSS

    question1 1 什么是anchor based anchor free answer 1 目标检测算法一般可分为anchor based anchor free 两者融合类 区别就在于有没有利用anchor提取候选目标框 2 A a
  • QT学生信息管理系统

    QT学生信息管理系统 项目描述 效果图 登录页面 管理员页面 用户页面 数据库表 用户表 学生表 项目描述 使用QT5 14和SQLite3 本项目分为登录界面 管理员界面 用户界面等界面 使用QStackedLayout实现页面布局及切换
  • 10大网络安全攻击手段及防御方法总结(下)

    6 分布式拒绝服务 DDOS DDoS攻击本身不能使恶意黑客突破安全措施 但会令网站暂时或永久掉线 相关数据显示 单次DDOS攻击可令小企业平均损失12 3万美元 大型企业的损失水平在230万美元左右 DDoS旨在用请求洪水压垮目标Web服
  • JAVA求解【乱序整数序列两数之和绝对值最小】

    题目 给定一个随机的整数 可能存在正整数和负整数 数组 nums 请你在该数组中找出两个数 其和的绝对值 nums x nums y 为最小值 并返回这个两个数 按从小到大返回 以及绝对值 每种输入只会对应一个答案 但是 数组中同一个元素不
  • 移动端H5页面在微信浏览器内audio无法自动播放问题解决

    相信许多小伙伴都遇见过这话种情况 在微信浏览器内添加的audio 无法自动播放 之前写过好多那种活动页添加的背景音乐都可以自动播放 直到后来ios 增加了限制就出现了这个问题 怎么解决的只需给audio标签增加一个属性就可以解决如下图
  • 二、MySQL入门

    1 如何查看MySQL是否运行 1查看进程 root sc mysql ps awx grep mysqld 12953 pts 1 S 0 00 bin sh usr local mysql bin mysqld safe datadir
  • JVM运行原理及Stack和Heap的实现过程

    Java语言写的源程序通过Java编译器 编译成与平台无关的 字节码程序 class文件 也就是0 1二进制程序 然后在OS之上的Java解释器中解释执行 而JVM是java的核心和基础 在java编译器和os平台之间的虚拟处理器 注 本网
  • js wangEditor富文本编辑器

  • 收藏清单:Java测试相关资源汇总

    收藏清单 Java测试相关资源汇总 Virtual environments 虚拟化环境 Vagrant 配置简单可信赖的虚拟化环境管理工具 Docker docker就不用多说了 Performance stress load 性能测试
  • 36-Jenkins-Job迁移

    Job迁移 前言 1 安装插件 2 配置信息 3 使用插件 前言 本篇来学习Jenkins中如何快速迁移job 在工作中可能会遇到这样的场景 即需要把一个Jenkins上的job迁移到另外一台Jenkins上 那怎么做比较好呢 一起来学习下
  • Shader Graph2-PBR介绍之表面属性(图解)

    PBR的实现由光线和表面属性决定 下面我们介绍一下表面属性 这个5个属性在ShaderGraph的根节点是经常的看到 左侧是Unity中的 右侧是UE中的 在没有Metallic金属的情况下 基础颜色值就决定了颜色的漫反射值 也就是说基础颜
  • gitee在README.md中添加图片

    前言 在使用gitee的添加README md文件的时候 有时候会希望能放一些效果图来实现展示效果 实现步骤 1 在项目中添加你的效果图片 比如我的就放在 assets 1 png 然后提交上去 2 打开你的项目 找到刚到图片 然后点击 3
  • Elasticsearch学习系列一(部署和配置IK分词器)

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • 基于深度学习的图像分类任务实现(二)卷积神经网络分类器&基于Residual Bolck的卷积神经网络分类器

    文章目录 1 代码编写思路 2 卷积神经网络分类器 2 1基本原理 2 2 代码实现 2 3 运行结果 3 基于Residual Bolck的卷积神经网络分类器 3 1基本原理 3 2代码实现 3 3模型结构可视化 3 4运行结果 实现多种