MobileNet
传统卷积神经网络,内存需求大、运算量大导致无法在移动设备以及嵌入式设备上运行。
MobileNet网络是由google团队在2017年提出的,专注于移动端或者嵌入式设备中的轻量级CNN网络。相比传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量。(相比VGG16准确率减少了0.9%,但模型参数只有VGG的1/32)
以下是传统卷积和Depthwise Convolution的比较:
pw卷积(就是1*1卷积,用于调整深度):
计算量大大降低:
MobileNet V1
网络中的亮点:
Depthwise Convolution(大大减少运算量和参数数量)
增加超参数α、β
其中α为卷积核的个数,β为输入图像的分辨率。
MobileNet V2
MobileNet v2网络是由google团队在2018年提出的,相比MobileNet V1网.
络,准确率更高,模型更小。
网络中的亮点:
Inverted Residuals (倒残差结构)
Linear Bottlenecks
与ResNet中形成的两头大 中间小的bottleneck结构相反,是一种倒残差结构。
采用了ReLU6函数,
在倒残差结构的最后一个1*1卷积层中,使用了线性的激活函数,而不是ReLU激活函数。
并不是所有的block中都有shortcut捷径分支,当sride=1并且输入特征矩阵与输出特征矩阵shape相同时才有shortcut连接。
网络结构:
此网络中描述的bottleneck是倒残差结构。
以下是MobileNet V2在分类和目标检测任务下与MobileNet V1的效率对比,可以看到在CPU下有比较明显的效率提升,基本实现了在移动端能实时完成任务的功能。
MobileNet V3
MoblieNet V3主要更新了:
更新Block(bneck)
使用NAS(Neural Architecture Search)搜索参数
重新设计耗时层结构
更新Block
重新设计耗时层结构
重新设计激活函数
SENet
国内自动驾驶创业公司 Momenta 在 ImageNet 2017 挑战赛中夺冠,网络架构为 SENet,Squeeze-and-Excitation Networks,论文作者为 Momenta 高级研发工程师胡杰。
网络是否可以从其他层面来考虑去提升性能,比如考虑特征通道之间的关系?SENet就是考虑了通道层面的关系。具体来说,就是通过学习的方式来获取每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征。
SE模块如下图所示:
首先是 Squeeze 操作,顺着空间维度来进行特征压缩,将每个二维的特征通道变成一个实数,这个实数某种程度上具有全局的感受野,表征着在特征通道上响应的全局分布
然后是 Excitation 操作,类似于循环神经网络门的机制。通过参数 w 来为每个特征通道生成权重,其中参数 w 被学习用来显式地建模特征通道间的相关性。(这里是两个全连接层)
最后是 Reweight 的操作,将 Excitation 的输出的权重看做是进过特征选择后的每个特征通道的重要性,然后通过乘法逐通道加权到先前的特征上,完成在通道上对原始特征的重标定。
下面是 BasicBlock 的代码:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.optim as optim
class BasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
# shortcut的输出维度和输出不一致时,用1*1的卷积来匹配维度
self.shortcut = nn.Sequential()
if stride != 1 or in_cha