深度学习-卷积神经网络CNN

news2024/12/25 12:46:03

案例-图像分类

网络结构: 卷积+BN+激活+池化

数据集介绍

CIFAR-10数据集5万张训练图像、1万张测试图像、10个类别、每个类别有6k个图像,图像大小32×32×3。下图列举了10个类,每一类随机展示了10张图片:

特征图计算

在卷积层和池化层结束后, 将特征图变形成一行n列数据, 计算特征图进行变化, 映射到全连接层时输入层特征为最后一层卷积层经池化后的特征图各维度相乘

具体流程-# Acc: 0.728

# 导包
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchsummary import summary
from torchvision.datasets import CIFAR10
from torchvision.transforms import ToTensor, Compose  # Compose: 数据增强(扩充数据集)
import time
import matplotlib.pyplot as plt
​
batch_size = 16
​
​
# 创建数据集
def create_dataset():
    torch.manual_seed(21)
    train = CIFAR10(
        root='data',
        train=True,
        transform=Compose([ToTensor()])
    )
    test = CIFAR10(
        root='data',
        train=False,
        transform=Compose([ToTensor()])
    )
    return train, test
​
​
# 创建模型
class ImgCls(nn.Module):
    # 定义网络结构
    def __init__(self):
        super(ImgCls, self).__init__()
        # 定义网络层:卷积层+池化层
        self.conv1 = nn.Conv2d(3, 16, stride=1, kernel_size=3)
        self.batch_norm_layer1 = nn.BatchNorm2d(num_features=16, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
​
        self.conv2 = nn.Conv2d(16, 32, stride=1, kernel_size=3)
        self.batch_norm_layer2 = nn.BatchNorm2d(num_features=32, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=1)
​
        self.conv3 = nn.Conv2d(32, 64, stride=1, kernel_size=3)
        self.batch_norm_layer3 = nn.BatchNorm2d(num_features=64, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=1)
​
        self.conv4 = nn.Conv2d(64, 128, stride=1, kernel_size=2)
        self.batch_norm_layer4 = nn.BatchNorm2d(num_features=128, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=2)
​
        self.conv5 = nn.Conv2d(128, 256, stride=1, kernel_size=2)
        self.batch_norm_layer5 = nn.BatchNorm2d(num_features=256, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool5 = nn.MaxPool2d(kernel_size=2, stride=1)
​
        # 全连接层
        self.linear1 = nn.Linear(1024, 2048)
        self.linear2 = nn.Linear(2048, 1024)
        self.linear3 = nn.Linear(1024, 512)
        self.linear4 = nn.Linear(512, 256)
        self.linear5 = nn.Linear(256, 128)
        self.out = nn.Linear(128, 10)
​
    # 定义前向传播
    def forward(self, x):
        # 第1层: 卷积+BN+激活+池化
        x = self.conv1(x)
        x = self.batch_norm_layer1(x)
        x = torch.rrelu(x)
        x = self.pool1(x)
​
        # 第2层: 卷积+BN+激活+池化
        x = self.conv2(x)
        x = self.batch_norm_layer2(x)
        x = torch.rrelu(x)
        x = self.pool2(x)
​
        # 第3层: 卷积+BN+激活+池化
        x = self.conv3(x)
        x = self.batch_norm_layer3(x)
        x = torch.rrelu(x)
        x = self.pool3(x)
​
        # 第4层: 卷积+BN+激活+池化
        x = self.conv4(x)
        x = self.batch_norm_layer4(x)
        x = torch.rrelu(x)
        x = self.pool4(x)
​
        # 第5层: 卷积+BN+激活+池化
        x = self.conv5(x)
        x = self.batch_norm_layer5(x)
        x = torch.rrelu(x)
        x = self.pool5(x)
​
        # 将特征图做成以为向量的形式:相当于特征向量
        x = x.reshape(x.size(0), -1)  # 将3维特征图转化为1维向量(1, n)
​
        # 全连接层
        x = torch.rrelu(self.linear1(x))
        x = torch.rrelu(self.linear2(x))
        x = torch.rrelu(self.linear3(x))
        x = torch.rrelu(self.linear4(x))
        x = torch.rrelu(self.linear5(x))
        # 返回输出结果
        return self.out(x)
​
​
# 训练
def train(model, train_dataset, epochs):
    torch.manual_seed(21)
    loss = nn.CrossEntropyLoss()
    opt = optim.Adam(model.parameters(), lr=1e-4)
    for epoch in range(epochs):
        dataloader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
        loss_total = 0
        iter = 0
        stat_time = time.time()
        for x, y in dataloader:
            output = model(x.to(device))
            loss_value = loss(output, y.to(device))
            opt.zero_grad()
            loss_value.backward()
            opt.step()
            loss_total += loss_value.item()
            iter += 1
        print(f'epoch:{epoch + 1:4d}, loss:{loss_total / iter:6.4f}, time:{time.time() - stat_time:.2f}s')
    torch.save(model.state_dict(), 'model/img_cls_model.pth')
​
​
# 测试
def test(valid_dataset, model, batch_size):
    # 构建数据加载器
    dataloader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False)
​
    # 计算精度
    total_correct = 0
    # 遍历每个batch的数据,获取预测结果,计算精度
    for x, y in dataloader:
        output = model(x.to(device))
        y_pred = torch.argmax(output, dim=-1)
        total_correct += (y_pred == y.to(device)).sum()
    # 打印精度
    print(f'Acc: {(total_correct.item() / len(valid_dataset))}')
​
​
if __name__ == '__main__':
    batch_size = 16
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    # 获取数据集
    train_data, test_data = create_dataset()
​
    # # 查看数据集
    # print(f'数据集类别: {train_data.class_to_idx}')
    # print(f'训练集: {train_data.data.shape}')
    # print(f'验证集: {test_data.data.shape}')
    # print(f'类别数量: {len(np.unique(train_data.targets))}')
    # # 展示图像
    # plt.figure(figsize=(8, 8))
    # plt.imshow(train_data.data[0])
    # plt.title(train_data.classes[train_data.targets[0]])
    # plt.show()
​
    # 实例化模型
    model = ImgCls().to(device)
​
    # 查看网络结构
    summary(model, (3, 32, 32), device='cuda', batch_size=batch_size)
​
    # 模型训练
    train(model, train_data, epochs=60)
    # 加载训练好的模型参数
    model.load_state_dict(torch.load('model/img_cls_model.pth'))
    model.eval()
    # 模型评估
    test(test_data, model, batch_size=16)   # Acc: 0.728
​

调整网络结构

第一次调整: 训练50轮, Acc: 0.71

第二次调整: 训练30轮, Acc:0.7351

第三次调整: batch_size=8, epoch=50 => Acc: 0.7644

# 导包
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torchsummary import summary
from torchvision.datasets import CIFAR10
from torchvision.transforms import ToTensor, Compose  # Compose: 数据增强(扩充数据集)
import time
import matplotlib.pyplot as plt
​
batch_size = 16
​
​
# 创建数据集
def create_dataset():
    torch.manual_seed(21)
    train = CIFAR10(
        root='data',
        train=True,
        transform=Compose([ToTensor()])
    )
    test = CIFAR10(
        root='data',
        train=False,
        transform=Compose([ToTensor()])
    )
    return train, test
​
​
# 创建模型
class ImgCls(nn.Module):
    # 定义网络结构
    def __init__(self):
        super(ImgCls, self).__init__()
        # 定义网络层:卷积层+池化层
        self.conv1 = nn.Conv2d(3, 16, stride=1, kernel_size=3, padding=1)
        self.batch_norm_layer1 = nn.BatchNorm2d(num_features=16, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2)
​
        self.conv2 = nn.Conv2d(16, 32, stride=1, kernel_size=3, padding=1)
        self.batch_norm_layer2 = nn.BatchNorm2d(num_features=32, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
​
        self.conv3 = nn.Conv2d(32, 64, stride=1, kernel_size=3, padding=1)
        self.batch_norm_layer3 = nn.BatchNorm2d(num_features=64, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=1)
​
        self.conv4 = nn.Conv2d(64, 128, stride=1, kernel_size=3, padding=1)
        self.batch_norm_layer4 = nn.BatchNorm2d(num_features=128, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool4 = nn.MaxPool2d(kernel_size=2, stride=1)
​
        self.conv5 = nn.Conv2d(128, 256, stride=1, kernel_size=3)
        self.batch_norm_layer5 = nn.BatchNorm2d(num_features=256, eps=1e-5, momentum=0.1, affine=True, track_running_stats=True)
        self.pool5 = nn.MaxPool2d(kernel_size=2, stride=2)
​
        # 全连接层
        self.linear1 = nn.Linear(1024, 2048)
        self.linear2 = nn.Linear(2048, 1024)
        self.linear3 = nn.Linear(1024, 512)
        self.linear4 = nn.Linear(512, 256)
        self.linear5 = nn.Linear(256, 128)
        self.out = nn.Linear(128, 10)
​
    # 定义前向传播
    def forward(self, x):
        # 第1层: 卷积+BN+激活+池化
        x = self.conv1(x)
        x = self.batch_norm_layer1(x)
        x = torch.relu(x)
        x = self.pool1(x)
​
        # 第2层: 卷积+BN+激活+池化
        x = self.conv2(x)
        x = self.batch_norm_layer2(x)
        x = torch.relu(x)
        x = self.pool2(x)
​
        # 第3层: 卷积+BN+激活+池化
        x = self.conv3(x)
        x = self.batch_norm_layer3(x)
        x = torch.relu(x)
        x = self.pool3(x)
​
        # 第4层: 卷积+BN+激活+池化
        x = self.conv4(x)
        x = self.batch_norm_layer4(x)
        x = torch.relu(x)
        x = self.pool4(x)
​
        # 第5层: 卷积+BN+激活+池化
        x = self.conv5(x)
        x = self.batch_norm_layer5(x)
        x = torch.rrelu(x)
        x = self.pool5(x)
​
        # 将特征图做成以为向量的形式:相当于特征向量
        x = x.reshape(x.size(0), -1)  # 将3维特征图转化为1维向量(1, n)
​
        # 全连接层
        x = torch.relu(self.linear1(x))
        x = torch.relu(self.linear2(x))
        x = torch.relu(self.linear3(x))
        x = torch.relu(self.linear4(x))
        x = torch.rrelu(self.linear5(x))
        # 返回输出结果
        return self.out(x)
​
​
# 训练
def train(model, train_dataset, epochs):
    torch.manual_seed(21)
    loss = nn.CrossEntropyLoss()
    opt = optim.Adam(model.parameters(), lr=1e-4)
    for epoch in range(epochs):
        dataloader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
        loss_total = 0
        iter = 0
        stat_time = time.time()
        for x, y in dataloader:
            output = model(x.to(device))
            loss_value = loss(output, y.to(device))
            opt.zero_grad()
            loss_value.backward()
            opt.step()
            loss_total += loss_value.item()
            iter += 1
        print(f'epoch:{epoch + 1:4d}, loss:{loss_total / iter:6.4f}, time:{time.time() - stat_time:.2f}s')
    torch.save(model.state_dict(), 'model/img_cls_model1.pth')
​
​
# 测试
def test(valid_dataset, model, batch_size):
    # 构建数据加载器
    dataloader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False)
​
    # 计算精度
    total_correct = 0
    # 遍历每个batch的数据,获取预测结果,计算精度
    for x, y in dataloader:
        output = model(x.to(device))
        y_pred = torch.argmax(output, dim=-1)
        total_correct += (y_pred == y.to(device)).sum()
    # 打印精度
    print(f'Acc: {(total_correct.item() / len(valid_dataset))}')
​
​
if __name__ == '__main__':
    batch_size = 8
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    # 获取数据集
    train_data, test_data = create_dataset()
​
    # # 查看数据集
    # print(f'数据集类别: {train_data.class_to_idx}')
    # print(f'训练集: {train_data.data.shape}')
    # print(f'验证集: {test_data.data.shape}')
    # print(f'类别数量: {len(np.unique(train_data.targets))}')
    # # 展示图像
    # plt.figure(figsize=(8, 8))
    # plt.imshow(train_data.data[0])
    # plt.title(train_data.classes[train_data.targets[0]])
    # plt.show()
​
    # 实例化模型
    model = ImgCls().to(device)
​
    # 查看网络结构
    summary(model, (3, 32, 32), device='cuda', batch_size=batch_size)
​
    # 模型训练
    train(model, train_data, epochs=50)
    # 加载训练好的模型参数
    model.load_state_dict(torch.load('model/img_cls_model1.pth', weights_only=True))
    model.eval()
    # 模型评估
    test(test_data, model, batch_size=16)   # Acc: 0.7644
​

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

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

相关文章

关于adb shell登录开发板后terminal显示不完整

现象 今天有个同事跟我说,adb shell 登录开发板后,终端显示不完整,超出边界后就会出现奇怪的问题,比如字符覆盖显示等。如下图所示。 正常情况下应该如下图所示: 很明显,第一张图的显示区域只有完整区域…

【论文分享】三维景观格局如何影响城市居民的情绪

城市景观对居民情绪的影响是近些年来讨论的热门话题之一,现有的研究主要以遥感影像为数据来源,进行二维图像-数据分析,其量化结果精确度有限。本文引入了三维景观格局的研究模型,通过街景图片及网络发帖信息补充图像及数据来源&am…

ChatGPT学术专用版,一键润色纠错+中英互译+批量翻译PDF

ChatGPT academic项目是由中科院团队基于ChatGPT专属定制。论文润色、语法检查、中英互译、代码解释等可一键搞定,堪称科研神器。 功能介绍 我们以3.5版本为例,ChatGPT学术版总共分为五个区域:输入控制区、输出对话区、基础功能区、函数插件…

Go 语言已立足主流,编程语言排行榜24 年 11 月

Go语言概述 Go语言,简称Golang,是由Google的Robert Griesemer、Rob Pike和Ken Thompson在2007年设计,并于2009年11月正式宣布推出的静态类型、编译型开源编程语言。Go语言以其提高编程效率、软件构建速度和运行时性能的设计目标,…

一、HTML

一、基础概念 1、浏览器相关知识 这五个浏览器市场份额都非常大,且都有自己的内核。 什么是内核: 内核是浏览器的核心,用于处理浏览器所得到的各种资源。 例如,服务器发送图片、视频、音频的资源,浏览…

VRRP HSRP GLBP 三者区别

1. VRRP(Virtual Router Redundancy Protocol,虚拟路由冗余协议) 标准协议:VRRP 是一种开放标准协议(RFC 5798),因此支持的厂商较多,通常用于多种网络设备中。主备模式:…

Elasticsearch:管理和排除 Elasticsearch 内存故障

作者:来自 Elastic Stef Nestor 随着 Elastic Cloud 提供可观察性、安全性和搜索等解决方案,我们将使用 Elastic Cloud 的用户范围从完整的运营团队扩大到包括数据工程师、安全团队和顾问。作为 Elastic 支持代表,我很乐意与各种各样的用户和…

Java集合(Collection+Map)

Java集合&#xff08;CollectionMap&#xff09; 为什么要使用集合&#xff1f;泛型 <>集合框架单列集合CollectionCollection遍历方式List&#xff1a;有序、可重复、有索引ArrayListLinkedListVector&#xff08;已经淘汰&#xff0c;不会再用&#xff09; Set&#xf…

大数据如何助力干部选拔的公正性

随着社会的发展和进步&#xff0c;干部选拔成为组织管理中至关重要的一环。传统的选拔方式可能存在主观性、不公平性以及效率低下等问题。大数据技术的应用&#xff0c;为干部选拔提供了更加全面、精准、客观的信息支持&#xff0c;显著提升选拔工作的科学性和公正性。以下是大…

EHOME视频平台EasyCVR多品牌摄像机视频平台监控视频编码H.265与Smart 265的区别?

在视频监控领域&#xff0c;技术的不断进步推动着行业向更高效、更智能的方向发展。特别是在编码技术方面&#xff0c;Smart 265作为一种新型的视频编码技术&#xff0c;相较于传统的H.265&#xff0c;有明显优势。这种技术的优势在EasyCVR视频监控汇聚管理平台中得到了充分的体…

Docker:查看镜像里的文件

目录 背景步骤1、下载所需要的docker镜像2、创建并运行临时容器3、停止并删除临时容器 背景 在开发过程中&#xff0c;为了更好的理解和开发程序&#xff0c;有时需要确认镜像里的文件是否符合预期&#xff0c;这时就需要查看镜像内容 步骤 1、下载所需要的docker镜像 可以使…

【Vitepress报错】Error: [vitepress] 8 dead link(s) found.

原因 VitePress 在编译时&#xff0c;发现 死链接(dead links) 会构建失败&#xff01;具体在哪我也找不到… 解决方案 如图第一行蓝色提示信息&#xff0c;设置 Vitepress 属性 ignoredeadlinks 为 true 可忽略报错。 .vuepress/config.js export default defineConfig(…

HTB:Squashed[WriteUP]

目录 连接至HTB服务器并启动靶机 使用rustscan对靶机TCP端口进行开放扫描 使用nmap对靶机开放端口进行脚本、服务扫描 使用浏览器访问靶机80端口页面 使用showmount列出靶机上的NFS共享 新建一个test用户 使用Kali自带的PHP_REVERSE_SHELL并复制到一号挂载点 尝试使用c…

数据分析-48-时间序列变点检测之在线实时数据的CPD

文章目录 1 时间序列结构1.1 变化点的定义1.2 结构变化的类型1.2.1 水平变化1.2.2 方差变化1.3 变点检测1.3.1 离线数据检测方法1.3.2 实时数据检测方法2 模拟数据2.1 模拟恒定方差数据2.2 模拟变化方差数据3 实时数据CPD3.1 SDAR学习算法3.2 Changefinder模块3.3 恒定方差CPD3…

ThriveX 博客管理系统前后端项目部署教程

前端 前端项目地址&#xff1a;https://github.com/LiuYuYang01/ThriveX-Blog 控制端项目地址&#xff1a;https://github.com/LiuYuYang01/ThriveX-Admin Vercel 首先以 Vercel 进行部署&#xff0c;两种方式部署都是一样的&#xff0c;我们以前端项目进行演示 首先我们先…

Seata源码笔记(三)

Seata源码笔记&#xff08;三&#xff09; RPC部分基础接口AbstractNettyRemotinginit方法send方法&#xff08;仅看sendSync&#xff09;sendSync中的钩子 AbstractNettyRemotingClient 基于incubator-seata-2.x RPC部分 基础接口 AbstractNettyRemoting init方法 主要设置…

Verilog HDL学习笔记

Verilog HDL&#xff08;Hardware Description Language&#xff09;是在一种硬件描述语言&#xff0c;类似于计算机的高级编程设计语言&#xff0c;它具有灵活性高&#xff0c;容易学习和使用等特点&#xff0c;同时Verilog能够通过文本的形式来描述数字系统的硬件结构和功能。…

java-Day07 包装类 异常+自定义异常

包装类 包装类:将基本数据类型包装成引用数据类型 int-Integer char-Character double-Double 其余都大写 包装类好处 1.包装类的存在弥补了基本数据类型的不足。在集合类中&#xff0c;无法将int 、double等类型放进去&#xff0c;因为集合的容器要求元素是Object类型。…

10款高效音频剪辑工具,让声音编辑更上一层楼。

音频剪辑在音频&#xff0c;视频&#xff0c;广告制作&#xff0c;游戏开发&#xff0c;广播等领域中都有广泛的应用。通过音频剪辑&#xff0c;创作者可以通将不同的音频片段进行剪切、拼接、混音等操作&#xff0c;创作出风格各异的音乐作品。如果你也正在为音频创作而努力的…

释放高级功能:Nexusflows Athene-V2-Agent在工具使用和代理用例方面超越 GPT-4o

在不断发展的人工智能领域&#xff0c;Nexusflows 推出了 Athene-V2-Agent 作为其模型系列的强大补充。这种专门的代理模型设计用于在功能调用和代理应用中发挥出色作用&#xff0c;突破了人工智能所能达到的极限。 竞争优势 Athene-V2-Agent 不仅仅是另一种人工智能模型&…