MobileNetV2详细原理(含torch源码)

简介: MobileNetV2详细原理(含torch源码)—— cifar10

MobilneNetV2原理
MobileNetV2是由谷歌开发的一种用于移动设备的轻量级卷积神经网络。与传统卷积神经网络相比,它具有更高的计算效率和更小的模型尺寸,可以在移动设备上实现高精度的图像识别任务。

    MobileNetV2的主要原理是使用深度可分离卷积来减少模型的参数数量和计算量。深度可分离卷积将传统的卷积操作分解为两个独立的操作:深度卷积和逐点卷积。深度卷积仅在通道维度上进行卷积操作,而逐点卷积仅在空间维度上进行卷积操作。这种分解能大大降低计算复杂度,同时保持较高的分类精度。

    另外,MobileNetV2还使用了线性瓶颈函数来加速网络训练,以及Inverted Residuals结构来充分使用低维特征信息。


线性瓶颈结构:

image.png
MobileNetV2两种残差块:
image.png
它还采用了轻量级的特征网络Design Spaces提升性能的策略,优化卷积核大小和数量,调整网络宽度和深度,最终得到一个更加高效的网络。网络结构图如下:
image.png
MobileNetV2的创新点:
MobileNetV2相较于MobileNetV1在以下方面进行了创新:

Inverted Residuals:MobileNetV2使用了Inverted Residuals结构,将输入先进行低维变换,再使用残差模块加上上采样,最后使用1x1卷积进行通道变换,从而减少计算量。

Linear Bottlenecks: MobileNetV2使用1x1卷积核将输入通道数缩小到一个较小的值,然后进行卷积操作,最后再使用1x1卷积通道扩展回原来的通道数。这样可以减少计算量和参数量,同时提高模型准确度。

使用深度可分离卷积:MobileNetV2中使用了深度可分离卷积,在计算相同的特征图时用的参数远少于传统卷积。而且,深度可分离卷积允许使用不同的卷积核、池化层和标准化层,从而提高了模型的灵活性。

设计高效的shortcut连接:在MobileNetV2中,shortcut连接采用的是identity mapping方法,使用1x1卷积将跳过的特征图的通道数与当前特征图的通道数对应起来,同时这种结构可以避免梯度消失和梯度爆炸的问题,提高了模型的稳定性。

激活函数采用Scaled Exponential Linear Unit (SELU):MobileNetV2将激活函数采用了Scaled Exponential Linear Unit (SELU),可以在不增加计算量的情况下提高模型的准确性。

    总之,MobileNetV2通过使用深度可分离卷积和其他技术来减少计算量和模型尺寸,同时保持高精度的分类任务,是一种非常有前途的轻量级卷积神经网络。

MobileNetV2对比MobileNetV1
MobileNetV2相比于MobileNetV1,主要改进有以下几个方面:

更优的性能:MobileNetV2在ImageNet上的Top-1准确率为72.0%,相比MobileNetV1(70.6%)有显著提升。

更高的效率:MobileNetV2在相同的计算资源下,参数量比MobileNetV1少了40%,计算量比它少了30%。

更好的适应性:MobileNetV2引入了一些新的技术,例如倒置余弦线性单元(Inverted Residuals with Linear Bottlenecks)和线性瓶颈模块(Linear Bottlenecks),使得它更适应于移动设备上的实时推理场景。

更好的鲁棒性:MobileNetV2在对小型变形的物体分类和检测任务上,能够显著提高模型的准确率。

MobilneNetV2源码(torch版)

数据集运行代码时自动下载,如果网络比较慢,可以自行点击我分享的链接下载cifar数据集。

链接:https://pan.baidu.com/s/1kfF4WxfpXr4a-GnEugh3AA?pwd=kd9a#list/path=%2F
提取码:kd9a

此代码是使用的GPU运行的,如果没有GPU导致运行失败,就把代码中的device、.to(device)删除,使用默认CPU运行。

如果使用GPU,GPU显存小导致运行报错,就将主函数main()里面的batch_size调小即可。



from torch.utils.data import DataLoader
from torchvision.datasets import CIFAR10
from torchvision.transforms import transforms
from torch.autograd import Variable


import torch.nn as nn
import torch.nn.functional as F
import torch

class Block(nn.Module):
    def __init__(self, in_planes, out_planes, expansion, stride):
        super(Block, self).__init__()
        self.stride = stride

        planes = expansion * in_planes
        self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
        self.bn1 = nn.BatchNorm2d(planes)
        self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, groups=planes, bias=False)
        self.bn2 = nn.BatchNorm2d(planes)
        self.conv3 = nn.Conv2d(planes, out_planes, kernel_size=1, bias=False)
        self.bn3 = nn.BatchNorm2d(out_planes)

        self.shortcut = nn.Sequential()
        if stride == 1 and in_planes != out_planes:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_planes)
            )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = F.relu(self.bn2(self.conv2(out)))
        out = self.bn3(self.conv3(out))
        out += self.shortcut(x) if self.stride == 1 else out
        return out


class MobileNetV2(nn.Module):
    def __init__(self, num_classes=10):
        super(MobileNetV2, self).__init__()

        self.cfgs = [
            # t, c, n, s
            [1, 16, 1, 1],
            [6, 24, 2, 1],
            [6, 32, 3, 2],
            [6, 64, 4, 2],
            [6, 96, 3, 1],
            [6, 160, 3, 2],
            [6, 320, 1, 1],
        ]

        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(32)
        self.layers = self._make_layers(in_planes=32)
        self.conv2 = nn.Conv2d(320, 1280, kernel_size=1, bias=False)
        self.bn2 = nn.BatchNorm2d(1280)
        self.linear = nn.Linear(1280, num_classes)

    def _make_layers(self, in_planes):
        layers = []
        for t, c, n, s in self.cfgs:
            for i in range(n):
                stride = s if i == 0 else 1
                layers.append(Block(in_planes, c, t, stride))
                in_planes = c
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layers(out)
        out = F.relu(self.bn2(self.conv2(out)))
        out = F.avg_pool2d(out, 4)
        out = out.view(out.size(0), -1)
        out = self.linear(out)
        return out


if __name__ == '__main__':
    train_data = CIFAR10('cifar', train=True, transform=transforms.ToTensor())
    data = DataLoader(train_data, batch_size=148, shuffle=True)

    device = torch.device("cuda")
    net = MobileNetV2().to(device)
    print(net)
    cross = nn.CrossEntropyLoss().to(device)
    optimizer = torch.optim.Adam(net.parameters(), 0.0001)
    for epoch in range(10):
        for img, label in data:
            img = Variable(img).to(device)
            label = Variable(label).to(device)
            output = net.forward(img)
            loss = cross(output, label)
            loss.backward()
            optimizer.zero_grad()
            optimizer.step()
            pre = torch.argmax(output, 1)
            num = (pre == label).sum().item()
            acc = num / img.shape[0]
        print("epoch:", epoch + 1)
        print("loss:", loss.item())
        print("Accuracy:", acc)
    以上代码采用的是跟PyTorch官方模型一样的模型结构,在_make_layers函数中构建了7个Block块,每个Block块都是跟MobileNetV2一样的结构,通过自定义一个Block类来实现。在forward函数中,通过调用这7个Block块的方式构建整个网络的结构。在最后的分类层中,采用了一个线性层。 

    使用cifar10训练做测试。

训练10个epoch的效果
image.png

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
机器学习/深度学习 编解码 BI
RegNet架构复现--CVPR2020
在这项工作中,我们**提出了一种新的网络设计范式**。我们的目标是帮助促进对网络设计的理解,并发现跨环境通用的设计原则。我们不是专注于设计单个网络实例,而是设计参数化网络群体的网络设计空间。整个过程类似于经典的网络手动设计,但提升到了设计空间级别。使用我们的方法,我们探索了网络设计的结构方面,并**得出了一个由简单、规则的网络组成的低维设计空间,我们称之为** ==RegNet==。
2549 0
RegNet架构复现--CVPR2020
|
机器学习/深度学习 编解码 计算机视觉
【轻量化网络系列(2)】MobileNetV2论文超详细解读(翻译 +学习笔记+代码实现)
【轻量化网络系列(2)】MobileNetV2论文超详细解读(翻译 +学习笔记+代码实现)
3197 0
【轻量化网络系列(2)】MobileNetV2论文超详细解读(翻译 +学习笔记+代码实现)
|
Shell 网络架构 计算机视觉
YOLOv11改进策略【模型轻量化】| ShufflenetV2,通过通道划分构建高效网络
YOLOv11改进策略【模型轻量化】| ShufflenetV2,通过通道划分构建高效网络
557 14
|
编解码 人工智能 算法
【AI系统】EfficientNet 系列
本文介绍了EfficientNet系列模型,特别是EfficientNet V1和V2。EfficientNet V1通过NAS技术同时探索网络的宽度、深度和分辨率对模型性能的影响,提出了复合模型缩放方法,以平衡三者关系,实现高效模型扩展。EfficientNet V2在此基础上,引入Fused-MBConv模块,采用渐进式学习策略和自适应正则化技术,进一步提升了模型的训练速度和推理效率。
1075 6
【AI系统】EfficientNet 系列
|
机器学习/深度学习 网络架构 计算机视觉
目标检测笔记(一):不同模型的网络架构介绍和代码
这篇文章介绍了ShuffleNetV2网络架构及其代码实现,包括模型结构、代码细节和不同版本的模型。ShuffleNetV2是一个高效的卷积神经网络,适用于深度学习中的目标检测任务。
355 1
目标检测笔记(一):不同模型的网络架构介绍和代码
|
机器学习/深度学习 算法 计算机视觉
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)
6001 1
经典神经网络论文超详细解读(五)——ResNet(残差网络)学习笔记(翻译+精读+代码复现)
|
机器学习/深度学习 数据采集 数据挖掘
11种经典时间序列预测方法:理论、Python实现与应用
本文将总结11种经典的时间序列预测方法,并提供它们在Python中的实现示例。
3519 2
11种经典时间序列预测方法:理论、Python实现与应用
|
机器学习/深度学习 计算机视觉 文件存储
【轻量化网络系列(3)】MobileNetV3论文超详细解读(翻译 +学习笔记+代码实现)
【轻量化网络系列(3)】MobileNetV3论文超详细解读(翻译 +学习笔记+代码实现)
6686 0
【轻量化网络系列(3)】MobileNetV3论文超详细解读(翻译 +学习笔记+代码实现)
|
机器学习/深度学习 编解码 TensorFlow
MobileNetV3架构解析与代码复现
MobileNet模型基于深度可分离卷积,这是一种分解卷积的形式,将标准卷积分解为深度卷积和`1*1`的点卷积。对于MobileNet,深度卷积将单个滤波器应用于每个输入通道,然后,逐点卷积应用`1*1`卷积将输出与深度卷积相结合。
3220 0
MobileNetV3架构解析与代码复现
|
机器学习/深度学习 文件存储 算法框架/工具
【YOLOv8改进- Backbone主干】2024最新轻量化网络MobileNetV4替换YoloV8的BackBone
YOLO目标检测专栏聚焦于模型的改进和实战应用,介绍了MobileNetV4,它在移动设备上优化了架构。文章提到了UIB(通用反向瓶颈)模块,结合了多种结构,增强了特征提取;Mobile MQA是专为移动平台设计的注意力层,提升了速度;优化的NAS提升了搜索效率。通过这些创新,MNv4在不同硬件上实现了性能和效率的平衡,且通过蒸馏技术提高了准确性。模型在Pixel 8 EdgeTPU上达到87%的ImageNet-1K准确率,延迟仅为3.8ms。论文、PyTorch和TensorFlow实现代码链接也已提供。