Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍

在这里插入图片描述

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学习学习和学业的先行者!
欢迎大家订阅专栏:零基础学Python:Python从0到100最新最全教程!

本文目录:

  • 一、ShuffleNet架构详解
    • 1. 通道混合机制(Channel Shuffle)
    • 2. 深度可分离卷积(Depthwise Separable Convolution)
    • 3. 轻量化设计
    • 4. 自适应平均池化(Adaptive Average Pooling)
  • 二、ShuffleNet架构
    • 1.网络结构概述
    • 2.代码实现
      • 2.1 ChannelShuffleModule 详解
        • 初始化方法 `__init__`
        • 前向传播方法 `forward`
      • 2.2 ShuffleNet 网络结构详解
        • 初始化方法 `__init__`
        • 前向传播方法 `forward`
        • 完整代码
  • 三、网络结构特点
    • 1. 深度可分离卷积:高效计算的核心
    • 2. 通道数的变化:动态调整通道数以优化性能
    • 3. 批量归一化和 ReLU:提升训练效率和稳定性
    • 4. 通道混合:增强通道间的信息流动
    • 5. 自适应平均池化:适应不同输入尺寸
  • 四、ShuffleNet 的优势总结

ShuffleNet是一种轻量级的深度学习模型,它在保持MobileNet的Depthwise Separable Convolution(深度可分离卷积)的基础上,引入了通道混合(Channel Shuffle)机制,以进一步提升模型的性能和效率。

image.png

一、ShuffleNet架构详解

1. 通道混合机制(Channel Shuffle)

通道混合是 ShuffleNet 的核心创新之一。在传统的深度学习模型中,卷积层的输出通道通常在空间上是高度相关的,这种相关性限制了模型的表示能力。ShuffleNet 通过通道混合机制打破了这种限制。具体来说,通道混合通过在组间重新排列通道,增强了通道间的信息流动,从而提高了模型的性能。
在实际应用中,通道混合模块的工作原理如下:假设输入张量的通道数为 C,我们将这些通道分成 G 个组,每个组包含 C/G 个通道。然后,我们在每个组内对通道进行重新排列,使得不同组的通道能够相互“交流”。这种重新排列的操作类似于洗牌,因此得名“通道混合”。

2. 深度可分离卷积(Depthwise Separable Convolution)

ShuffleNet 继承了 MobileNet 的深度可分离卷积技术。深度可分离卷积将标准的卷积操作分解为两个步骤:深度卷积(Depthwise Convolution)和逐点卷积(Pointwise Convolution)。深度卷积为每个输入通道单独应用一个卷积核,而逐点卷积则通过 1×1 卷积核将深度卷积的输出通道进行组合。这种分解方式显著减少了模型的参数数量和计算量,使得 ShuffleNet 能够在计算资源受限的设备上高效运行。

3. 轻量化设计

ShuffleNet 的设计目标是实现轻量化,以便在移动和嵌入式设备上高效运行。为了达到这一目标,ShuffleNet 在多个方面进行了优化。首先,它通过深度可分离卷积减少了参数数量和计算量。其次,ShuffleNet 采用了通道混合机制,进一步提高了模型的效率。此外,ShuffleNet 还引入了自适应平均池化(Adaptive Average Pooling),允许模型接受任意尺寸的输入,并将其转换为固定尺寸的输出,为后续的全连接层提供了便利。

4. 自适应平均池化(Adaptive Average Pooling)

自适应平均池化是 ShuffleNet 的一个重要组成部分。它允许模型接受任意尺寸的输入,并将其转换为固定尺寸的输出。这种灵活性使得 ShuffleNet 能够适应不同的输入尺寸,而无需对模型结构进行调整。在实际应用中,自适应平均池化通常用于将特征图的尺寸调整为 1×1,以便为全连接层提供输入。

二、ShuffleNet架构

1.网络结构概述

ShuffleNet主要由以下几个部分组成:

  1. 输入层:接收输入数据。
  2. 深度可分离卷积层:减少参数数量和计算量。
  3. 批量归一化层:提高训练效率和稳定性。
  4. ReLU激活函数:引入非线性。
  5. 通道混合模块:增强通道间的信息流动。
  6. 自适应平均池化层:适应不同尺寸的输入。
  7. 全连接层:输出分类结果。

这种结构设计使得 ShuffleNet 在保持高效性的同时,也具备了较强的特征提取能力。

2.代码实现

2.1 ChannelShuffleModule 详解

ChannelShuffleModule 是 ShuffleNet 中用于增强通道间信息流动的关键组件。它通过将输入张量的通道分成多个组,并在组内进行洗牌,从而实现通道间的信息重组。

初始化方法 __init__

在初始化方法中,我们接收两个参数:channelsgroupschannels 是输入张量的通道数,而 groups 是我们想要将这些通道分成的组数。我们通过一个断言来确保 channels 可以被 groups 整除,以保证每个组内的通道数是均匀的。

assert channels % groups == 0

接着,我们存储这些值,并计算每个组应有的通道数。

self.channel_per_group = self.channels // self.groups
前向传播方法 forward

在前向传播方法中,我们首先获取输入张量的尺寸,这包括批量大小 batch、通道数 _、序列长度 series 和模态数 modal

batch, _, series, modal = x.size()

然后,我们将输入张量重新排列成 groups 个组,每组包含 self.channel_per_group 个通道。这一步通过 reshape 方法实现。

x = x.reshape(batch, self.groups, self.channel_per_group, series, modal)

接下来是洗牌操作,这是通过 permute 方法实现的。我们交换 permute 方法中指定维度的顺序,从而在组内打乱通道的顺序。

x = x.permute(0, 2, 1, 3, 4)

最后,我们再次使用 reshape 方法将张量恢复到原始的形状,并将其返回。

x = x.reshape(batch, self.channels, series, modal)
return x

2.2 ShuffleNet 网络结构详解

ShuffleNet 类定义了整个网络的结构,它由多个组件组成,包括卷积层、批量归一化层、ReLU 激活函数、通道混合模块、自适应平均池化层和全连接层。

初始化方法 __init__

在初始化方法中,我们接收三个参数:train_shape 表示训练样本的形状,category 表示类别的数量,kernel_size 表示卷积核的尺寸。

def __init__(self, train_shape, category, kernel_size=3):

我们使用 nn.Sequential 来组织网络中的多个层,包括卷积层、批量归一化层、ReLU 激活函数和通道混合模块。

self.layer = nn.Sequential(# 第一个卷积层,用于减少输入通道并进行空间维度的下采样nn.Conv2d(1, 1, (kernel_size, 1), (2, 1), (kernel_size // 2, 0), groups=1),# ...
)

这里,我们首先使用一个深度可分离卷积来减少输入通道,并进行空间维度的下采样。然后,我们添加一个1x1的卷积层来扩展通道数,接着是批量归一化层、ReLU 激活函数和通道混合模块。

我们还添加了一个自适应平均池化层,它可以根据输入特征图的实际尺寸动态调整池化尺寸,以确保输出尺寸的一致性。

self.ada_pool = nn.AdaptiveAvgPool2d((1, train_shape[-1]))

最后,我们添加一个全连接层,它将展平的特征图映射到最终的分类结果。

self.fc = nn.Linear(512*train_shape[-1], category)
前向传播方法 forward

在前向传播方法中,我们首先将输入数据 x 通过 self.layer 中定义的卷积层和通道混合模块。

x = self.layer(x)

然后,我们将结果通过自适应平均池化层,以获得固定尺寸的特征图。

x = self.ada_pool(x)

接下来,我们将特征图展平,以适配全连接层。

x = x.view(x.size(0), -1)

最后,我们通过全连接层 self.fc 得到最终的分类结果,并将其返回。

x = self.fc(x)
return x
完整代码
import torch.nn as nn
class ChannelShuffleModule(nn.Module):def __init__(self, channels, groups):super().__init__()assert channels % groups == 0self.channels = channelsself.groups = groupsself.channel_per_group = self.channels // self.groupsdef forward(self, x):'''x.shape: [b, c, series, modal]'''batch, _, series, modal = x.size()x = x.reshape(batch, self.groups, self.channel_per_group, series, modal)x = x.permute(0, 2, 1, 3, 4)x = x.reshape(batch, self.channels, series, modal)return xclass ShuffleNet(nn.Module):def __init__(self, train_shape, category, kernel_size=3):super(ShuffleNet, self).__init__()self.layer = nn.Sequential(nn.Conv2d(1, 1, (kernel_size, 1), (2, 1), (kernel_size // 2, 0), groups=1),nn.Conv2d(1, 64, 1, 1, 0),nn.BatchNorm2d(64),nn.ReLU(),ChannelShuffleModule(channels=64, groups=8),nn.Conv2d(64, 64, (kernel_size, 1), (2, 1), (kernel_size // 2, 0), groups=64),nn.Conv2d(64, 128, 1, 1, 0),nn.BatchNorm2d(128),nn.ReLU(),ChannelShuffleModule(channels=128, groups=8),nn.Conv2d(128, 128, (kernel_size, 1), (2, 1), (kernel_size // 2, 0), groups=128),nn.Conv2d(128, 256, 1, 1, 0),nn.BatchNorm2d(256),nn.ReLU(),ChannelShuffleModule(channels=256, groups=16),nn.Conv2d(256, 256, (kernel_size, 1), (2, 1), (kernel_size // 2, 0), groups=256),nn.Conv2d(256, 512, 1, 1, 0),nn.BatchNorm2d(512),nn.ReLU(),ChannelShuffleModule(channels=512, groups=16))self.ada_pool = nn.AdaptiveAvgPool2d((1, train_shape[-1]))self.fc = nn.Linear(512*train_shape[-1], category)def forward(self, x):x = self.layer(x)x = self.ada_pool(x)x = x.view(x.size(0), -1)x = self.fc(x)return x

ShuffleNet 的初始化方法中,我们定义了一个包含多个卷积层、批量归一化层、ReLU 激活函数和通道混合模块的序列。每个卷积层都使用了深度可分离卷积技术,以减少参数数量和计算量。自适应平均池化层用于将不同尺寸的特征图转换为固定尺寸的输出,最后通过全连接层输出分类结果。

三、网络结构特点

1. 深度可分离卷积:高效计算的核心

深度可分离卷积 是 ShuffleNet 的关键特性之一,它将传统的卷积操作分解为两个独立的步骤:深度卷积(Depthwise Convolution)逐点卷积(Pointwise Convolution) 。这种分解方式极大地减少了模型的参数数量和计算量。

  • 深度卷积:深度卷积为每个输入通道单独应用一个卷积核,而不涉及通道间的交互。这种方式显著减少了卷积操作的计算复杂度。
  • 逐点卷积:逐点卷积使用 1×1 的卷积核对深度卷积的输出进行组合,增加了通道间的交互。这种组合方式不仅减少了参数数量,还保留了模型的表达能力。

在 ShuffleNet 中,深度可分离卷积被广泛应用于多个卷积层中。例如,在第一个卷积层中,深度可分离卷积将输入通道数减少到 1,然后通过 1×1 卷积将通道数扩展到 64。这种设计不仅减少了参数数量,还为后续的卷积层提供了足够的通道数。

2. 通道数的变化:动态调整通道数以优化性能

ShuffleNet 在网络的不同阶段动态调整通道数,以优化性能和计算效率。通过 1×1 卷积层,模型能够灵活地增加或减少通道数。例如,在第一个卷积层中,输入通道数被扩展到 64,为后续的深度可分离卷积提供了足够的输入通道。这种动态调整通道数的设计不仅提高了模型的灵活性,还减少了计算量。

此外,ShuffleNet 在后续的卷积层中逐步增加通道数,以适应更复杂的特征提取需求。例如,在第二个卷积层中,通道数从 64 增加到 128;在第三个卷积层中,通道数进一步增加到 256。这种逐步增加通道数的设计使得模型能够在不同阶段提取不同层次的特征,从而提高了模型的性能。

3. 批量归一化和 ReLU:提升训练效率和稳定性

在深度学习模型中,批量归一化(Batch Normalization)ReLU 激活函数 是两个重要的组件,它们能够显著提高模型的训练效率和稳定性。

  • 批量归一化:批量归一化通过归一化每个特征的输入,减少了内部协变量偏移(Internal Covariate Shift),从而加快了模型的收敛速度。在 ShuffleNet 中,每个卷积层后都添加了批量归一化层,以提高训练效率和模型的稳定性。
  • ReLU 激活函数:ReLU 激活函数通过引入非线性,使得模型能够学习复杂的特征表示。在 ShuffleNet 中,ReLU 激活函数被广泛应用于每个卷积层后,以提高模型的非线性表达能力。

4. 通道混合:增强通道间的信息流动

通道混合(Channel Shuffle) 是 ShuffleNet 的核心创新之一。在传统的卷积神经网络中,卷积层的输出通道通常在空间上是高度相关的,这种相关性限制了模型的表示能力。ShuffleNet 通过通道混合机制打破了这种限制。

通道混合模块的工作原理如下:假设输入张量的通道数为 C,我们将这些通道分成 G 个组,每个组包含 C/G 个通道。然后,我们在每个组内对通道进行重新排列,使得不同组的通道能够相互“交流”。这种重新排列的操作类似于洗牌,因此得名“通道混合”。

通道混合机制不仅增强了通道间的信息流动,还提高了模型的特征提取能力。在 ShuffleNet 中,通道混合模块被广泛应用于每个深度可分离卷积块后,以增强通道间的信息交互。

5. 自适应平均池化:适应不同输入尺寸

自适应平均池化(Adaptive Average Pooling) 是 ShuffleNet 的一个重要组成部分。它允许模型接受任意尺寸的输入,并将其转换为固定尺寸的输出。这种灵活性使得 ShuffleNet 能够适应不同的输入尺寸,而无需对模型结构进行调整。

在实际应用中,自适应平均池化通常用于将特征图的尺寸调整为 1×1,以便为全连接层提供输入。在 ShuffleNet 中,自适应平均池化层被放置在卷积层之后,以确保模型能够处理不同尺寸的输入数据。


ShuffleNet 的设计哲学在于通过 轻量化的设计 实现高效的特征提取。它通过 深度可分离卷积通道混合技术 减少了模型的参数数量和计算量,同时保持了较高的性能。这种设计使得 ShuffleNet 非常适合在计算资源受限的移动和嵌入式设备上部署,用于图像识别和处理任务。

具体来说,ShuffleNet 的轻量化设计主要体现在以下几个方面:

  • 深度可分离卷积:通过将卷积操作分解为深度卷积和逐点卷积,显著减少了参数数量和计算量。
  • 通道混合:通过在组内重新排列通道,增强了通道间的信息流动,提高了模型的特征提取能力。
  • 自适应平均池化:通过将特征图的尺寸调整为固定尺寸,使得模型能够适应不同尺寸的输入数据。
  • 动态调整通道数:通过 1×1 卷积层动态调整通道数,优化了模型的性能和计算效率。

这种轻量化设计不仅提高了 ShuffleNet 的计算效率,还使得它能够在移动和嵌入式设备上高效运行。ShuffleNet 的高效性和灵活性使其成为一种理想的轻量级深度学习模型,适用于各种资源受限的场景。

四、ShuffleNet 的优势总结

ShuffleNet 的设计哲学和轻量化设计使其具有以下优势:

  • 高效性:通过 深度可分离卷积通道混合技术,ShuffleNet 显著减少了参数数量和计算量,提高了模型的计算效率。
  • 灵活性:通过 自适应平均池化 和动态调整通道数,ShuffleNet 能够适应不同尺寸的输入数据,具有很强的灵活性。
  • 高性能:尽管参数数量和计算量减少,但 ShuffleNet 通过通道混合机制增强了通道间的信息流动,保持了较高的性能。
  • 适用性:ShuffleNet 的轻量化设计使其能够在移动和嵌入式设备上高效运行,适用于各种资源受限的场景。

尽管 ShuffleNet 在轻量级深度学习模型中已经取得了显著的成果,但仍有进一步优化的空间。未来,随着技术的不断发展,ShuffleNet 可以在更多领域进行应用,如 自动驾驶医疗影像分析自然语言处理 等。

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

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

相关文章

04树 + 堆 + 优先队列 + 图(D1_树(D1_基本介绍))

目录 一、什么是树? 二、相关术语 根结点 边 叶子结点 兄弟结点 祖先结点 结点的大小 树的层 结点的深度 结点的高度 树的高度 斜树 一、什么是树? 树是一种类似于链表的数据结构,不过链表的结点是以线性方式简单地指向其后继结…

Rust语言进阶之文件处理:std::fs用法实例(九十九)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【…

flowable expression和json字符串中的双引号内容

前言 最近做项目,发现了一批特殊的数据,即特殊字符",本身输入双引号也不是什么特殊的字符,毕竟在存储时就是正常字符,只不过在编码的时候需要转义,转义符是\,然而转义符\也是特殊字符&…

学习数据结构(5)单向链表的实现

(1)头部插入 (2)尾部删除 (3)头部删除 (4)查找 (5)在指定位置之前插入节点 (6)在指定位置之后插入节点 (7)删除…

14-8C++STL的queue容器

一、queue容器 (1)queue容器的简介 queue为队列容器&#xff0c;“先进先出”的容器 (2)queue对象的构造 queue<T>q; queue<int>que Int;//存放一个int的queue容器 queue<string>queString;//存放一个string的queue容器 (3)queue容器的push()与pop()方…

算法基础学习——快排与归并(附带java模版)

快速排序和归并排序是两种速度较快的排序方式&#xff0c;是最应该掌握的两种排序算法&#xff0c; &#xff08;一&#xff09;快速排序&#xff08;不稳定的&#xff09; 基本思想&#xff1a;分治 平均时间复杂度&#xff1a;O(nlogn) / 最慢O(n^2) / 最快O(n) 步骤&…

团体程序设计天梯赛-练习集——L1-028 判断素数

前言 一道10分的题目&#xff0c;相对来说比较简单&#xff0c;思考的时候要仔细且活跃&#xff0c;有时候在写代码的时候一些代码的出现很多余&#xff0c;并且会影响最后的结果 L1-028 判断素数 本题的目标很简单&#xff0c;就是判断一个给定的正整数是否素数。 输入格式…

安卓(android)订餐菜单【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的&#xff08;如果代码有错漏&#xff0c;可查看源码&#xff09; 1.掌握Activity生命周的每个方法。 2.掌握Activity的创建、配置、启动和关闭。 3.掌握Intent和IntentFilter的使用。 4.掌握Activity之间的跳转方式、任务栈和四种启动模式。 5.掌握在Activity中添加…

阿里云 - RocketMQ入门

前言 云消息队列 RocketMQ 版产品具备异步通信的优势&#xff0c;主要应用于【异步解耦】、【流量削峰填谷】等场景对于同步链路&#xff0c;需要实时返回调用结果的场景&#xff0c;建议使用RPC调用方案阿里云官网地址RocketMQ官网地址 模型概述 生产者生产消息并发送至服务…

MySQL注入中load_file()函数的使用

前言 在Msql注入中&#xff0c;load_file()函数在获得webshell以及提权过程中起着十分重要的作用&#xff0c;常被用来读取各种配置文件 而load_file函数只有在满足两个条件的情况下才可以使用&#xff1a; 文件权限&#xff1a;chmod ax pathtofile 文件大小&#xff1a;必须…

HTML<hgroup>标签

例子&#xff1a; 使用hgroup元素标记标题和段落是相关的&#xff1a; <hgroup> <h2>Norway</h2> <p>The land with the midnight sun.</p> </hgroup> 定义和用法&#xff1a; 标签<hgroup>用于包围标题和一个或多个<p&g…

深度学习的应用

目录 一、机器视觉 1.1 应用场景 1.2 常见的计算机视觉任务 1.2.1 图像分类 1.2.2 目标检测 1.2.3 图像分割 二、自然语言处理 三、推荐系统 3.1 常用的推荐系统算法实现方案 四、图像分类实验补充 4.1 CIFAR-100 数据集实验 实验代码 4.2 CIFAR-10 实验代码 深…

Redis篇 Redis如何清理过期的key以及对应的解决方法

Redis设置Key过期时间 在 Redis 中&#xff0c;可以通过特定的命令为 Key 设置过期时间&#xff0c;使得 Key 在一定时间后自动删除&#xff0c;这对于管理缓存、验证码等临时数据非常有用。 解决方法 1. Redis过期删除策略 1.1 如何实现过期策略 对一个 key 设置了过期时间…

Oracle Primavera P6 最新版 v24.12 更新 2/2

目录 一. 引言 二. P6 EPPM 更新内容 1. 用户管理改进 2. 更轻松地标准化用户设置 3. 摘要栏标签汇总数据字段 4. 将里程碑和剩余最早开始日期拖到甘特图上 5. 轻松访问审计数据 6. 粘贴数据时排除安全代码 7. 改进了状态更新卡片视图中的筛选功能 8. 直接从活动电子…

UE5.3 C++ CDO的初步理解

一.UObject UObject是所有对象的基类&#xff0c;往上还有UObjectBaseUtility。 注释&#xff1a;所有虚幻引擎对象的基类。对象的类型由基于 UClass 类来定义。 这为创建和使用UObject的对象提供了 函数&#xff0c;并且提供了应在子类中重写的虚函数。 /** * The base cla…

进阶数据结构——高精度运算

目录 前言一、高精度运算的定义与背景二、高精度运算的实现方式三、高精度运算的算法实现四、高精度运算的应用场景五、代码模版&#xff08;c&#xff09;六、经典例题1.[高精度加法](https://www.lanqiao.cn/problems/1516/learning/?page1&first_category_id1&name…

使用 cmake

使用前注意 : CMake是一种跨平台的构建系统&#xff0c;它用于管理软件构建过程&#xff0c;尤其适合多语言、多配置的项目。CMake不直接构建软件&#xff0c;而是生成特定构建工具&#xff08;如Makefile或Visual Studio项目&#xff09;所需的配置文件。 如果仅仅使用 qt 编…

(1)Linux高级命令简介

Linux高级命令简介 在安装好linux环境以后第一件事情就是去学习一些linux的基本指令&#xff0c;我在这里用的是CentOS7作演示。 首先在VirtualBox上装好Linux以后&#xff0c;启动我们的linux&#xff0c;输入账号密码以后学习第一个指令 简介 Linux高级命令简介ip addrtou…

【ArcMap零基础训练营】03 常用数据网站的数据下载及处理

03 常见数据网站的数据下载及处理 230108直播录像 常见数据下载及nc文件批处理 数据源网站汇总 名称网址备注RESDChttps://www.resdc.cn/中科院地理科学与资源研究所&#xff0c;非会员用户每日5次下载&#xff0c;大部分有用的资源均收费。TPDChttps://data.tpdc.ac.cn/国家青…

MySQL数据库(二)

一 DDL (一 数据库操作 1 查询-数据库&#xff08;所有/当前&#xff09; 1 所有数据库&#xff1a; show databases; 2 查询当前数据库&#xff1a; select database(); 2 创建-数据库 可以定义数据库的编码方式 create database if not exists ax1; create database ax2…