小杰深度学习(sixteen)——视觉-经典神经网络——MobileNetV2

作者:jie*日期:2025/10/19

7.MobileNetV2

1. 网络的背景
MobileNetV1 还不够轻量和高性能,为了让移动设备有更好的体验,Google 团队提出了 MobileNetV2 架构
MobileNetV2网络是由谷歌团队在2018年提出的,它相对于MobileNetV1而言,有着更高的准确率和更小的网络模型。
论文地址:https://arxiv.org/abs/1801.04381

Inverted Residuals and Linear Bottlenecks.pdf

2. 网络的创新

在paper中的Table 2中给出了网络结构的架构表,如下图所示(网络的结构):

上表中:
Input是每一层结构的输入矩阵尺寸和channel;Operator是操作;t是拓展因子,也就是倒置残差第一个 1x1 卷积,将原来通道放大几倍;c是输出通道数channel;n是bottleneck模块重复的次数;
s是步距,如果bottleneck重复,但只针对于第一次bottleneck的DW卷积,其他为1。
由网络结构的图可以看到最后一层是卷积层,起的是全连接层的作用,k是输出的类别,如果是ImageNet数据集,那么k就是1000。
注意:在每个DW卷积之后都有batchNorm操作。
注意:在第一个bottleneck结构中,由于t=1,所以并没有进行升维操作,即没有第一个Conv2D层。
拓展因子在MobileNetV2中第一层倒残差结构中是1,其它倒残差结构采取的是6

2.1 Inverted Residuals(倒残差结构)
ResNet残差结构是先用1x1的卷积降维,再升维。而在MobileNetV2中,是先升维,再降维,所以该结构叫倒残差结构,网络结构表格中的bottleneck就是倒残差结构。
先看一下残差结构,如下图所示:

残差结构的过程是:
11x1卷积降维
23x3卷积
31x1卷积升维
对输入特征矩阵进行利用1x1卷积进行降维,减少输入特征矩阵的channel,然后通过3x3的卷积核进行处理提取特征,最后通过1x1的卷积核进行升维,它的结构为两边深,中间浅的结构。
在MobileNetV2网络结构中,采用了倒残差结构,它的结构中间深,两边浅,如下图所示:

倒残差结构的过程是:
1首先会通过一个1x1卷积层来进行升维处理,在卷积后会跟有BN和Relu6激活函数
2紧接着是一个3x3大小DW卷积,卷积后面依旧会跟有BN和Relu6激活函数
3最后一个卷积层是1x1卷积,起到降维作用,注意卷积后只跟了BN结构,并没有使用Relu6激活函数。倒残差结构的具体过程如下图所示:

在MobileNetV1中,DW卷积的个数局限于上一层的输出通道数,无法自由改变,但是加入PW卷积之后,也就是升维卷积之后,DW卷积的个数取决于PW卷积的输出通道数,而这个通道数是可以任意指定的,因此解除了3x3卷积核个数的限制。
2.2 Relu6
从上图的倒残差结构图中可以看到,卷积之后跟着的激活函数不再是MobileNetV1的Relu激活函数,而是Relu6激活函数,它的表达式是:

图像如下:

可以看到Relu6激活函数是Relu的变种,在输入小于0时,结果为0,输入大于6时:结果为6。在0到6之间时:

y=x


为什么要是用Relu6替代Relu?
主要因为在移动端设备float16的低精度的时候,也能有很好的数值分辨率,因为Relu的输出范围为0到正无穷,如果对Relu的激活范围不加限制,激活值非常大,分布在一个很大的范围内,则低精度的float16无法很好地精确描述如此大范围的数值,带来精度损失,如果进行量化,Relu6能够有更好的量化表现和更小的精度下降。
2.3 Linear Bottlenecks
在倒残差结构的最后一个1x1的卷积层,使用的激活函数为线性激活函数(即不采用非线性激活,例如Relu或者Relu6,直接输出)
2.4 Shortcut
如下图所示,左侧为有shortcut连接的倒残差结构,右侧是无shortcut连接的倒残差结构:

shortcut将输入与输出直接进行相加,可以使得网络在较深的时候依旧可以进行训练。
注意:这里只有stride=1且输入特征矩阵与输出特征矩阵shape相同时才有shortcut连接。
2.5 拓展因子
paper的Table 1给出了倒残差结构的特征矩阵,如下图所示:

上图中的h和w是输入特征矩阵的高和宽,k是channel,t是拓展因子,即升维时的比例,例如输入特征矩阵维度是32,那么升维后就是32×t,即表格中的tk,k′ 是降维时卷积核的个数。

3.2 结构组件介绍

3.2.1 卷积

输入特征矩阵是(224 x 224 x 3),本层卷积核的宽、高、通道、个数是(3 x 3 x 3 x 32),步长为2,padding方式为SAME,经过计算可知,输出特征矩阵为(112 x 112 x 32)。

本层之后要经过Relu6激活函数,如下图:

3.2.2 bottleneck结构

此层bottleneck结构无第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(112 x 112 x 32)。

本bottleneck结构第一层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 32),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(112 x 112 x 32)。

本bottleneck结构第二层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 32 x 16),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(112 x 112 x 16)。

本结构如下图:

3.2.3 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(112 x 112 x 16)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 16 x 96),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(112 x 112 x 16)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 96),padding方式为SAME,步长为2,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(56 x 56 x 96)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 96 x 24),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(56 x 56 x 24)。

本结构如下图:

3.2.4 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(56 x 56 x 24)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 24 x 144),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(56 x 56 x 144)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 144),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(56 x 56 x 144)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 144 x 24),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(56 x 56 x 24)。

本结构如下图:

3.2.5 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(56 x 56 x 24)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 24 x 144),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(56 x 56 x 144)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 144),padding方式为SAME,步长为2,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 144)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 144 x 32),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(28 x 28 x 32)。

本结构如下图:

3.2.6 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(28 x 28 x 32)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 32 x 192),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 192)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 192),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 192)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 192 x 32),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(28 x 28 x 32)。

本结构如下图:

3.2.7 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(28 x 28 x 32)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 32 x 192),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 192)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 192),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 192)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 192 x 32),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(28 x 28 x 32)。

本结构如下图:

3.2.8 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(28 x 28 x 32)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 32 x 192),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(28 x 28 x 192)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 192),padding方式为SAME,步长为2,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 192)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 192 x 64),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 64)。

本结构如下图:

3.2.9 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 64)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 64 x 384),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 384),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 384 x 64),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 64)。

本结构如下图:

3.2.10 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 64)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 64 x 384),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 384),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 384 x 64),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 64)。

本结构如下图:

3.2.11 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 64)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 64 x 384),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 384),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 384 x 64),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 64)。

本结构如下图:

3.2.12 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 64)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 64 x 384),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 384),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 384)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 384 x 96),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 96)。

本结构如下图:

3.2.13 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 96)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 96 x 576),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 576)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 576),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 576)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 576 x 96),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 96)。

本结构如下图:

3.2.14 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 96)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 96 x 576),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 576)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 576),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 576)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 576 x 96),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(14 x 14 x 96)。

本结构如下图:

3.2.15 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(14 x 14 x 96)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 96 x 576),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(14 x 14 x 576)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 576),padding方式为SAME,步长为2,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 576)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 576 x 160),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(7 x 7 x 160)。

本结构如下图:

3.2.16 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(7 x 7 x 160)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 160 x 960),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 960),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 960 x 160),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(7 x 7 x 160)。

本结构如下图:

3.2.17 bottleneck结构

此层bottleneck结构有第一层卷积层,有shortcut结构。

本bottleneck结构输入特征矩阵是(7 x 7 x 160)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 160 x 960),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 960),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 960 x 160),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(7 x 7 x 160)。

本结构如下图:

3.2.18 bottleneck结构

此层bottleneck结构有第一层卷积层,无shortcut结构。

本bottleneck结构输入特征矩阵是(7 x 7 x 160)。

本bottleneck结构第一层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 160 x 960),padding方式为SAME,步长为1,经过Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第二层DwiseConv2D卷积核的宽、高、个数是(3 x 3 x 960),padding方式为SAME,步长为1,经过batchNorm进行归一化,以及Relu6激活函数,经过计算可知,输出特征矩阵为(7 x 7 x 960)。

本bottleneck结构第三层Conv2D卷积核的宽、高、通道、个数是(1 x 1 x 960 x 320),padding方式为SAME,步长为1,经过计算可知,输出特征矩阵为(7 x 7 x 320)。

本结构如下图:

3.2.19 卷积

输入特征矩阵是(7 x 7 x 320),本层卷积核的宽、高、通道、个数是(1 x 1 x 320 x 1280),步长为1,padding方式为SAME,经过计算可知,输出特征矩阵为(7 x 7 x 1280)。

本层之后要经过Relu6激活函数,如下图:

3.2.20 池化-降采样

池化方式为AvgPool,输入特征矩阵是(7 x 7 x 1280),池化核大小为7,步长为1,经过计算可知,输出特征矩阵为(1 x 1 x 1280)。

如下图:

3.2.21 卷积

输入特征矩阵是(1 x 1 x 1280),本层卷积核的宽、高、通道、个数是(1 x 1 x 1280 x 1000),步长为1,padding方式为SAME,经过计算可知,输出特征矩阵为(1 x 1 x 1000)。

本层之后要Squeeze进行展平,即使输出矩阵(1 x 1 x 1000)转换成1000个节点,如下图:

3.2.22 Softmax

最后通过Softmax实现将多分类的输出值转换为范围在[0, 1]和为1的概率分布,如下图:

4 代码展示

1from torch import nn
2import  torch
3
4#卷积 +批归一化+激活函数的组合模块
5class ConvBNRelu(nn.Module):
6    def __init__(self,in_channels, out_channels, kernel_size=3, stride=1, padding=0, groups=1,
7                 activation=True):
8        super(ConvBNRelu,self).__init__()
9        if padding=='same':
10            padding=(kernel_size-1)//2
11        #卷积层,groups=1为标准卷积,groups=in_channels为深度可分离卷积
12        self.layers=[nn.Conv2d(in_channels=in_channels,out_channels=out_channels,
13                          kernel_size=kernel_size,stride=stride,padding=padding,groups=groups,bias=False)]
14        self.layers.append(nn.BatchNorm2d(out_channels))
15        #激活函数层,使用relu6限制激活函数范围,适合移动端部署
16        if activation:
17            self.layers.append(nn.ReLU6(inplace=True))
18        self.layers2=nn.Sequential(*self.layers)
19
20    def forward(self,x):
21        return self.layers2(x)
22
23#倒残差块:MobileNetV2的核心组件,先升维再降维
24class InvertedResidualBlock(nn.Module):
25    def __init__(self,in_channels, t, c, s):
26        """
27             参数:
28                 in_channels: 输入通道数
29                 t: 扩展因子,决定升维倍数
30                 c: 输出通道数
31                 s:
32        """
33        super(InvertedResidualBlock,self).__init__()
34        #扩展卷积:使用1x1卷积增加通道数
35        self.exp=ConvBNRelu(in_channels=in_channels,out_channels=in_channels*t,kernel_size=1,stride=1)#现在设置stride为1
36        #深度卷积,使用3x3深度可分离卷积进行处理空间信息
37        self.depthwise=ConvBNRelu(in_channels=in_channels*t,out_channels=in_channels*t,kernel_size=3,stride=s,padding=1,groups=in_channels*t)
38
39        #逐点卷积,使用1x1卷积降低通道数,不使用激活函数保留特征信息
40        self.pointwise=ConvBNRelu(in_channels=in_channels*t,out_channels=c,kernel_size=1,activation=False)
41        #是否进行残差连接:输入输出通道数相同且步长为1时,使用残差链接
42        self.is_res=in_channels==c and s==1
43    def forward(self,x):
44        identity=x #保存输入作为残差
45        x=self.exp(x)
46        x=self.depthwise(x)
47        x=self.pointwise(x)
48        if self.is_res:
49            x = identity + x  # 残差连接
50        return x
51
52
53class BottleneckLayer(nn.Module):
54    def __init__(self,in_channels, t, c, n, s):
55        """
56        参数:
57            in_channels: 输入通道数
58            t: 扩展因子
59            c: 输出通道数
60            n: 堆叠的残差块数量
61            s: 第一个残差块的步长,其余残差块步长为1
62        """
63        super(BottleneckLayer,self).__init__()
64        self.stack=nn.Sequential(
65            InvertedResidualBlock(in_channels,t,c,s), # 第一个残差块可能改变通道数和分辨率
66            #后续残差块保持通道数和分辨率不变,仅使用步长为1
67            *(InvertedResidualBlock(c,t,c,1)for _ in range(n-1))
68        )
69    def forward(self,x):
70        return self.stack(x)
71
72# MobileNetV2主模型
73class MobileNetV2(nn.Module):
74    def __init__(self,num_classes=1000):
75        super(MobileNetV2,self).__init__()
76        #初始化卷积层:提取基础的特征
77        self.c1=ConvBNRelu(in_channels=3,out_channels=32,kernel_size=3,stride=2,padding=1)
78        #7个瓶颈层模块(倒残差结构),逐步提取特征并降低空间分辨率(hxw的尺寸)
79        self.bottleneck1=BottleneckLayer(32,1,16,1,1)#第一层不进行下采样
80        self.bottleneck2 = BottleneckLayer(16, 6, 24, 2, 2)
81        self.bottleneck3 = BottleneckLayer(24, 6, 32, 3, 2)
82        self.bottleneck4 = BottleneckLayer(32, 6, 64, 4, 2)
83        self.bottleneck5 = BottleneckLayer(64, 6, 96, 3, 1)  # 保持分辨率不变
84        self.bottleneck6 = BottleneckLayer(96, 6, 160, 3, 2)
85        self.bottleneck7 = BottleneckLayer(160, 6, 320, 1, 1)
86        #最终特征提取层
87        # 最终特征提取层
88        self.c2 = ConvBNRelu(320, 1280, 1)
89        #全局平均池化,将特征压缩为1x1
90        self.avg_pool=nn.AdaptiveAvgPool2d((1,1))
91        #使用普通池化转化成1x1
92        # self.avg_pool2=nn.AvgPool2d((7,7))
93        #输出层 分类器,使用1x1卷积直接映射为类别数
94        self.c3=nn.Conv2d(in_channels=1280,out_channels=num_classes,kernel_size=1)
95    def forward(self,x):
96        # 特征提取路径
97        x = self.c1(x)
98        x = self.bottleneck1(x)
99        x = self.bottleneck2(x)
100        x = self.bottleneck3(x)
101        x = self.bottleneck4(x)
102        x = self.bottleneck5(x)
103        x = self.bottleneck6(x)
104        x = self.bottleneck7(x)
105        x = self.c2(x)
106
107        # 分类路径
108        x = self.avg_pool(x)
109        x = self.c3(x)
110        out = x.view(x.size(0), -1)  # 展平为二维张量
111        return out
112if __name__ == '__main__':
113    #模型测试 输入5张 224x224的RGB图像
114    model=MobileNetV2()
115    x=torch.rand(5,3,224,224)
116    print(model(x).shape)  #输出形状[5,1000]
117

小杰深度学习(sixteen)——视觉-经典神经网络——MobileNetV2》 是转载文章,点击查看原文


相关推荐


C#:函数默认参数
曹牧2025/10/17

C#函数默认参数允许在方法定义时为参数指定默认值,当调用时未提供该参数值则自动使用默认值:    ‌1、基本语法‌     在方法声明中通过参数名=默认值形式定义,例如void Print(string msg="default")。调用时可省略有默认值的参数Print(),此时msg取值为"default"。    ‌2、使用规则‌         默认参数必须从右向左连续定义,即某个参数有默认值后,其右侧所有参数必须都有默认值        默认值必须是编译时常量,不支持运行时动态赋值


【项目实战 Day12】springboot + vue 苍穹外卖系统(Apache POI + 工作台模块 + Excel表格导出 完结)
Roye_ack2025/10/16

目录 一、工作台模块 1、查询今日运营数据 - GET接口 (1)需求分析 (2)代码开发 2、查询今日运营数据 - GET接口 (1)需求分析 (2)代码开发 3、查询菜品总览 - GET接口 (1)需求分析 (2)代码开发 4、查询套餐总览 - GET接口 (1)需求分析 (2)代码开发 二、Excel表格导出 1、Apache POI (1)入门案例 2、导出Excel表格模块 (1)需求分析 (2)代码开发 【1】导入excel模板文件 【2】c


【HarmonyOS Bug踩坑】主窗口调用的接口,UI在子窗口异常显示
GeorgeGcs2025/10/15

【HarmonyOS Bug踩坑】主窗口调用的UI表现在子窗口异常显示 一、问题现象: 这个问题的标题略显抽象,毕竟涉及到的异常表现形式太多,标题是临时拟定的。 说白了,这个问题是鸿蒙里经典的上下文指定问题。 异常的业务场景是,在主窗口之上,添加一个子窗口。当在主窗口里调用某些UI表现,例如:气泡,弹窗,模态窗口,自定义安全键盘,自定义loading等,你会发现,有时候都异常加载到子窗口中了,并没有在主窗口显示。如下图所示: import { window } from '@kit.ArkUI


k8s-pod的启动
Code Rhythm2025/10/13

k8s-pod的启动 一、命令行启动nginx的pod创建deployment访问节点中的nginx查看部署控制器和副本控制器模拟高可用,将k8s-3关机手动触发重建删除rs会重新启新的rs删除deploy,所管理的rs也会被删除 二、yaml文件启podkubectl apply 启动podkubectl apply 使用部署控制器启动pod 三、pod的启动流程四、pod的终止过程 官方文档:https://kubernetes.io/zh-cn/docs/concept


敏捷开发流程-精简版
暖阳_2025/10/12

敏捷开发流程 - 精简版(实战版) 版本: v1.0 更新日期: 2025-10-11 适用场景: 中小型团队快速迭代开发 🎯 流程全景图 📋 5大阶段详解 阶段1:需求收集 → 业务需求文档 负责人: 项目经理 输入: 用户原始需求(口头/邮件/会议记录) 核心工作: 收集用户需求 整理为层级结构(一级-二级-三级) 组织需求评审会①(内部简单评审) 产出物: ✅ 业务需求文档(层级结构) 评审点:需求评审会① 参与人:项目经理、产品经理 目的:快速确认需求方向和范围 输


门诊场景评测深度分析报告:医生-病人-测量代理交互对诊断影响机制研究(上)
Allen_Lyb2025/10/10

引言 医疗人工智能(AI)的发展正从静态问答系统向动态交互式决策助手演进,大型语言模型(LLM)在医学领域测评中展现出显著进步,如美国医学执照考试正确率从 2021 年 9 月的 38.1% 提升至 2023 年 11 月的 90.2%,超越人类专家平均水平(87%)[1][2]。然而,临床决策的复杂、顺序性本质与多模态数据收集需求,使得依赖静态问答的传统评估方法难以准确描绘 AI 系统的真实临床能力——研究表明,动态决策环境下诊断准确率可降至静态问答的 1/10 以下[3][4]。与此同时,


Android Studio 新功能 Journey Test:借助 AI 实现基于自然语言的 UI 测试用例编写
fundroid2025/10/9

在 Android 应用开发中,大家经常使用单元测试框架进行 UI 测试。随着技术演进,Android Studio 推出的 Journey Test 功能,依托 Gemini AI,为 UI 测试带来了全新的范式转变。 核心能力:自然语言与 AI 驱动的测试 Journey Test 最大的亮点在于结合了自然语言和 Gemini AI 的能力。开发者无需再埋头于复杂的代码编写,只需用日常的自然语言描述测试步骤,比如 “在邮箱输入框中输入 [email protected]”“验证是否显示‘邮箱为


【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
凉凉心.2025/10/7

1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册 2. 什么是服务注册与发现 Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心,而系统中的其他微服务使用Eureka的客户端连接到Eureka


Java分布式缓存的负载均衡与扩展性:构建高可用系统的隐形支柱
墨夶2025/10/6

Java与分布式缓存的“生死博弈” 在某个电商平台的双十一大促凌晨,当流量洪峰冲破百万QPS时,Java工程师们发现:那些精心设计的Redis集群、Ehcache本地缓存、以及看似简单的负载均衡策略,正在以肉眼可见的速度瓦解。这个残酷的现实揭示了一个真相:Java在分布式缓存中的角色,远不止是调用API那么简单。它需要像外科医生一样精准控制资源分配,像建筑大师一样设计可扩展的架构。 一、Java分布式缓存的“三体法则”:负载均衡的本质 1.1 负载均衡:分布式系统的“心脏起搏器” /


Python高校社团选择报名系统 微信小程序设计与实现
qq_31666783672025/10/4

目录 已开发项目效果实现截图技术路线核心代码参考示例结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 已开发项目效果实现截图 同行可拿货,招校园代理 本系统还支持springboot/laravel/express/nodejs/thinkphp/flask/django/ssm/springcloud 微服务分布式等框架 技术路线 开发语言:Python 框架:flask/django 开发软件:PyCharm/vscode 数据库

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0