昇思25天学习打卡营第21天|CV-Shufflenet图像分类

打卡

目录

打卡

ShuffleNet 网络介绍

ShuffleNet 模型架构

Pointwise Group Convolution

Channel Shuffle

ShuffleNet模块

ShuffleNet 模块代码

构建ShuffleNet网络

模块代码

模型训练和评估

模型训练

模型评估

模型预测


ShuffleNet 网络介绍

ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型,和MobileNet, SqueezeNet等一样主要应用在移动端,所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作:Pointwise Group Convolution Channel Shuffle,这在保持精度的同时大大降低了模型的计算量。因此,ShuffleNetV1和MobileNet类似,都是通过设计更高效的网络结构来实现模型的压缩和加速。

ShuffleNet在保持不低的准确率的前提下,将参数量几乎降低到了最小,因此其运算速度较快,单位参数量对模型准确率的贡献非常高。了解ShuffleNet更多详细内容,详见论文ShuffleNet。

ShuffleNet 模型架构

ShuffleNet最显著的特点在于对不同通道进行重排来解决Group Convolution带来的弊端。通过改进ResNet 的 Bottleneck单元,在较小的计算量的情况下达到了较高的准确率。

Pointwise Group Convolution

  • Group Convolution(分组卷积)原理如下图。分组卷积的每一组的卷积核大小为in_channels/g*k*k,一共有g组,所有组共有 (in_channels/g*k*k)*out_channels 个参数,是正常卷积参数的1/g。分组卷积中,每个卷积核只处理输入特征图的一部分通道,其优点在于参数量会有所降低,但输出通道数仍等于卷积核的数量
  • Depthwise Convolution(深度可分离卷积)将组数g分为和输入通道相等的in_channels,然后对每一个in_channels做卷积操作,每个卷积核只处理一个通道,记卷积核大小为1*k*k,则卷积核参数量为:in_channels*k*k,得到的feature maps通道数与输入通道数相等
  • Pointwise Group Convolution(逐点分组卷积)在分组卷积的基础上,令每一组的卷积核大小为 1×1 ,卷积核参数量为(in_channels/g*1*1)*out_channels。

Channel Shuffle

Group Convolution的弊端在于不同组别的通道无法进行信息交流,堆积 GConv 层后一个问题是不同组之间的特征图是不通信的,这就好像分成了g个互不相干的道路,每一个人各走各的,这可能会降低网络的特征提取能力。这也是Xception,MobileNet等网络采用密集的1x1卷积(Dense Pointwise Convolution)的原因。

为了解决不同组别通道“近亲繁殖”的问题,ShuffleNet优化了大量密集的1x1卷积(在使用的情况下计算量占用率达到了惊人的93.4%),引入Channel Shuffle机制(通道重排)。这项操作直观上表现为将不同分组通道均匀分散重组,使网络在下一层能处理不同组别通道的信息。

如下图所示,对于g组,每组有n个通道的特征图,首先reshape成g行n列的矩阵,再将矩阵转置成n行g列,最后进行flatten操作,得到新的排列。这些操作都是可微分可导的且计算简单,在解决了信息交互的同时符合了ShuffleNet轻量级网络设计的轻量特征。

ShuffleNet模块

如下图,ShuffleNet对ResNet中的Bottleneck结构进行由(a)到(b), (c)的更改:

  1. 将开始和最后的1×1 卷积模块(降维、升维)改成 Point Wise Group Convolution;

  2. 为了进行不同通道的信息交流,再降维之后进行Channel Shuffle;

  3. 降采样模块中,3×3 Depth Wise Convolution的步长设置为2,长宽降为原来的一般,因此shortcut中采用步长为2的3×3 平均池化,并把相加改成拼接。

ShuffleNet 模块代码
class ShuffleV1Block(nn.Cell):def __init__(self, inp, oup, group, first_group, mid_channels, ksize, stride):super(ShuffleV1Block, self).__init__()self.stride = stridepad = ksize // 2self.group = groupif stride == 2:outputs = oup - inpelse:outputs = oupself.relu = nn.ReLU()branch_main_1 = [GroupConv(in_channels=inp, out_channels=mid_channels,kernel_size=1, stride=1, pad_mode="pad", pad=0,groups=1 if first_group else group),nn.BatchNorm2d(mid_channels),nn.ReLU(),]branch_main_2 = [nn.Conv2d(mid_channels, mid_channels, kernel_size=ksize, stride=stride,pad_mode='pad', padding=pad, group=mid_channels,weight_init='xavier_uniform', has_bias=False),nn.BatchNorm2d(mid_channels),GroupConv(in_channels=mid_channels, out_channels=outputs,kernel_size=1, stride=1, pad_mode="pad", pad=0,groups=group),nn.BatchNorm2d(outputs),]self.branch_main_1 = nn.SequentialCell(branch_main_1)self.branch_main_2 = nn.SequentialCell(branch_main_2)if stride == 2:self.branch_proj = nn.AvgPool2d(kernel_size=3, stride=2, pad_mode='same')def construct(self, old_x):left = old_xright = old_xout = old_xright = self.branch_main_1(right)if self.group > 1:right = self.channel_shuffle(right)right = self.branch_main_2(right)if self.stride == 1:out = self.relu(left + right)elif self.stride == 2:left = self.branch_proj(left)out = ops.cat((left, right), 1)out = self.relu(out)return outdef channel_shuffle(self, x):batchsize, num_channels, height, width = ops.shape(x)group_channels = num_channels // self.groupx = ops.reshape(x, (batchsize, group_channels, self.group, height, width))x = ops.transpose(x, (0, 2, 1, 3, 4))x = ops.reshape(x, (batchsize, num_channels, height, width))return x

构建ShuffleNet网络

ShuffleNet网络结构如下图。以输入图像 224×224,组数3(g = 3)为例,首先通过数量24,卷积核大小为3×3 ,stride为2的卷积层,输出特征图大小为112×112 ,channel为24;然后通过stride为2的最大池化层,输出特征图大小为56×56 ,channel数不变;再堆叠3个ShuffleNet模块(Stage2, Stage3, Stage4),三个模块分别重复4次、8次、4次,其中每个模块开始先经过一次下采样模块(上图(c)),使特征图长宽减半,channel翻倍(Stage2的下采样模块除外,将channel数从24变为240);随后经过全局平均池化,输出大小为1×1×960 ,再经过全连接层和softmax,得到分类概率。

模块代码

class ShuffleNetV1(nn.Cell):def __init__(self, n_class=1000, model_size='2.0x', group=3):super(ShuffleNetV1, self).__init__()print('model size is ', model_size)self.stage_repeats = [4, 8, 4]self.model_size = model_sizeif group == 3:if model_size == '0.5x':self.stage_out_channels = [-1, 12, 120, 240, 480]elif model_size == '1.0x':self.stage_out_channels = [-1, 24, 240, 480, 960]elif model_size == '1.5x':self.stage_out_channels = [-1, 24, 360, 720, 1440]elif model_size == '2.0x':self.stage_out_channels = [-1, 48, 480, 960, 1920]else:raise NotImplementedErrorelif group == 8:if model_size == '0.5x':self.stage_out_channels = [-1, 16, 192, 384, 768]elif model_size == '1.0x':self.stage_out_channels = [-1, 24, 384, 768, 1536]elif model_size == '1.5x':self.stage_out_channels = [-1, 24, 576, 1152, 2304]elif model_size == '2.0x':self.stage_out_channels = [-1, 48, 768, 1536, 3072]else:raise NotImplementedErrorinput_channel = self.stage_out_channels[1]self.first_conv = nn.SequentialCell(nn.Conv2d(3, input_channel, 3, 2, 'pad', 1, weight_init='xavier_uniform', has_bias=False),nn.BatchNorm2d(input_channel),nn.ReLU(),)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')features = []for idxstage in range(len(self.stage_repeats)):numrepeat = self.stage_repeats[idxstage]output_channel = self.stage_out_channels[idxstage + 2]for i in range(numrepeat):stride = 2 if i == 0 else 1first_group = idxstage == 0 and i == 0features.append(ShuffleV1Block(input_channel, output_channel,group=group, first_group=first_group,mid_channels=output_channel // 4, ksize=3, stride=stride))input_channel = output_channelself.features = nn.SequentialCell(features)self.globalpool = nn.AvgPool2d(7)self.classifier = nn.Dense(self.stage_out_channels[-1], n_class)def construct(self, x):x = self.first_conv(x)x = self.maxpool(x)x = self.features(x)x = self.globalpool(x)x = ops.reshape(x, (-1, self.stage_out_channels[-1]))x = self.classifier(x)return x

模型训练和评估

采用CIFAR-10数据集对ShuffleNet进行预训练。

  • CIFAR-10共有60000张32*32的彩色图像,均匀地分为10个类别,其中50000张图片作为训练集,10000图片作为测试集。
  • 使用 mindspore.dataset.Cifar10Dataset 接口下载并加载CIFAR-10的训练集。目前仅支持二进制版本(CIFAR-10 binary version)。
from download import download
import mindspore as ms
from mindspore.dataset import Cifar10Dataset
from mindspore.dataset import vision, transformsurl = "https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz"download(url, "./dataset", kind="tar.gz", replace=True)def get_dataset(train_dataset_path, batch_size, usage):image_trans = []if usage == "train":image_trans = [vision.RandomCrop((32, 32), (4, 4, 4, 4)),vision.RandomHorizontalFlip(prob=0.5),vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]elif usage == "test":image_trans = [vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]label_trans = transforms.TypeCast(ms.int32)dataset = Cifar10Dataset(train_dataset_path, usage=usage, shuffle=True)dataset = dataset.map(image_trans, 'image')dataset = dataset.map(label_trans, 'label')dataset = dataset.batch(batch_size, drop_remainder=True)return datasetdataset = get_dataset("./dataset/cifar-10-batches-bin", 128, "train")
batches_per_epoch = dataset.get_dataset_size()  ## 390

模型训练

用随机初始化的参数做预训练。

1)首先调用ShuffleNetV1定义网络,参数量选择"2.0x",并定义损失函数为交叉熵损失,学习率经过4轮的warmup后采用余弦退火,优化器采用Momentum

2)最后用train.model中的Model接口将模型、损失函数、优化器封装在model中,并用model.train()对网络进行训练。将ModelCheckpointCheckpointConfigTimeMonitorLossMonitor传入回调函数中,将会打印训练的轮数、损失和时间,并将ckpt文件保存在当前目录下。

import time
import mindspore
import numpy as np
from mindspore import Tensor, nn
from mindspore.train import ModelCheckpoint, CheckpointConfig, TimeMonitor, LossMonitor, Model, Top1CategoricalAccuracy, Top5CategoricalAccuracydef train():mindspore.set_context(mode=mindspore.PYNATIVE_MODE, device_target="Ascend")net = ShuffleNetV1(model_size="2.0x", n_class=10)loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)min_lr = 0.0005base_lr = 0.05lr_scheduler = mindspore.nn.cosine_decay_lr(min_lr,base_lr,batches_per_epoch*250,batches_per_epoch,decay_epoch=250)lr = Tensor(lr_scheduler[-1])optimizer = nn.Momentum(params=net.trainable_params(), learning_rate=lr, momentum=0.9, weight_decay=0.00004, loss_scale=1024)loss_scale_manager = ms.amp.FixedLossScaleManager(1024, drop_overflow_update=False)model = Model(net, loss_fn=loss, optimizer=optimizer, amp_level="O3", loss_scale_manager=loss_scale_manager)callback = [TimeMonitor(), LossMonitor()]save_ckpt_path = "./"config_ckpt = CheckpointConfig(save_checkpoint_steps=batches_per_epoch, keep_checkpoint_max=5)ckpt_callback = ModelCheckpoint("shufflenetv1", directory=save_ckpt_path, config=config_ckpt)callback += [ckpt_callback]print("============== Starting Training ==============")start_time = time.time()# 由于时间原因,epoch = 5,可根据需求进行调整model.train(5, dataset, callbacks=callback)use_time = time.time() - start_timehour = str(int(use_time // 60 // 60))minute = str(int(use_time // 60 % 60))second = str(int(use_time % 60))print("total time:" + hour + "h " + minute + "m " + second + "s")print("============== Train Success ==============")if __name__ == '__main__':train()

模型评估

设置好评估模型的路径后加载数据集,并设置Top 1, Top 5的评估标准,最后用model.eval()接口对模型进行评估。

from mindspore import load_checkpoint, load_param_into_netdef test():mindspore.set_context(mode=mindspore.GRAPH_MODE, device_target="Ascend")dataset = get_dataset("./dataset/cifar-10-batches-bin", 128, "test")net = ShuffleNetV1(model_size="2.0x", n_class=10)param_dict = load_checkpoint("shufflenetv1-5_390.ckpt")load_param_into_net(net, param_dict)net.set_train(False)loss = nn.CrossEntropyLoss(weight=None, reduction='mean', label_smoothing=0.1)eval_metrics = {'Loss': nn.Loss(), 'Top_1_Acc': Top1CategoricalAccuracy(),'Top_5_Acc': Top5CategoricalAccuracy()}model = Model(net, loss_fn=loss, metrics=eval_metrics)start_time = time.time()res = model.eval(dataset, dataset_sink_mode=False)use_time = time.time() - start_timehour = str(int(use_time // 60 // 60))minute = str(int(use_time // 60 % 60))second = str(int(use_time % 60))log = "result:" + str(res) + ", ckpt:'" + "./shufflenetv1-5_390.ckpt" \+ "', time: " + hour + "h " + minute + "m " + second + "s"print(log)filename = './eval_log.txt'with open(filename, 'a') as file_object:file_object.write(log + '\n')if __name__ == '__main__':test()

模型预测

import mindspore
import matplotlib.pyplot as plt
import mindspore.dataset as dsnet = ShuffleNetV1(model_size="2.0x", n_class=10)
show_lst = []
param_dict = load_checkpoint("shufflenetv1-5_390.ckpt")
load_param_into_net(net, param_dict)
model = Model(net)
dataset_predict = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = ds.Cifar10Dataset(dataset_dir="./dataset/cifar-10-batches-bin", shuffle=False, usage="train")
dataset_show = dataset_show.batch(16)
show_images_lst = next(dataset_show.create_dict_iterator())["image"].asnumpy()
image_trans = [vision.RandomCrop((32, 32), (4, 4, 4, 4)),vision.RandomHorizontalFlip(prob=0.5),vision.Resize((224, 224)),vision.Rescale(1.0 / 255.0, 0.0),vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),vision.HWC2CHW()]
dataset_predict = dataset_predict.map(image_trans, 'image')
dataset_predict = dataset_predict.batch(16)
class_dict = {0:"airplane", 1:"automobile", 2:"bird", 3:"cat", 4:"deer", 5:"dog", 6:"frog", 7:"horse", 8:"ship", 9:"truck"}
# 推理效果展示(上方为预测的结果,下方为推理效果图片)
plt.figure(figsize=(16, 5))
predict_data = next(dataset_predict.create_dict_iterator())
output = model.predict(ms.Tensor(predict_data['image']))
pred = np.argmax(output.asnumpy(), axis=1)
index = 0
for image in show_images_lst:plt.subplot(2, 8, index+1)plt.title('{}'.format(class_dict[pred[index]]))index += 1plt.imshow(image)plt.axis("off")
plt.show()

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

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

相关文章

数字图像处理笔记(三) ---- 傅里叶变换的基本原理

系列文章目录 数字图像处理笔记(一)---- 图像数字化与显示 数字图像处理笔记(二)---- 像素加图像统计特征 数字图像处理笔记(三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、傅里叶变换二、离散傅里叶变…

JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测

JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测 目录 JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现TTAO-Transformer-LSTM多变量回归预测,三角拓扑聚合…

【运维自动化-配置平台】模型及模型关联最小化实践

蓝鲸智云配置平台,以下简称配置平台 我们知道主机是配置平台最常见的管控资源对象,在业务拓扑里可以通过划分模块来清晰的可视化管理;那其他资源如何通过配置平台来纳管呢,比如网络设备交换机。场景需求:如何把交换机…

【Linux 驱动】IMX6ULL eLCDIF参考手册翻译

1. eLCDIF 1.1 概述 eLCDIF是一种通用的显示控制器,用于驱动各种尺寸和性能不同的显示设备。 eLCDIF块支持以下功能: 支持MPU接口(8080模式和6800模式)支持DOTCLK接口(RGB接口)VSYNC模式:针对高…

Maven高级——详解

目录 一、分模块设计 二、分模块设计小实践 三、Maven继承 1.继承关系实现 ​编辑 2.版本锁定 dependencyManagement 自定义属性/引用属性 四、Maven聚合 五、Maven私服 一、分模块设计 为什么要分模块设计,将项目按照功能拆分分成若干个子模…

QT串口和数据库通信

创建串口 串口连接客户端并向服务器发送消息 client.pro #------------------------------------------------- # # Project created by QtCreator 2024-07-02T14:11:20 # #-------------------------------------------------QT core gui network QT core gui…

房屋出租系统 学习笔记 韩顺平 零基础30天学会Java(2024.7.15)

代码见package houserent P362 房屋出租需求 P363 房屋出租设计 分层模式 P364 房屋出租工具 给了一个工具包:Utility,使用:String s2 Utility.readString(10,”hspedu”);来限制输入字符大小最大是10,同时初始化的值为hspedu&a…

完全移动huggingface模型仓库(不是简单mv)

Linux中移动huggingface模型仓库 参考链接 先在bashrc中配置: export HF_DATASETS_CACHE"/your/path/dataset" export HF_HOME"/your/path/" export HUGGINGFACE_HUB_CACHE"/your/path/hub" export TRANSFORMERS_CACHE"/your…

速腾聚创激光雷达复现FAST-LIO

目录 1.软件环境 2.测试执行 3.代码学习 3.1.找主节点代码文件 3.2.整体流程结构 3.3.具体函数理解 记录复现FAST-LIO算法的过程和,代码梳理和理解 1.软件环境 Windows 10(64bits) VMware 16 Pro Ubuntu 20.04 ROS Noetic FAST-LIO的简化版、注释版。感谢…

Hospital 14.6.0全开源医院管理预约系统源码

InfyHMS 具有 60 种功能和 9 种不同类型的用户类型, 他们可以登录系统并根据他们的角色访问他们的数据。 源码下载:https://download.csdn.net/download/m0_66047725/89580674 更多资源下载:关注我。

Top-down Microarchitecture Analysis Method

1、英文链接: 1. https://www.intel.com/content/www/us/en/docs/vtune-profiler/cookbook/2023-0/top-down-microarchitecture-analysis-method.html 2. http://portal.nacad.ufrj.br/online/intel/vtune2017/help/GUID-02271361-CCD4-410C-8338-4B8158157EB6.ht…

LC61----1374. 生成每种字符都是奇数个的字符串(字符串)---java版

1.题目 2.思路 (1)题目要生成每种字符是奇数个的字符串。 (2)所以直接用参数n%2来判断。 (3)返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。 (4)感觉题目不是很规范哈…

go程序在windows服务中优雅开启和关闭

本篇主要是讲述一个go程序,如何在windows服务中优雅开启和关闭,废话不多说,开搞!!!   使用方式:go程序 net服务启动 Ⅰ 开篇不利 Windows go进程编译后,为一个.exe文件,直接执行即…

知名医药医疗行业人工智能数字化转型讲师培训师唐兴通谈医药医疗销售与创新思维创新管理数字化AI及大客户销售医美生活美容品牌市场

​唐兴通 数字化商业创新顾问、数字化转型教练、沃顿商学院演讲嘉宾。全球商业思想大家EM罗杰斯(创新的扩散)、杰弗里摩尔(跨越鸿沟)、马修狄克逊(挑战式销售)、布兰登博格(竞合战略&#xff0…

css渐变色背景|<gradient

使用渐变色作为背景 可以直接将渐变色用作元素的背景&#xff0c;可以看做是一种特殊的背景图片。&#xff08;是作为背景background一个属性值不是背景颜色background-color的属性值 &#xff09; CSS 渐变是一种从一种颜色平滑过渡到另一种颜色的效果&#xff0c;由 <gra…

Java数据结构(四)——链表

文章目录 链表概念及结构单链表的实现LinkedList的使用构造方法遍历 LinkedList的模拟实现ArrayList与LinkedList区别链表的相关练习反转链表链表的中间结点链表的回文结构判断链表是否有环寻找入环的第一个结点 链表 概念及结构 链表是一种物理存储结构上非连续存储结构&…

【C语言】 二叉树创建(结构体,先序遍历,中序遍历,后续遍历)

二叉树的创建&#xff1a;首先先定义一个结构体&#xff0c;里面包含数据&#xff08;data&#xff09;&#xff0c;指向左子树的指针&#xff08;L&#xff09;&#xff0c;指向右子树的指针&#xff08;R&#xff09;三个部分 在创建树的函数中&#xff0c;首先先输入…

netty使用redis发布订阅实现消息推送

netty使用redis发布订阅实现消息推送 场景 项目中需要给用户推送消息: 接口 RestController public class PushApi {Autowiredprivate PushService pushService;/*** 消息推送* param query* return*/PostMapping("/push/message")public String push(RequestBody…

『 Linux 』信号的写入与保存

文章目录 信号的发送信号的保存sigset_t 类型与信号集操作函数阻塞信号集(信号屏蔽字)操作函数未决信号集操作函数验证阻塞信号集与未决信号集 信号的发送 $ kill -l1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10)…

EXCEL自动公式计算始终为0

如果你的数据单元格的左上角存在绿色的三角小箭头&#xff0c;那么就会造成这种问题&#xff1a; 你的数字是以文本形式存入的单元格 解决办法&#xff1a; 选中数据列&#xff0c;数据->分列 直接选择完成 此时就可以进行公式计算了