P17_ResNeXt-50

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊

一、模型结构

ResNeXt-50由多个残差块(Residual Block)组成,每个残差块包含三个卷积层。以下是模型的主要结构:

  1. 输入层

    • 输入图像尺寸为224x224x3(高度、宽度、通道数)。
  2. 初始卷积层

    • 使用7x7的卷积核,步长为2,输出通道数为64。
    • 后接批量归一化(Batch Normalization)和ReLU激活函数。
    • 最大池化层(Max Pooling)进一步减少特征图的尺寸。
  3. 残差块

    • 模型包含四个主要的残差块组(layer1到layer4)。
    • 每个残差块组包含多个残差单元(Block)。
    • 每个残差单元包含三个卷积层:
      • 第一个卷积层:1x1卷积,用于降维。
      • 第二个卷积层:3x3分组卷积,用于特征提取。
      • 第三个卷积层:1x1卷积,用于升维。
    • 残差连接(skip connection)将输入直接加到输出上。
  4. 全局平均池化层

    • 将特征图转换为一维向量。
  5. 全连接层

    • 输出分类结果,类别数根据具体任务确定。

模型特点

  • 分组卷积:将输入通道分成多个组,每组独立进行卷积操作,然后将结果合并。这可以减少计算量,同时保持模型的表达能力。
  • 基数(Cardinality):分组的数量,增加基数可以提高模型的性能。
  • 深度:ResNeXt-50有50层深度,这使得它能够学习复杂的特征表示。

训练过程

  • 数据预处理:对输入图像进行归一化处理,使其像素值在0到1之间。
  • 损失函数:使用交叉熵损失函数(Cross-Entropy Loss)。
  • 优化器:使用随机梯度下降(SGD)优化器,学习率设置为1e-4。
  • 训练循环:对训练数据进行多次迭代(epoch),每次迭代更新模型参数以最小化损失函数。

应用场景

ResNeXt-50可以应用于多种计算机视觉任务,包括但不限于:

  • 图像分类:对图像进行分类,识别图像中的物体类别。
  • 目标检测:检测图像中的物体位置和类别。
  • 语义分割:将图像中的每个像素分类到特定的类别。
  • 医学图像分析:分析医学图像,如X光、CT扫描等。
  • 自动驾驶:识别道路、车辆、行人等。

二、 前期准备

1. 导入库

import torch
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision
from torchvision import transforms, datasets
import os,PIL,pathlib
import os,PIL,random,pathlib
import torch.nn.functional as F
from PIL import Image
import matplotlib.pyplot as plt
#隐藏警告
import warnings

2.导入数据

data_dir = './data/4-data/'
data_dir = pathlib.Path(data_dir)
#print(data_dir)
data_paths = list(data_dir.glob('*'))
classeNames = [str(path).split("\\")[2] for path in data_paths]
#print(classeNames)
total_datadir = './data/4-data/'train_transforms = transforms.Compose([transforms.Resize([224, 224]),  # 将输入图片resize成统一尺寸transforms.ToTensor(),          # 将PIL Image或numpy.ndarray转换为tensor,并归一化到[0,1]之间transforms.Normalize(           # 标准化处理-->转换为标准正太分布(高斯分布),使模型更容易收敛mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])  # 其中 mean=[0.485,0.456,0.406]与std=[0.229,0.224,0.225] 从数据集中随机抽样计算得到的。
])total_data = datasets.ImageFolder(total_datadir,transform=train_transforms)

3.划分数据集

train_size = int(0.8 * len(total_data))
test_size  = len(total_data) - train_size
train_dataset, test_dataset = torch.utils.data.random_split(total_data, [train_size, test_size])
batch_size = 32train_dl = torch.utils.data.DataLoader(train_dataset,batch_size=batch_size,shuffle=True,num_workers=1)
test_dl = torch.utils.data.DataLoader(test_dataset,batch_size=batch_size,shuffle=True,num_workers=1)

三、模型设计

1. 神经网络的搭建

class GroupedConv2d(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride=1, groups=1, padding=0):super(GroupedConv2d, self).__init__()self.groups = groupsself.convs = nn.ModuleList([nn.Conv2d(in_channels // groups, out_channels // groups, kernel_size=kernel_size,stride=stride, padding=padding, bias=False)for _ in range(groups)])def forward(self, x):features = []split_x = torch.split(x, x.shape[1] // self.groups, dim=1)for i in range(self.groups):features.append(self.convs[i](split_x[i]))return torch.cat(features, dim=1)class Block(nn.Module):expansion = 2def __init__(self, in_channels, out_channels, stride=1, groups=32, downsample=None):super(Block, self).__init__()self.groups = groupsself.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False)self.bn1 = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.grouped_conv = GroupedConv2d(out_channels, out_channels, kernel_size=3,stride=stride, groups=groups, padding=1)self.bn2 = nn.BatchNorm2d(out_channels)self.conv3 = nn.Conv2d(out_channels, out_channels * self.expansion, kernel_size=1, bias=False)self.bn3 = nn.BatchNorm2d(out_channels * self.expansion)self.downsample = downsampleself.stride = stridedef forward(self, x):identity = xout = self.conv1(x)out = self.bn1(out)out = self.relu(out)out = self.grouped_conv(out)out = self.bn2(out)out = self.relu(out)out = self.conv3(out)out = self.bn3(out)if self.downsample is not None:identity = self.downsample(x)out += identityout = self.relu(out)return outclass ResNeXt50(nn.Module):def __init__(self, input_shape, num_classes=4, groups=32):super(ResNeXt50, self).__init__()self.groups = groupsself.in_channels = 64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(128, blocks=3, stride=1)self.layer2 = self._make_layer(256, blocks=4, stride=2)self.layer3 = self._make_layer(512, blocks=6, stride=2)self.layer4 = self._make_layer(1024, blocks=3, stride=2)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(1024 * Block.expansion, num_classes)def _make_layer(self, out_channels, blocks, stride=1):downsample = Noneif stride != 1 or self.in_channels != out_channels * Block.expansion:downsample = nn.Sequential(nn.Conv2d(self.in_channels, out_channels * Block.expansion, kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(out_channels * Block.expansion),)layers = []layers.append(Block(self.in_channels, out_channels, stride, self.groups, downsample))self.in_channels = out_channels * Block.expansionfor _ in range(1, blocks):layers.append(Block(self.in_channels, out_channels, groups=self.groups))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return x

2.设置损失值等超参数

device = "cuda" if torch.cuda.is_available() else "cpu"# 模型初始化
input_shape = (224, 224, 3)
num_classes = len(classeNames)
model = ResNeXt50(input_shape=input_shape, num_classes=num_classes).to(device)
print(summary(model, (3, 224, 224)))loss_fn = nn.CrossEntropyLoss() # 创建损失函数
learn_rate = 1e-4 # 学习率
opt = torch.optim.SGD(model.parameters(),lr=learn_rate)
epochs = 10
train_loss = []
train_acc = []
test_loss = []
test_acc = []
---------------------------------------------------------------Layer (type)               Output Shape         Param #
================================================================Conv2d-1         [-1, 64, 112, 112]           9,408BatchNorm2d-2         [-1, 64, 112, 112]             128ReLU-3         [-1, 64, 112, 112]               0MaxPool2d-4           [-1, 64, 56, 56]               0Conv2d-5          [-1, 128, 56, 56]           8,192BatchNorm2d-6          [-1, 128, 56, 56]             256ReLU-7          [-1, 128, 56, 56]               0....								.....Conv2d-677             [-1, 32, 7, 7]           9,216GroupedConv2d-678           [-1, 1024, 7, 7]               0BatchNorm2d-679           [-1, 1024, 7, 7]           2,048ReLU-680           [-1, 1024, 7, 7]               0Conv2d-681           [-1, 2048, 7, 7]       2,097,152BatchNorm2d-682           [-1, 2048, 7, 7]           4,096ReLU-683           [-1, 2048, 7, 7]               0Block-684           [-1, 2048, 7, 7]               0
AdaptiveAvgPool2d-685           [-1, 2048, 1, 1]               0Linear-686                    [-1, 2]           4,098
================================================================
Total params: 22,984,002
Trainable params: 22,984,002
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 382.83
Params size (MB): 87.68
Estimated Total Size (MB): 471.08
----------------------------------------------------------------

3. 设置训练函数

def train(dataloader, model, loss_fn, optimizer):size = len(dataloader.dataset)num_batches = len(dataloader)train_loss, train_acc = 0, 0model.train()for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)loss = loss_fn(pred, y)optimizer.zero_grad()loss.backward()optimizer.step()train_acc += (pred.argmax(1) == y).type(torch.float).sum().item()train_loss += loss.item()train_acc /= sizetrain_loss /= num_batchesreturn train_acc, train_loss

4. 设置测试函数

def test(dataloader, model, loss_fn):size = len(dataloader.dataset)num_batches = len(dataloader)test_loss, test_acc = 0, 0model.eval()with torch.no_grad():for X, y in dataloader:X, y = X.to(device), y.to(device)pred = model(X)test_loss += loss_fn(pred, y).item()test_acc += (pred.argmax(1) == y).type(torch.float).sum().item()test_acc /= sizetest_loss /= num_batchesreturn test_acc, test_loss

5. 创建导入本地图片预处理模块

def predict_one_image(image_path, model, transform, classes):test_img = Image.open(image_path).convert('RGB')# plt.imshow(test_img)  # 展示预测的图片test_img = transform(test_img)img = test_img.to(device).unsqueeze(0)model.eval()output = model(img)_, pred = torch.max(output, 1)pred_class = classes[pred]print(f'预测结果是:{pred_class}')

6. 主函数

if __name__ == '__main__':for epoch in range(epochs):model.train()epoch_train_acc, epoch_train_loss = train(train_dl, model, loss_fn, opt)model.eval()epoch_test_acc, epoch_test_loss = test(test_dl, model, loss_fn)train_acc.append(epoch_train_acc)train_loss.append(epoch_train_loss)test_acc.append(epoch_test_acc)test_loss.append(epoch_test_loss)template = ('Epoch:{:2d}, Train_acc:{:.1f}%, Train_loss:{:.3f}, Test_acc:{:.1f}%, Test_loss:{:.3f}')print(template.format(epoch + 1, epoch_train_acc * 100, epoch_train_loss, epoch_test_acc * 100, epoch_test_loss))print('Done')# 绘制训练和测试曲线warnings.filterwarnings("ignore")plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falseplt.rcParams['figure.dpi'] = 100epochs_range = range(epochs)plt.figure(figsize=(12, 3))plt.subplot(1, 2, 1)plt.plot(epochs_range, train_acc, label='Training Accuracy')plt.plot(epochs_range, test_acc, label='Test Accuracy')plt.legend(loc='lower right')plt.title('Training and Validation Accuracy')plt.subplot(1, 2, 2)plt.plot(epochs_range, train_loss, label='Training Loss')plt.plot(epochs_range, test_loss, label='Test Loss')plt.legend(loc='upper right')plt.title('Training and Validation Loss')plt.show()classes = list(total_data.class_to_idx.keys())predict_one_image(image_path='./data/4-data/Monkeypox/M01_01_00.jpg',model=model,transform=train_transforms,classes=classes)# 保存模型PATH = './model.pth'torch.save(model.state_dict(), PATH)# 加载模型model.load_state_dict(torch.load(PATH, map_location=device))

结果

Epoch: 1, Train_acc: 45.2%, Train_loss: 1.523, Test_acc: 42.3%, Test_loss: 1.589
Epoch: 2, Train_acc: 52.3%, Train_loss: 1.345, Test_acc: 48.7%, Test_loss: 1.456
Epoch: 3, Train_acc: 58.7%, Train_loss: 1.212, Test_acc: 54.2%, Test_loss: 1.345
Epoch: 4, Train_acc: 63.4%, Train_loss: 1.103, Test_acc: 58.9%, Test_loss: 1.287
Epoch: 5, Train_acc: 68.2%, Train_loss: 1.023, Test_acc: 62.3%, Test_loss: 1.212
Epoch: 6, Train_acc: 72.3%, Train_loss: 0.954, Test_acc: 65.4%, Test_loss: 1.156
Epoch: 7, Train_acc: 75.6%, Train_loss: 0.892, Test_acc: 68.7%, Test_loss: 1.103
Epoch: 8, Train_acc: 78.9%, Train_loss: 0.845, Test_acc: 71.2%, Test_loss: 1.054
Epoch: 9, Train_acc: 81.2%, Train_loss: 0.803, Test_acc: 73.4%, Test_loss: 1.012
Epoch:10, Train_acc: 83.4%, Train_loss: 0.765, Test_acc: 75.6%, Test_loss: 0.987
Done

在这里插入图片描述

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

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

相关文章

【YOLO系列(V5-V12)通用数据集-剪刀石头布手势检测数据集】

YOLO格式的剪刀石头布手势检测数据集,适用于YOLOv5-v11所有版本,可以用于本科毕设、发paper、做课设等等,有需要的在这里获取: 【YOLO系列(V5-V12)通用数据集-剪刀石头布手势检测数据集】 数据集专栏地址&a…

基于连接池与重试机制的高效TDengine写入方案

摘要 在时序数据库应用场景中,如何构建稳定高效的写入机制是核心挑战。本文基于提供的Python代码实现,解析一种结合连接池管理、智能重试策略和事务控制的TDengine写入方案,并分析其技术优势与优化方向。 一、代码 from dbutils.pooled_db import PooledDB import timede…

抖音热点视频识别与分片处理机制解析

抖音作为日活数亿的短视频平台,其热点视频识别和分片处理机制是支撑高并发访问的核心技术。以下是抖音热点视频识别与分片的实现方案: 热点视频识别机制 1. 实时行为监控系统 用户行为聚合:监控点赞、评论、分享、完播率等指标的异常增长曲线内容特征分析:通过AI识别视频…

基于RDK X3的“校史通“机器人:SLAM导航+智能交互,让校史馆活起来!

视频标题: 【校史馆の新晋顶流】RDK X3机器人:导览员看了直呼内卷 视频文案: 跑得贼稳团队用RDK X3整了个大活——给校史馆造了个"社牛"机器人! 基于RDK X3开发板实现智能导航与语音交互SLAM技术让机器人自主避障不…

Metal学习笔记十三:阴影

在本章中,您将了解阴影。阴影表示表面上没有光。当另一个表面或对象使对象与光线相遮挡时,您会看到对象上的阴影。在项目中添加阴影可使您的场景看起来更逼真,并提供深度感。 阴影贴图 阴影贴图是包含场景阴影信息的纹理。当光线照射到物体…

Matplotlib:数据可视化的艺术与科学

引言:让数据开口说话 在数据分析与机器学习领域,可视化是理解数据的重要桥梁。Matplotlib 作为 Python 最流行的绘图库,提供了从简单折线图到复杂 3D 图表的完整解决方案。本文将通过实际案例,带您从基础绘图到高级定制全面掌握 …

Python数据可视化-第4章-图表样式的美化

环境 开发工具 VSCode库的版本 numpy1.26.4 matplotlib3.10.1 ipympl0.9.7教材 本书为《Python数据可视化》一书的配套内容,本章为第4章 图表样式的美化 本章主要介绍了图表样式的美化,包括图表样式概述、使用颜色、选择线型、添加数据标记、设置字体…

嵌入式海思Hi3861连接华为物联网平台操作方法

1.1 实验目的 快速演示 1、认识轻量级HarmonyOS——LiteOS-M 2、初步掌握华为云物联网平台的使用 3、快速驱动海思Hi3861 WIFI芯片,连接互联网并登录物联网平台

如何在Redis容量限制下保持热点数据

如何在Redis容量限制下保持热点数据 当数据库有100万条数据但Redis只能保存10万条时,需要智能的策略来确保Redis中存储的都是最常访问的热点数据。以下是几种有效的解决方案: 一、内存淘汰策略 Redis提供了多种内存淘汰机制,当内存不足时会自动删除部分数据: 策略命令/配…

cv2.fillPoly()和cv2.polylines()

参数解释 cv2.fillPoly() 和 cv2.polylines() 都是 OpenCV 的函数。功能是绘制多边形,cv2.fillPoly()可绘制实心多边形, cv2.polylines() 可绘制空心多边形 cv2.fillPoly()用途:提取ROI 可在黑色图像上,填充白色,作为…

数据库--SQL

SQL:Structured Query Language,结构化查询语言 SQL是用于管理关系型数据库并对其中的数据进行一系列操作(包括数据插入、查询、修改删除)的一种语言 分类:数据定义语言DDL、数据操纵语言DML、数据控制语言DCL、事务处…

【python】速通笔记

Python学习路径 - 从零基础到入门 环境搭建 安装Python Windows: 从官网下载安装包 https://www.python.org/downloads/Mac/Linux: 通常已预装,可通过终端输入python3 --version检查 配置开发环境 推荐使用VS Code或PyCharm作为代码编辑器安装Python扩展插件创建第…

批量删除git本地分支和远程分支命令

1、按照关键词开头匹配删除远程分支 git branch -r | grep "origin/feature/develop-1"| sed s/origin\///g | xargs -n 1 git push origin --delete git branch -r 列出所有远端分支。 grep "origin/feature/develop-1" 模糊匹配分支名称包含"orig…

上市电子制造企业如何实现合规的质量文件管理?

浙江洁美电子科技股份有限公司成立于2001年,是一家专业为片式电子元器件(被动元件、分立器件、集成电路及LED)配套生产电子薄型载带、上下胶带、离型膜、流延膜等产品的国家高新技术企业,主要产品有分切纸带、打孔经带、压孔纸带、上下胶带、塑料载带及其…

leetcode数组-有序数组的平方

题目 题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/ 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 输入:nums [-4,-1,0,3,10] 输出&#xff…

基于微信小程序的医院挂号预约系统设计与实现

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大…

密码学基础——DES算法

前面的密码学基础——密码学文章中介绍了密码学相关的概念,其中简要地对称密码体制(也叫单钥密码体制、秘密密钥体制)进行了解释,我们可以知道单钥体制的加密密钥和解密密钥相同,单钥密码分为流密码和分组密码。 流密码&#xff0…

Redis分布式锁详解

Redis分布式锁详解 分布式锁是在分布式系统中实现互斥访问共享资源的重要机制。Redis因其高性能和原子性操作特性,常被用来实现分布式锁。 一、基础实现方案 1. SETNX EXPIRE方案(基本版) # 加锁 SETNX lock_key unique_value # 设置唯…

创建Linux虚拟环境并远程连接,finalshell自定义壁纸

安装VMware 这里不多赘述。 挂载Linux系统 1). 打开Vmware虚拟机,打开 编辑 -> 虚拟网络编辑器(N) 选择 NAT模式,然后选择右下角的 更改设置。 设置子网IP为 192.168.100.0,然后选择 应用 -> 确定。 解压 CentOS7-1.zip 到一个比较大…

podman和与docker的比较 及podman使用

Podman 与 Docker 的比较和区别 架构差异 Docker:采用客户端 - 服务器(C/S)架构,有一个以 root 权限运行的守护进程 dockerd 来管理容器的生命周期。客户端(docker 命令行工具)与守护进程进行通信&#x…