《昇思 25 天学习打卡营第 11 天 | ResNet50 图像分类 》

《昇思 25 天学习打卡营第 11 天 | ResNet50 图像分类 》

活动地址:https://xihe.mindspore.cn/events/mindspore-training-camp
签名:Sam9029


计算机视觉-图像分类,很感兴趣

且今日精神颇佳,一个字,学啊

上一节(ResNet50 迁移学习)直接应用了 ResNet50 模型却没有解释概念

这一节解释,虽然提前去了解了,还是温习一下

ResNet 网络: ResNet50 网络是 2015 年由微软实验室的何恺明提出,获得 ILSVRC2015 图像分类竞赛第一名。主要的特征如下:

残差学习(最重要的概念):ResNet50 的核心思想是引入了“残差学习”框架。在深度网络中,如果层数太多,网络的训练可能会变得困难,因为每增加一层,网络的性能反而可能下降。残差学习通过添加跳过(skip connections)或快捷连接(shortcut connections)解决了这个问题,允许网络学习残差函数,而不是直接学习未映射的特征表示。

层叠结构:ResNet50 包含 50 层深的网络结构,这些层被组织成多个残差块(residual blocks)。每个残差块包含两个卷积层,后面跟着批量归一化(Batch Normalization)和 ReLU 激活函数。

批量归一化:ResNet50 在每个卷积层之后使用批量归一化,这有助于加速收敛速度,同时减少对初始化的敏感性。

恒等快捷连接:在每个残差块中,输入通过一个恒等快捷连接(identity shortcut connection)直接添加到块的输出。这保证了在网络训练过程中,梯度可以有效地流动到较浅的层。

性能:由于其设计,ResNet50 在多个标准数据集(如 ImageNet 和 COCO)上表现出色,成为了许多计算机视觉任务的基准模型。

意思是啥呢?

看完了也不是很懂,但只要明白一个概念,就是很厉害,比起传统的 卷积化神经网络模型,resNet50 性能和识别误差都更小。

传统的卷积神经网络都是将一系列的卷积层和池化层堆叠得到的,但当网络堆叠到一定深度时,就会出现退化问题。

ResNet 网络模型就提出了残差网络结构(Residual Network)来减轻退化问题,使用 ResNet 网络可以实现搭建较深的网络结构(突破 1000 层)

使用实践

学习完概念,当然少不了实践拉,这次使用 CIFAR-10数据集 来进行 图像分类的模型训练

下载数据集
from download import downloadurl = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"download(url, "./datasets-cifar10-bin", kind="tar.gz", replace=True)

CIFAR-10 数据集主要是一些 airplane、automobile、bird、cat、deer、dog、frog、horse、ship、truck,可查看(datasets-cifar10-bin/cifar-10-batches-bin/batches.meta.text)

  • 然后是一些 数据增强操作,略过

构建 ResNet50 网络模型

残差网络结构(Residual Network)是 ResNet 网络的主要亮点,ResNet 使用残差网络结构后可有效地减轻退化问题,实现更深的网络结构设计,提高网络的训练精度。

构建残差网络结构

请添加图片描述

这里的原理概念太难懂了,直接说主要特征和使用

残差网络结构主要由两种:

  • 一种是 Building Block,适用于较浅的 ResNet 网络,如 ResNet18 和 ResNet34;

  • 另一种是 Bottleneck,适用于层数较深的 ResNet 网络,如 ResNet50、ResNet101 和 ResNet152。

这一节使用 ResNet50 来构建 图像识别模型所以,我注重记录一下 Bottleneck 网络的构建

class ResidualBlock(nn.Cell):expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍def __init__(self, in_channel: int, out_channel: int,stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:super(ResidualBlock, self).__init__()self.conv1 = nn.Conv2d(in_channel, out_channel,kernel_size=1, weight_init=weight_init)self.norm1 = nn.BatchNorm2d(out_channel)self.conv2 = nn.Conv2d(out_channel, out_channel,kernel_size=3, stride=stride,weight_init=weight_init)self.norm2 = nn.BatchNorm2d(out_channel)self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,kernel_size=1, weight_init=weight_init)self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)self.relu = nn.ReLU()self.down_sample = down_sampledef construct(self, x):identity = x  # shortscuts分支out = self.conv1(x)  # 主分支第一层:1*1卷积层out = self.norm1(out)out = self.relu(out)out = self.conv2(out)  # 主分支第二层:3*3卷积层out = self.norm2(out)out = self.relu(out)out = self.conv3(out)  # 主分支第三层:1*1卷积层out = self.norm3(out)if self.down_sample is not None:identity = self.down_sample(x)out += identity  # 输出为主分支与shortcuts之和out = self.relu(out)return out
定义make_layer实现残差块的构建

这个函数的作用在于构建一个 由多个残差块组成的 网络层,是 ResNet 网络构建深度残差网络的基础

def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],channel: int, block_nums: int, stride: int = 1):down_sample = None  # shortcuts分支if stride != 1 or last_out_channel != channel * block.expansion:# 创建下采样层:down_sample = nn.SequentialCell([nn.Conv2d(last_out_channel, channel * block.expansion,# 使用1x1卷积进行通道数的调整和下采样, 紧接着是批量归一化层。kernel_size=1, stride=stride, weight_init=weight_init),nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)])layers = []layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))in_channel = channel * block.expansion# 循环创建剩余的残差块并添加到layers列表for _ in range(1, block_nums):layers.append(block(in_channel, channel))return nn.SequentialCell(layers)
定义 ResNet网络模型

最重要的步骤,定义 ResNet 模型类型函数

from mindspore import load_checkpoint, load_param_into_netclass ResNet(nn.Cell):def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],layer_nums: List[int], num_classes: int, input_channel: int) -> None:super(ResNet, self).__init__()self.relu = nn.ReLU()# 第一个卷积层,输入channel为3(彩色图像),输出channel为64self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)self.norm = nn.BatchNorm2d(64)# 最大池化层,缩小图片的尺寸self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')# 各个残差网络结构块定义self.layer1 = make_layer(64, block, 64, layer_nums[0])self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)# 平均池化层self.avg_pool = nn.AvgPool2d()# flattern层self.flatten = nn.Flatten()# 全连接层self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)def construct(self, x):# // ... 省略return x
  • 然后定义 _resnet 函数加载 使用 ResNet 网络模型类
  • 再使用 _resnet 函数构建 resnet50 网络模型
def resnet50(num_classes: int = 1000, pretrained: bool = False):"""ResNet50模型"""resnet50_url = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt"resnet50_ckpt = "./LoadPretrainedModel/resnet50_224_new.ckpt"return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,pretrained, resnet50_ckpt, 2048)
模型训练
# 定义ResNet50网络
network = resnet50(pretrained=True)# 全连接层输入层的大小
in_channel = network.fc.in_channels
fc = nn.Dense(in_channels=in_channel, out_channels=10)
# 重置全连接层
network.fc = fc# 设置学习率
num_epochs = 5
lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,step_per_epoch=step_size_train, decay_epoch=num_epochs)
# 定义优化器和损失函数
# // ... 省略# 定义训练函数
def train(data_loader, epoch): //epoch 即 num_epoch# // ... 省略# 定义预测函数
def evaluate(data_loader):# // ... 省略# 开始循环训练
print("Start Training Loop ...")for epoch in range(num_epochs):curr_loss = train(data_loader_train, epoch) # 训练curr_acc = evaluate(data_loader_val) # 预测print("Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]" % (epoch+1, num_epochs, curr_loss, curr_acc))# 保存当前预测准确率最高的模型# // ... 省略

使用 可视化模型 预测

定义 visualize_model 来检验我们训练的 ResNet 微调模型 在图像分类方面的效果

import matplotlib.pyplot as pltdef visualize_model(best_ckpt_path, dataset_val):num_class = 10  # 对狼和狗图像进行二分类net = resnet50(num_class)# 加载模型参数param_dict = ms.load_checkpoint(best_ckpt_path)ms.load_param_into_net(net, param_dict)# 加载验证集的数据进行验证data = next(dataset_val.create_dict_iterator())images = data["image"]labels = data["label"]# 预测图像类别output = net(data['image'])pred = np.argmax(output.asnumpy(), axis=1)# 图像分类classes = []with open(data_dir + "/batches.meta.txt", "r") as f:for line in f:line = line.rstrip()if line:classes.append(line)# 显示图像及图像的预测值plt.figure()for i in range(6):plt.subplot(2, 3, i + 1)# 若预测正确,显示为蓝色;若预测错误,显示为红色color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'plt.title('predict:{}'.format(classes[pred[i]]), color=color)picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))mean = np.array([0.4914, 0.4822, 0.4465])std = np.array([0.2023, 0.1994, 0.2010])picture_show = std * picture_show + meanpicture_show = np.clip(picture_show, 0, 1)plt.imshow(picture_show)plt.axis('off')plt.show()# 使用测试数据集进行验证
visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)

模型的预测结果,由章节解释 5 次训练就可以达到 70% 的准确率,

Epoch: [ 5/ 5], Average Train Loss: [0.745], Accuracy: [0.742], 差不多由 74%

当然想要继续提升,所需要的训练次数就会成倍的上升,训练成本也会添加,好在教程有说,80 次的 epochs 下就能达到理想的预测效果,

所有我实际测试一下,看看 80 的 ecochs 准确率是多少

实际测试日志输出

  • 10:42:29开始训练
# 第二次 5次训练时--就达到了 80%,多3次epoch 提升 10%
Epoch: [  5/ 80], Average Train Loss: [0.516], Accuracy: [0.802]# 8次训练--达到了 81%,多3次epoch 提升 1%
Epoch: [  8/ 80], Average Train Loss: [0.429], Accuracy: [0.817]# 8次训练--达到了 83%,多16次epoch 提升 3%, 这个提升就有些慢了,看来提升准确率很不容易
Epoch: [ 21/ 80], Average Train Loss: [0.211], Accuracy: [0.837]# 40次训练--达到了 84%,多35次epoch 提升 4%,预测一下 80次的时候会到90%,看可不可以,希望不要打脸
Epoch: [ 40/ 80], Average Train Loss: [0.077], Accuracy: [0.847]# 49-51次训练--准确率进行了 过山车 波动,下降之后又回升了
Epoch: [ 49/ 80], Average Train Loss: [0.056], Accuracy: [0.850]
Epoch: [ 50/ 80], Average Train Loss: [0.057], Accuracy: [0.847]
Epoch: [ 51/ 80], Average Train Loss: [0.052], Accuracy: [0.846]# --------------------------------------------------
Epoch: [ 80/ 80], Average Train Loss: [0.033], Accuracy: [0.849]
# --------------------------------------------------
#================================================================================
End of validation the best Accuracy is:  0.851, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt# 呃,80次的epochs 准确率是 84%, 过程最高时 85%

给我整嘛了,还是有好多的东西都不懂,不过也是初略的了解到了在图像识别方面 ResNet 网络模型的应用和突出的优势

所有内容仅为个人理解,若有错误与遗漏还望各位大佬指正


#================================================================================
End of validation the best Accuracy is: 0.851, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt

呃,80次的epochs 准确率是 84%, 过程最高时 85%


给我整嘛了,还是有好多的东西都不懂,不过也是初略的了解到了在图像识别方面 ResNet 网络模型的应用和突出的优势> 所有内容仅为个人理解,若有错误与遗漏还望各位大佬指正

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

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

相关文章

C++笔试强训1

文章目录 一、单项选择题二、编程题1. 组队竞赛1. 删除公共字符 一、单项选择题 解析&#xff1a; for(初始化部分;条件判断部分;调整部分) { //循环部分 } 本题中条件判断部分是(y 123) && (x < 4)&#xff0c;中间用&&相连&#xff0c;左右都为真时才为真…

STM32实战项目:从零打造GPS蓝牙自行车码表,掌握传感器、蓝牙、Flash存储等核心技术

一、 引言 骑行&#xff0c;作为一项绿色健康的运动方式&#xff0c;越来越受到人们的喜爱。而记录骑行数据&#xff0c;分析速度、里程等信息&#xff0c;则成为了许多骑行爱好者的追求。本篇文章将带你使用STM32单片机&#xff0c;DIY一款功能完备的自行车码表&#xff0c;记…

GRPC使用之ProtoBuf

1. 入门指导 1. 基本定义 Protocol Buffers提供一种跨语言的结构化数据的序列化能力&#xff0c;类似于JSON&#xff0c;不过更小、更快&#xff0c;除此以外它还能用用接口定义(IDL interface define language)&#xff0c;通protoc编译Protocol Buffer定义文件&#xff0c;…

vue学习笔记之组件传值

说起组件传值&#xff0c;首先要介绍再vue中什么是组件。 组件&#xff08;Component&#xff09;&#xff0c;是vue中很强大的一个功能&#xff0c;可以将一些可重用的代码进行重用。所有的vue组件同时也是vue实例&#xff0c;可以接受使用相同的选项对象和提供相同的生命周期…

高考志愿填报千万要注意这四点

在高考志愿填报过程中&#xff0c;确实有很多需要留心的点。我为你总结了四个关键点&#xff0c;希望能帮助你顺利完成志愿填报&#xff1a; 1、学校提供的支持 学校作为学生志愿填报咨询服务的主阵地&#xff0c;应提供体系化和制度化的支持。包括及时关注并传达政策动向和相…

Spring AOP源码篇三之 xml配置

简单代码示例, 了解Spring AOP基于xml的基本用法 xml配置&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

数学系C++ 排序算法简述(八)

目录 排序 选择排序 O(n2) 不稳定&#xff1a;48429 归并排序 O(n log n) 稳定 插入排序 O(n2) 堆排序 O(n log n) 希尔排序 O(n log2 n) 图书馆排序 O(n log n) 冒泡排序 O(n2) 优化&#xff1a; 基数排序 O(n k) 快速排序 O(n log n)【分治】 不稳定 桶排序 O(n…

Linux—网络设置

目录 一、ifconfig——查看网络配置 1、查看网络接口信息 1.1、查看所有网络接口 1.2、查看具体的网络接口 2、修改网络配置 3、添加网络接口 4、禁用/激活网卡 二、hostname——查看主机名称 1、查看主机名称 2、临时修改主机名称 3、永久修改主机名称 4、查看本…

Polkadot(DOT)即将爆雷?治理无能还歧视亚洲!资金将在两年内耗尽!是下一个FTX吗?

近期&#xff0c;关于Polkadot(DOT)生态圈的一系列负面消息引发了业界和投资者的广泛关注。从高昂的营销开支、缺乏实际业务亮点&#xff0c;再到治理问题和种族歧视指控&#xff0c;Polkadot似乎正面临着严峻的危机。业内人士警告&#xff0c;Polkadot的财政状况堪忧&#xff…

一个最简单的comsol斜坡稳定性分析例子——详细步骤

一个最简单的comsol斜坡稳定性分析例子——详细步骤 标准模型例子—详细步骤 线弹性模型下的地应力平衡预应力与预应变、土壤塑性和安全系数求解的辅助扫描

Vue2前端实现数据可视化大屏全局自适应 Vue实现所有页面自适应 Vue实现自适应所有屏幕

Vue自适应所有屏幕大小,目前页面自适应,尤其是数据可视化大屏的自适应更是案例很多 今天就记录一下使用Vue全局自适应各种屏幕大小的功能 在Vue.js中创建一个数据大屏,并使其能够自适应不同屏幕大小,通常涉及到布局的响应式设计、CSS媒体查询、以及利用Vue的事件系统来处理…

非同步升压转换器,效率95%你信吗?ETA1611输出电流2A, 22V DCDC

前言&#xff1a; 截止24年7月7日某创报价&#xff1a;500&#xff1a; &#xffe5;0.7856 / 个 建议使用前同时了解下方器件。 2毛钱的SOT23-5封装28V、1.5A、1.2MHz DCDC转换器用于LCD偏置电源和白光LED驱动等MT3540升压芯片 描述 ETA1611 SOT23-6封装 丝印GVYW&#xff0…

对话大模型Prompt是否需要礼貌点?

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 基于Dify的QA数据集构建&#xff08;附代码&#xff09;Qwen-2-7B和GLM-4-9B&#x…

YOLOv8结合SAHI推理图像和视频

文章目录 前言视频效果必要环境一、完整代码二、运行方法1、 推理图像2、 推理视频 总结 前言 在上一篇文章中&#xff0c;我们深入探讨了如何通过结合YOLOv8和SAHI来增强小目标检测效果 &#xff0c;并计算了相关评估指标&#xff0c;虽然我们也展示了可视化功能&#xff0c;…

入门PHP就来我这(高级)13 ~ 图书添加功能

有胆量你就来跟着路老师卷起来&#xff01; -- 纯干货&#xff0c;技术知识分享 路老师给大家分享PHP语言的知识了&#xff0c;旨在想让大家入门PHP&#xff0c;并深入了解PHP语言。 今天给大家接着上篇文章编写图书添加功能。 1 添加页面 创建add.html页面样式&#xff0c;废…

去O化神器 Exbase

随着去O化进程推动&#xff0c;很多旧业务依赖的oracle数据库&#xff0c;都需要实现做数据库的替换&#xff0c;当下能很好兼容Oracle&#xff0c;并实现异构数据库之间转换的工具并不多。这里给大家推荐一个商业工具数据库迁移工具exbase&#xff08;北京海量&#xff09;&am…

排序格式排序格式

排序格式排序格式

CosyVoice - 阿里最新开源语音克隆、文本转语音项目 支持情感控制及粤语 本地一键整合包下载

近日&#xff0c;阿里通义实验室发布开源语音大模型项目FunAudioLLM&#xff0c;而且一次包含两个模型&#xff1a;SenseVoice和CosyVoice。 CosyVoice专注自然语音生成&#xff0c;支持多语言、音色和情感控制&#xff0c;支持中英日粤韩5种语言的生成&#xff0c;效果显著优于…

Java多线程不会?一文解决——

方法一 新建类如MyThread继承Thread类重写run()方法再通过new MyThread类来新建线程通过start方法启动新线程 案例&#xff1a; class MyThread extends Thread {public MyThread(String name) {super(name);}Overridepublic void run() {for(int i0;i<10;i){System.out.…

深度学习中的Channel,通道数是什么?

参考文章&#xff1a; 直观理解深度学习的卷积操作&#xff0c;超赞&#xff01;-CSDN博客​​​​​​如何理解卷积神经网络中的通道&#xff08;channel&#xff09;_神经网络通道数-CSDN博客 深度学习-卷积神经网络—卷积操作详细介绍_深度卷积的作用-CSDN博客 正文&…