mobileNetV1网络解析,以及实现(pytorch)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: mobileNetV1网络解析,以及实现(pytorch)

Google提出了移动端模型MobileNet,其核心是采用了深度可分离卷积,其不仅可以降低模型计算复杂度,而且可以大大降低模型大小,适合应用在真实的移动端应用场景。在认识MobileNet之前,我们先了解一下什么是深度可分离卷积,以及和普通卷积的区别。

img

上面的图片展示了普通卷积和分组卷积的不同,下面我们通过具体的例子来看。

普通卷积

标准卷积运算量的计算公式:

$$ {FLOPs }=\left(2 \times C_{0} \times K^{2}-1\right) \times H \times W \times C_{1} $$

计算公式参考:深度学习之(经典)卷积层计算量以及参数量总结 (考虑有无bias,乘加情况) - 琴影 - 博客园 (cnblogs.com)

参数量计算公式:$K^{2} \times C_{0} \times C{1}$

$C_{0}$ :输入的通道。

K:卷积核大小。

H,W:输出 feature map的大小

$C_{1}$:输出通道的大小。

bias=False,即不考虑偏置的情况有-1,有True时没有-1。

举例:

输入的尺寸是227×227×3,卷积核大小是11×11,输出是6,输出维度是55×55,

我们带入公式可以计算出

参数量:

$11^2 \times 3 \times 6$=2178

运算量:

$2 \times 3 \times11^{2}\times 55\times 55 \times 6$=13176900

分组卷积

分组卷积则是对输入feature map进行分组,然后每组分别卷积。

假设输入feature map的尺寸仍为$C_{0}\times H \times W$,输出feature map的数量为$C_{1}$个,如果设定要分成G个groups,则每组的输入feature map数量为$\frac{C_{0}}{G}$,每组的输出feature map数量为$\frac{C{1}}{G}$,每个卷积核的尺寸为$\frac{C_{0}}{G}\times K \times K$,卷积核的总数仍为$C_{1}$个,每组的卷积核数量为$\frac{C{1}}{G}$,卷积核只与其同组的输入map进行卷积,卷积核的总参数量为$N\times \frac{C_{0}}{G}\times K \times K$,总参数量减少为原来的 $\frac{1}{G}$。

计算量公式:

$$ \left[\left(2 \times K^{2} \times C_{0} / g +1\right) \times H \times W \times C_{o} / g\right] \times g $$

分组卷积的参数量为:

$$ K * K * \frac{C_{0}}{g} * \frac{C_{1}}{g} * g $$

举例:

输入的尺寸是227×227×3,卷积核大小是11×11,输出是6,输出维度是55×55,group为3

我们带入公式可以计算出

参数量:

$11^2 \times \frac{3}{3} \times \frac{6}{3} \times 3$=726

运算量:

$\left[\left(2 \times 11^{2} \times3 / 3 +1\right) \times 55 \times 55 \times 6 / 3\right] \times 3$=2205225

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

设输入特征维度为$D_{F}\times D_{F}\times M$,M为通道数,$D_{k}$为卷积核大小,M为输入的通道数, N为输出的通道数,G为分组数。

当分组数量等于输入map数量,输出map数量也等于输入map数量,即M=N=G,N个卷积核每个尺寸为$D_{k}\times D_{k}\times 1 $时,Group Convolution就成了Depthwise Convolution。

逐点卷积就是把G组卷积用conv1x1拼接起来。如下图:

查看源图像

深度可分离卷积有深度卷积+逐点卷积。计算如下:

  • 深度卷积:设输入特征维度为$D_{F}\times D_{F}\times M$,M为通道数。卷积核的参数为$D_{k}\times D_{k}\times 1 \times M$。输出深度卷积后的特征维度为:$D_{F}\times D_{F}\times M$。卷积时每个通道只对应一个卷积核(扫描深度为1),所以 FLOPs为:$M\times D_{F}\times D_{F}\times D_{K}\times D_{K}$
  • 逐点卷积:输入为深度卷积后的特征,维度为$D_{F}\times D_{F}\times M$。卷积核参数为$1\times1\times M\times N$。输出维度为$D_{F}\times D_{F}\times N$。卷积过程中对每个特征做$1 \times 1$的标准卷积, FLOPs为:$N \times D_{F} \times D_{F}\times M$

    将上面两个参数量相加就是 $D_{k} \times D_{k} \times M+M \times N$

所以深度可分离卷积参数量是标准卷积的$\frac{D_{K} \times D_{K} \times M+M \times N}{D_{K} \times D_{K} \times M \times N}=\frac{1}{N}+\frac{1}{D_{K}^{2}}$

mobileNetV1

详见论文翻译:

https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/122692846

mobileNetV1的网络结构如下图.前面的卷积层中除了第一层为标准卷积层外,其他都是深度可分离卷积(Conv dw + Conv/s1),卷积后接了一个7*7的平均池化层,之后通过全连接层,最后利用Softmax激活函数将全连接层输出归一化到0-1的一个概率值,根据概率值的高低可以得到图像的分类情况。

image-20220125175313205

pytorch版本

import torch
import torch.nn as nn
import torchvision

def BottleneckV1(in_channels, out_channels, stride):
  return  nn.Sequential(
        nn.Conv2d(in_channels=in_channels,out_channels=in_channels,kernel_size=3,stride=stride,padding=1,groups=in_channels),
        nn.BatchNorm2d(in_channels),
        nn.ReLU6(inplace=True),
        nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=1),
        nn.BatchNorm2d(out_channels),
        nn.ReLU6(inplace=True)
    )

class MobileNetV1(nn.Module):
    def __init__(self, num_classes=1000):
        super(MobileNetV1, self).__init__()

        self.first_conv = nn.Sequential(
            nn.Conv2d(in_channels=3,out_channels=32,kernel_size=3,stride=2,padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU6(inplace=True),
        )

        self.bottleneck = nn.Sequential(
            BottleneckV1(32, 64, stride=1),
            BottleneckV1(64, 128, stride=2),
            BottleneckV1(128, 128, stride=1),
            BottleneckV1(128, 256, stride=2),
            BottleneckV1(256, 256, stride=1),
            BottleneckV1(256, 512, stride=2),
            BottleneckV1(512, 512, stride=1),
            BottleneckV1(512, 512, stride=1),
            BottleneckV1(512, 512, stride=1),
            BottleneckV1(512, 512, stride=1),
            BottleneckV1(512, 512, stride=1),
            BottleneckV1(512, 1024, stride=2),
            BottleneckV1(1024, 1024, stride=1),
        )

        self.avg_pool = nn.AvgPool2d(kernel_size=7,stride=1)
        self.linear = nn.Linear(in_features=1024,out_features=num_classes)
        self.dropout = nn.Dropout(p=0.2)
        self.softmax = nn.Softmax(dim=1)

        self.init_params()

    def init_params(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight)
                nn.init.constant_(m.bias,0)
            elif isinstance(m, nn.Linear) or isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x = self.first_conv(x)
        x = self.bottleneck(x)
        x = self.avg_pool(x)
        x = x.view(x.size(0),-1)
        x = self.dropout(x)
        x = self.linear(x)
        out = self.softmax(x)
        return out

if __name__=='__main__':
    model = MobileNetV1()
    print(model)

    input = torch.randn(1, 3, 224, 224)
    out = model(input)
    print(out.shape)
目录
相关文章
|
10天前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
86 30
|
14天前
|
机器学习/深度学习 人工智能 PyTorch
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
本文探讨了Transformer模型中变长输入序列的优化策略,旨在解决深度学习中常见的计算效率问题。文章首先介绍了批处理变长输入的技术挑战,特别是填充方法导致的资源浪费。随后,提出了多种优化技术,包括动态填充、PyTorch NestedTensors、FlashAttention2和XFormers的memory_efficient_attention。这些技术通过减少冗余计算、优化内存管理和改进计算模式,显著提升了模型的性能。实验结果显示,使用FlashAttention2和无填充策略的组合可以将步骤时间减少至323毫秒,相比未优化版本提升了约2.5倍。
33 3
Transformer模型变长序列优化:解析PyTorch上的FlashAttention2与xFormers
|
12天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
15天前
|
SQL 安全 算法
网络安全之盾:漏洞防御与加密技术解析
在数字时代的浪潮中,网络安全和信息安全成为维护个人隐私和企业资产的重要防线。本文将深入探讨网络安全的薄弱环节—漏洞,并分析如何通过加密技术来加固这道防线。文章还将分享提升安全意识的重要性,以预防潜在的网络威胁,确保数据的安全与隐私。
31 2
|
16天前
|
安全 算法 网络安全
网络安全的盾牌与剑:漏洞防御与加密技术深度解析
在数字信息的海洋中,网络安全是航行者不可或缺的指南针。本文将深入探讨网络安全的两大支柱——漏洞防御和加密技术,揭示它们如何共同构筑起信息时代的安全屏障。从最新的网络攻击手段到防御策略,再到加密技术的奥秘,我们将一起揭开网络安全的神秘面纱,理解其背后的科学原理,并掌握保护个人和企业数据的关键技能。
25 3
|
19天前
|
网络协议
网络通信的基石:TCP/IP协议栈的层次结构解析
在现代网络通信中,TCP/IP协议栈是构建互联网的基础。它定义了数据如何在网络中传输,以及如何确保数据的完整性和可靠性。本文将深入探讨TCP/IP协议栈的层次结构,揭示每一层的功能和重要性。
51 5
|
21天前
|
网络协议 安全 文件存储
动态DNS(DDNS)技术在当前网络环境中日益重要,它允许使用动态IP地址的设备通过固定域名访问
动态DNS(DDNS)技术在当前网络环境中日益重要,它允许使用动态IP地址的设备通过固定域名访问,即使IP地址变化,也能通过DDNS服务保持连接。适用于家庭网络远程访问设备及企业临时或移动设备管理,提供便捷性和灵活性。示例代码展示了如何使用Python实现基本的DDNS更新。尽管存在服务可靠性和安全性挑战,DDNS仍极大提升了网络资源的利用效率。
38 6
|
19天前
|
监控 网络协议 网络性能优化
网络通信的核心选择:TCP与UDP协议深度解析
在网络通信领域,TCP(传输控制协议)和UDP(用户数据报协议)是两种基础且截然不同的传输层协议。它们各自的特点和适用场景对于网络工程师和开发者来说至关重要。本文将深入探讨TCP和UDP的核心区别,并分析它们在实际应用中的选择依据。
42 3
|
28天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
65 2
|
2月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
73 0