MobileNet-v2网络框架

2024-03-31 22:58
文章标签 框架 网络 v2 mobilenet

本文主要是介绍MobileNet-v2网络框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、MobileNet-v2

MobileNetV2: Inverted Residuals and Linear Bottlenecks

  • 论文链接:https://arxiv.org/abs/1801.04381
  • 论文翻译:https://www.e-learn.cn/content/qita/675949
  • 论文详解:https://www.cnblogs.com/darkknightzh/p/9410574.html
  • 论文代码:https://github.com/tensorflow/models/tree/master/research/slim/nets/mobilenet

二、MobileNet算法

1、线性瓶颈层(linear bottlenecks)

MobileNet-v2使用了线性瓶颈层。因为当使用ReLU等激活函数时,会导致信息丢失。如下图所示,低维(2维)的信息嵌入到n维的空间中,并通过随机矩阵T对特征进行变换,之后再加上ReLU激活函数,之后在通过T-1进行反变换。当n=2,3时,会导致比较严重的信息丢失,部分特征重叠到一起了;当n=15到30时,信息丢失程度降低,但是变换矩阵已经是高度非凸的了。
在这里插入图片描述
由于非线性层会毁掉一部分信息,因而非常有必要使用线性瓶颈层。且线性瓶颈层包含所有的必要信息,扩张层则是供非线性层丰富信息使用。

在这里插入图片描述
上图对比了不同的卷积方式:

  • (a),传统卷积方式,输入和输出维度不一样,且卷积核直接对输入的红色立方体进行滤波;
  • (b)为可分离卷积,左侧3×3卷积的每个卷积核只对输入的对应层进行滤波,此时特征维度不变;右边的1*1的卷积对特征进行升维或者降维(图中为升维)。
  • (c)图中为带线性瓶颈层的可分离卷积,输入通过3×3 depthwise卷积+ReLU6,得到中间相同维度的特征。之后在通过1×1conv+ReLU6,得到降维后的特征(带斜线立方体)。之后在通过1×1卷积(无ReLU)进行升维。
  • (d)图中则是维度比较低的特征,先通过1×1conv(无ReLU)升维,而后通过3×3 depthwise卷积+ReLU6保持特征数量不变,再通过1×1conv+ReLU6得到降维后的下一层特征;

2、Inverted residual block
在这里插入图片描述
上图为反转残差块(inverted residual block)。显示了传统的残差块和反转残差块的区别:

  • 传统的残差块如(a)将高维特征先使用1×1conv降维,然后在使用3×3conv进行滤波,并使用1×1conv进行升维(这些卷积中均包含ReLU),得到输出特征(下一层的输入),并进行element wise的相加。
  • 反转残差块则是将低维特征使用1×1conv升维(不含ReLU),而后使用3×3conv+ReLU对特征进行滤波,并使用1×1conv+ReLU对特征再降维,得到本层特征的输出,并进行element wise的相加。

反转的原因:瓶颈层的输入包含了所有的必要信息,因而右侧最左边的层后面不加ReLU,防止信息丢失。升维后,信息更加丰富,此时加上ReLU,之后在降维,理论上可以保持所有的必要信息不丢失。

为何使用ReLU? 使用ReLU可以增加模型的稀疏性。过于稀疏了,信息就丢失了。。。

那瓶颈层内部为何需要升维呢? 原因是为了增加模型的表达能力:当使用ReLU对某通道的信息进行处理后,该通道会不可避免的丢失信息;然而如果有足够多的通道的话,某通道丢失的信息,可能仍旧保留在其他通道中,因而才会在瓶颈层内部对特征进行升维。文中附录证明了,瓶颈层内部升维足够大时,能够抵消ReLU造成的信息丢失(如文中将特征维度扩大了6倍)。

在这里插入图片描述
瓶颈层的具体结构如上表所示。输入通过1×1的conv+ReLU层将维度从k维增加到tk维,之后通过3×3conv+ReLU可分离卷积对图像进行降采样(stride>1时),此时特征维度已经为tk维度,最后通过1×1conv(无ReLU)进行降维,维度从tk降低到k’维。

需要注意的是,除了整个模型中的第一个瓶颈层的t=1之外,其他瓶颈层t=6(论文中Table 2),即第一个瓶颈层内部并不对特征进行升维。

在这里插入图片描述
另外,对于瓶颈层,当stride=1时,才会使用elementwise 的sum将输入和输出特征连接(如上图左侧);stride=2时,无short cut连接输入和输出特征(上图右侧)。

3、网络模型

MobileNetV2的模型如下图所示,其中t为瓶颈层内部升维的倍数,c为特征的维数,n为该瓶颈层重复的次数,s为瓶颈层第一个conv的步幅。

需要注意的是:

  • 当n>1时(即该瓶颈层重复的次数>1),只在第一个瓶颈层stride为对应的s,其他重复的瓶颈层stride均为1
  • 只在stride=1时,输出特征尺寸和输入特征尺寸一致,才会使用elementwise sum将输出与输入相加
  • 当n>1时,只在第一个瓶颈层特征维度为c,其他时候channel不变。

例如,对于该图中56²×24的那层,共有3个该瓶颈层,只在第一个瓶颈层使用stride=2,后两个瓶颈层stride=1;第一个瓶颈层由于输入和输出尺寸不一致,因而无short cut连接,后两个由于stride=1,输入输出特征尺寸一致,会使用short cut将输入和输出特征进行elementwise的sum;只在第一个瓶颈层最后的1×1conv对特征进行升维,后两个瓶颈层输出维度不变(不要和瓶颈层内部的升维弄混了)。

该层输入特征为56×56×24,第一个瓶颈层输出为28×28×32(特征尺寸降低,特征维度增加,无short cut),第二个、第三个瓶颈层输入和输出均为28×28×32(此时c=32,s=1,有short cut)。

另外,下表中还有一个k。MobileNetV1中提出了宽度缩放因子,其作用是在整体上对网络的每一层维度(特征数量)进行瘦身。MobileNetV2中,当该因子<1时,最后的那个1×1conv不进行宽度缩放;否则进行宽度缩放。

在这里插入图片描述

4、pytorch代码

import torch.nn as nn
import mathdef conv_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp, oup, 3, stride, 1, bias=False),nn.BatchNorm2d(oup),nn.ReLU6(inplace=True))def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),nn.ReLU6(inplace=True))class InvertedResidual(nn.Module):def __init__(self, inp, oup, stride, expand_ratio):super(InvertedResidual, self).__init__()self.stride = strideassert stride in [1, 2]self.use_res_connect = self.stride == 1 and inp == oupself.conv = nn.Sequential(# pwnn.Conv2d(inp, inp * expand_ratio, 1, 1, 0, bias=False),nn.BatchNorm2d(inp * expand_ratio),nn.ReLU6(inplace=True),# dwnn.Conv2d(inp * expand_ratio, inp * expand_ratio, 3, stride, 1, groups=inp * expand_ratio, bias=False),nn.BatchNorm2d(inp * expand_ratio),nn.ReLU6(inplace=True),# pw-linearnn.Conv2d(inp * expand_ratio, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)def forward(self, x):if self.use_res_connect:return x + self.conv(x)else:return self.conv(x)class MobileNetV2(nn.Module):def __init__(self, n_class=1000, input_size=224, width_mult=1.):super(MobileNetV2, self).__init__()# setting of inverted residual blocksself.interverted_residual_setting = [# t, c, n, s[1, 16, 1, 1],[6, 24, 2, 2],[6, 32, 3, 2],[6, 64, 4, 2],[6, 96, 3, 1],[6, 160, 3, 2],[6, 320, 1, 1],]# building first layerassert input_size % 32 == 0input_channel = int(32 * width_mult)self.last_channel = int(1280 * width_mult) if width_mult > 1.0 else 1280self.features = [conv_bn(3, input_channel, 2)]# building inverted residual blocksfor t, c, n, s in self.interverted_residual_setting:output_channel = int(c * width_mult)for i in range(n):if i == 0:self.features.append(InvertedResidual(input_channel, output_channel, s, t))else:self.features.append(InvertedResidual(input_channel, output_channel, 1, t))input_channel = output_channel# building last several layersself.features.append(conv_1x1_bn(input_channel, self.last_channel))self.features.append(nn.AvgPool2d(input_size/32))# make it nn.Sequentialself.features = nn.Sequential(*self.features)# building classifierself.classifier = nn.Sequential(nn.Dropout(),nn.Linear(self.last_channel, n_class),)self._initialize_weights()def forward(self, x):x = self.features(x)x = x.view(-1, self.last_channel)x = self.classifier(x)return xdef _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))if m.bias is not None:m.bias.data.zero_()elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()elif isinstance(m, nn.Linear):n = m.weight.size(1)m.weight.data.normal_(0, 0.01)m.bias.data.zero_()

这篇关于MobileNet-v2网络框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/865581

相关文章

MyBatis框架实现一个简单的数据查询操作

《MyBatis框架实现一个简单的数据查询操作》本文介绍了MyBatis框架下进行数据查询操作的详细步骤,括创建实体类、编写SQL标签、配置Mapper、开启驼峰命名映射以及执行SQL语句等,感兴趣的... 基于在前面几章我们已经学习了对MyBATis进行环境配置,并利用SqlSessionFactory核

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

poj 3181 网络流,建图。

题意: 农夫约翰为他的牛准备了F种食物和D种饮料。 每头牛都有各自喜欢的食物和饮料,而每种食物和饮料都只能分配给一头牛。 问最多能有多少头牛可以同时得到喜欢的食物和饮料。 解析: 由于要同时得到喜欢的食物和饮料,所以网络流建图的时候要把牛拆点了。 如下建图: s -> 食物 -> 牛1 -> 牛2 -> 饮料 -> t 所以分配一下点: s  =  0, 牛1= 1~

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

poj 3068 有流量限制的最小费用网络流

题意: m条有向边连接了n个仓库,每条边都有一定费用。 将两种危险品从0运到n-1,除了起点和终点外,危险品不能放在一起,也不能走相同的路径。 求最小的费用是多少。 解析: 抽象出一个源点s一个汇点t,源点与0相连,费用为0,容量为2。 汇点与n - 1相连,费用为0,容量为2。 每条边之间也相连,费用为每条边的费用,容量为1。 建图完毕之后,求一条流量为2的最小费用流就行了

poj 2112 网络流+二分

题意: k台挤奶机,c头牛,每台挤奶机可以挤m头牛。 现在给出每只牛到挤奶机的距离矩阵,求最小化牛的最大路程。 解析: 最大值最小化,最小值最大化,用二分来做。 先求出两点之间的最短距离。 然后二分匹配牛到挤奶机的最大路程,匹配中的判断是在这个最大路程下,是否牛的数量达到c只。 如何求牛的数量呢,用网络流来做。 从源点到牛引一条容量为1的边,然后挤奶机到汇点引一条容量为m的边

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1