轻量模型简介

轻量化模型
  • 1. 卷积
  • * 深度可分离卷积(Depthwise separable Convolution)
    
    • 分组卷积(Group Convolution)
  • 2. MobileNet
  • * 一个问题
    
  • 3. ShuffleNet
  • * channel shuffle
    
    • pointwise group convolutions
    • ShuffleNet unit
    • ShuffleNet
  • 4. SE模块
  • * Squeeze操作
    
    • Excitation操作
    • SE模块的加载
    • SE Block实现

1. 卷积

深度可分离卷积(Depthwise separable Convolution)

深度可分离卷积depthwise separable
convolution较多的应用在轻量级的网络,由depthwise(DW)和pointwise(PW)两个部分结合起来提取特征feature
map。相比常规的卷积操作,其参数数量和运算成本比较低。

Depthwise separable convolution将卷积操作分为两步,分别是逐点卷积 (PointWise
Convolution,PW)和逐通道卷积 (DepthWise Convolution,DW)。

  • DepthWise Convolution
    标准卷积操作将卷积核用于所有的输入通道上,如输入为3×224×224时,一个卷积核在3个通道上同时卷积操作,最终一个卷积核对应输出一个feature
    map,而DepthWise
    Convolution不同,它针对每个输入通道应用不同的卷积核,一个卷积核对应一个输入通道。DW卷积完全在二维平面内运算,卷积核数量与上一层的通道数相同,如下图所示

![通道卷积](https://img-
blog.csdnimg.cn/df5d291465104764ba56df86a9e24478.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
Depthwise Convolution完成后的Feature map数量与输入层的通道数相同,无法扩展Feature
map。而且这种运算对输入层的每个通道独立进行卷积运算,没有有效的利用不同通道在相同空间位置上的特征信息。因此需要PointWise
Convolution来将这些Feature map进行组合生成新的Feature map。

  • PointWise Convolution
    PointWise
    Convolution就是卷积核大小为1×1×M的标准卷积,M为上一层的输出通道数。PW卷积在ResNet中已经用到,使用1×1卷积降低维度。PW卷积运算会将上一步的feature
    map在深度方向上进行加权组合,生成新的feature map,与普通卷积相同,输出的feature
    map数量与卷积核数量保持一致,如下图所示,上一层输出深度为3,则卷积核大小为1×1×3 。
    PW卷积的作用是对DW后各通道的特征进行融合,使得不同通道在相同空间位置上的特征得到有效利用
    ![PW卷积](https://img-
    blog.csdnimg.cn/e333011d694148568ae7c48c325b9a3d.png?x-oss-
    process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

综合来看,Depthwise separable convolution运算过程如下。
![深度可分离卷积](https://img-
blog.csdnimg.cn/ef67dfe431cd46ae9359083fcd38e882.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
深度可分离卷积降低了参数数量和运算成本,以3×5×5的输入,要得到输出为4×3×3的输出为例,分别计算使用标准卷积和深度可分离卷积的参数量与运算量。

  1. 标准卷积
    由[3, 5, 5]获得[4, 3, 3],需要4个filter,每个大小为3×3,参数量为卷积核W x 卷积核H x 输入通道数 x 输出通道数 =
    4×3×3×3 = 108,计算量为卷积核W x 卷积核H x (图片W-卷积核W+1) x (图片H-卷积核H+1) x 输入通道数 x 输出通道数 =
    3×3×(5-2)×(5-2)×3×4 = 972 。

  2. Depthwise separable convolution
    首先考虑DW卷积,维度与输入通道数保持一致,则需要3个卷积核,每个大小为3×3,则参数量=27,计算量为243;
    再考虑PW卷积,卷积核大小为1×1×3,,共有4个,则参数量为1×1×3×4=12,运算量为1×1×3×3×3×4=108;

相加可以得到,深度可分离卷积共计参数量为39,运算量为351,与标准卷积的108,972相比缩小了很多。

分组卷积(Group Convolution)

分组卷积对输入进行分组,每组分别卷积,若输入为 C × H × W C×H×W C×H×W,卷积核数量为N,分为 G G G个组,每组需处理的输入为 C G
\frac{C}{G} GC​个,每组输出为 N G \frac{N}{G} GN​,设每个卷积核大小为 C G × K × K
\frac{C}{G}×K×K GC​×K×K,卷积核共有 N N N个,参数量为 N × C G × K × K N×\frac{C}{G}×K×K
N×GC​×K×K。
即常规卷积输出的特征图上,每一个点是由输入特征图 C × H × W C×H×W C×H×W个点计算得到的,分组卷积输出的特征图上,每一个点是由输入特征图
C G × H × W \frac{C}{G}×H×W GC​×H×W个点计算得到的,所以分组卷积的参数量是标准卷积的 1 G \frac{1}{G}
G1​

因为每组的卷积核只与该组的输入进行卷积,不会与其他组的输入计算,故运算量也大大减小。下图清晰的展示了分组卷积的运算。

![分组卷积](https://img-
blog.csdnimg.cn/8f754b2ddd7042279782d9c08a3e7af3.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

2. MobileNet

MobileNet的基本单元是depthwise separable
convolution,它们对参数规模和计算量的改进我们在上面已经有所解释,根据论文中进一步的推导,比较depthwise separable
convolution和标准卷积可以得到如下公式:

![卷积比较](https://img-
blog.csdnimg.cn/d4f24b1b4f0b4996b247559c0e0585c5.png#pic_center)
其中 N N N为输出特征图深度, D K D_K DK​为卷积核大小, N N N值一般较大,所以可以粗略地认为depthwise separable
convolution相较于标准卷积,其参数量可减少至后者的 1 D K 2 \frac{1}{D^2_K} DK2​1​。

MobileNet基本结构如下图右,
![MoblieNet基本结构](https://img-
blog.csdnimg.cn/58fc1b0e7ffb44c38f22bd45bb3d8151.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
基本单元即为可分离卷积单元,从代码角度来看MobileNet的Block更为清晰。

class Block(nn.Module):
    '''Depthwise conv + Pointwise conv'''
    def __init__(self, in_planes, out_planes, stride=1):
        super(Block, self).__init__()
        # DW卷积, 卷积核大小3×3, 分为 in_planes,各层单独进行卷积
        # 输入输出深度相同均为in_planes
        self.conv1 = nn.Conv2d(in_planes, in_planes, kernel_size=3, stride=stride, padding=1, groups=in_planes, bias=False)
        self.bn1 = nn.BatchNorm2d(in_planes)
        # PW 卷积, 1*1 的卷积核
        self.conv2 = nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=1, padding=0, bias=False)
        self.bn2 = nn.BatchNorm2d(out_planes)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.relu(self.bn2(self.conv2(out)))
        return out

MobileNet共有28层,第一层为标准3×3卷积,总体结构如下图
![MobileNet结构](https://img-
blog.csdnimg.cn/2ff5b14f1c2c45f3802f0821b6f66421.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_19,color_FFFFFF,t_70,g_se,x_16#pic_center)
模型在训练时使用了非常少的正则化以及数据增强技术,因为小模型很少有过拟合的问题,也没有使用side
heads或者标签平滑操作,因为深度卷积中参数量很小,所以也没有进行权重衰减。

MobileNet为了进一步缩小模型,引入了两个超参数——width multiplier和resolution
multiplier,前者按比例减少通道数,记为 α \alpha α,几个典型的取值为1, 0.75, 0.5和0.25,结合此参数,计算量为

![计算量a](https://img-
blog.csdnimg.cn/c93ec6047d114bee8049b01f8e66527c.png#pic_center)
后者按比例降低特征图大小,记为 ρ \rho ρ,例如原来输入特征图是224x224,可以减少为192x192,引入resolution
multiplier后,参数计算为

![计算2](https://img-
blog.csdnimg.cn/f766d5f245994a37ab3e45b85b94bebc.png#pic_center)
引入width multiplier和resolution
multiplier势必会降低MobileNet的性能,所以根据需要的accuracy和model size来选择其取值。

一个问题

在很多文章中提到了此时计算量的bottleneck是conv1x1 ,这是我现在还没能理解的地方,需要以后继续学习。

3. ShuffleNet

前面提到在MobileNet中,1×1卷积已成为继续缩减计算量的瓶颈,这时出现了ShuffleNet,它在Xception和ResNeXt基础上,使用pointwise
group convolutions减少1×1卷积的复杂性,并且为了克服分组卷积带来的副作用(分组之间的信息不流通),提出一种新的操作——channel
shuffle来帮助不同特征分组之间的信息“交流”。

ShuffleNet除了已经介绍的depthwise separable convolution,还使用了channel shuffle、pointwise
group convolutions来改进ResNet。

channel shuffle

channel shuffle操作基于分组卷积(group
convolution),分组卷积已在上面介绍过,如下图(a)所示,每个卷积核仅与其对应分组的feature
map做卷积,这样大大减少了计算量,但是会有“副作用”,对于输出特征,它仅仅关注学习所在分组的特征,某个通道的输出仅来自一小部分输入通道,这样具有很大的局限性,故作者提出channel
shuffle。
![channel shuffle](https://img-
blog.csdnimg.cn/3f6518e462d9422ab57c466608e2dcab.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
在(b)图中,在一次分组卷积GConv1后,对所得结果的feature划分为subgroups(在代码中可通过reshape和
transpose来实现),将subgroups顺序打乱后输入到GConv2的分组卷积核中,而( c
)图的思想与(b)图是一致的,这样就可以在一定程度上解决分组卷积通道信息不相关的问题。

对channel shuffle,原文中已解释的很明白

This can be efficiently and elegantly implemented by a channel shuffle
operation (Fig 1 (c )): suppose a convolutional layer with g groups whose
output has g × n channels; we first reshape the output channel dimension
into (g; n), transposing and then flattening it back as the input of next
layer.

即使两个卷积具有不同的组数,该操作仍然有效。此外,channel shuffle也是可微的,这意味着它可以嵌入到网络结构中进行端到端训练。

pointwise group convolutions

PW卷积为卷积核大小为1×1的卷积操作,pointwise group convolutions即为分组的PW卷积。

ShuffleNet unit

![shuffleNet unit](https://img-
blog.csdnimg.cn/8e537890de014401bc2012f07d7c9931.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
作者利用原始ResNet中的Bottleneck模块,逐步改进,最终形成ShuffleNet Unit。

图(a):用3×3的DW卷积代替Bottleneck中的3×3卷积;
图(b):用1×1的分组卷积代替原来的1×1卷积;
图(c):在short
cut上添加3×3的平均池化并设置stride=2,改变原有ResNet的Add操作为concat,即按channel合并,这使得在不增加额外计算成本的情况下,很容易扩大通道尺寸。

ShuffleNet

基于ShuffleNet Unit,提出ShuffleNet结构如下表
![结构](https://img-blog.csdnimg.cn/484188a471804cc5a78932abefec6830.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
ShuffleNet主要由ShuffleNet Unit堆叠而成,主体遵循ResNet的结构,分为3个stage,每个stage中用ShuffleNet
Unit代替原有的残差块,在ShuffleNet Unit中使用分组数g控制PW卷积的复杂度,使用不同组数和输出通道数,以确保计算量大致不变。

将上表中的ShuffleNet作为ShuffleNet 1×,在通道上取一个缩放因子 s s s,将其模型称为ShuffleNet s×, s s
s用于控制filters的数量,在整个ShuffleNet架构上,其复杂度的变化大概是 s 2 s^2 s2倍,不同参数的表现和计算量如下表所示

![ShuffleNet s×](https://img-
blog.csdnimg.cn/f5d37c0cbd2d4b219f62f9618b6f408b.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
ShuffleNet的实现代码:ShuffleNet V1
神经网络简介与代码实战

对于卷积模型压缩的几个变形,这篇文章介绍的很详细,可作为参考阅读:
深入剖析MobileNet和它的变种(例如:ShuffleNet)为什么会变快?

4. SE模块

SENet即Squeeze-and-Excitation
Networks,使用SE模块学习通道之间的相关性,通过对通道进行加权,强调有效信息,抑制无效信息。
SE模块分为Squeeze和Excitation两部分,很容易加载到已有的网络架构中,SE模块的结构如下图所示:
![SE结构](https://img-
blog.csdnimg.cn/1db71e1341d6440fac777f2501667550.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
可以看到,输入X( C ′ × H ′ × W ′ C’×H’×W’ C′×H′×W′)先经过一个 F t r F_{tr} Ftr​变换(eg.
卷积)获得特征图U( C × H × W C×H×W C×H×W),接着就要进行SE分支的操作。

Squeeze操作

Squeeze本质上是一个全局平均池化,顺着空间维度进行特征压缩,将每个二维的特征通道变成一个通道描述符(标量),这个描述符在某种程度上具有全局的感受野,并且输出的维度(
1 × 1 × C 1×1×C 1×1×C)与输入的特征通道数一致,它允许网络的所有层使用来自全局感受野的信息。

Excitation操作

输入为Squeeze的输出,维度为 1 × 1 × C 1×1×C 1×1×C。
Excitation操作基于特征通道间的相关性,对每个特征通道生成了一个权重,用于代表特征通道的重要程度,故Excitation的输出维度仍是C个标量( 1
× 1 × C 1×1×C 1×1×C)。
权重生成后,通过乘法逐通道地加权 到之前的特征上,完成通道维度上对原始特征的特征重标定

SE模块的加载

SE模块的简单性也使得它很容易加入到已有的网络结构中,原论文中举了两个例子,分别是Inception和ResNet并给出了详细的计算图,结合Inception网络的计算图,可以更好的理解SE模块的操作过程。
![Inception+SE](https://img-
blog.csdnimg.cn/6e2db645443843d79e8a2f73eba88ef4.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_17,color_FFFFFF,t_70,g_se,x_16#pic_center)
Squeeze操作即图中的Global Pooling,Excitation操作即后续的FC+RELU+FC+Sigmoid组合。
在进行Excitation时,第一次FC的输出维度上添加了一个衰减因子reduction ,这个参数的目的是为了减少通道个数从而降低计算量。

对Squeeze中的池化选择、Excitation中reduction值大小和激活函数选择,原论文中也做了不同尝试,可以查看原论文进行了解。

将SE加载到ResNet中,结构是相似的
![ResNet+SE](https://img-
blog.csdnimg.cn/3a03ebf442694ec4a00f80fd083b7d6a.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_19,color_FFFFFF,t_70,g_se,x_16#pic_center)
这时需要考虑的要更多一些,例如SE
block是加在ResNet哪个stage或者放在残差单元的哪个位置,论文也对不同情况进行了实验,如下图,将SE放在残差单元不同位置的结构
![SE不同位置](https://img-
blog.csdnimg.cn/0b4a26f7a1744bd7a5372e7979b046d1.png?x-oss-
process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAeWl6aGlfaGFv,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
不同实验的结果对比,参看原论文,不做介绍。

SE Block实现

根据结构图,使用pytorch可以快速完成SE模块的搭建,代码如下

class SELayer(nn.Module):
    def __init__(self, channel, reduction=16):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y.expand_as(x)
👉AI大模型学习路线汇总👈

大模型学习路线图,整体分为7个大的阶段:(全套教程文末领取哈)

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

👉大模型实战案例👈

光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

在这里插入图片描述

👉大模型视频和PDF合集👈

观看零基础学习书籍和视频,看书籍和视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
在这里插入图片描述
在这里插入图片描述

👉学会后的收获:👈

• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习框架等技术,这些技术的掌握可以提高程序员的编码能力和分析能力,让程序员更加熟练地编写高质量的代码。

👉获取方式:

😝有需要的小伙伴,可以保存图片到wx扫描二v码免费领取【保证100%免费】🆓

在这里插入图片描述

  • 21
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值