当前位置:   article > 正文

MobileNetV2详细原理(含torch源码)_mobilenetv2模型

mobilenetv2模型

 

目录

MobilneNetV2原理

MobileNetV2的创新点:

MobileNetV2对比MobileNetV1

MobilneNetV2源码(torch版)

训练10个epoch的效果


MobilneNetV2原理

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

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

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

线性瓶颈结构:

MobileNetV2两种残差块:

        它还采用了轻量级的特征网络Design Spaces提升性能的策略,优化卷积核大小和数量,调整网络宽度和深度,最终得到一个更加高效的网络。网络结构图如下:

 

MobileNetV2的创新点:

        MobileNetV2相较于MobileNetV1在以下方面进行了创新:

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

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

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

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

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

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

MobileNetV2对比MobileNetV1

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

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

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

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

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

MobilneNetV2源码(torch版)

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

链接:百度网盘
提取码:kd9a 

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

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

  1. from torch.utils.data import DataLoader
  2. from torchvision.datasets import CIFAR10
  3. from torchvision.transforms import transforms
  4. from torch.autograd import Variable
  5. import torch.nn as nn
  6. import torch.nn.functional as F
  7. import torch
  8. class Block(nn.Module):
  9. def __init__(self, in_planes, out_planes, expansion, stride):
  10. super(Block, self).__init__()
  11. self.stride = stride
  12. planes = expansion * in_planes
  13. self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
  14. self.bn1 = nn.BatchNorm2d(planes)
  15. self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, groups=planes, bias=False)
  16. self.bn2 = nn.BatchNorm2d(planes)
  17. self.conv3 = nn.Conv2d(planes, out_planes, kernel_size=1, bias=False)
  18. self.bn3 = nn.BatchNorm2d(out_planes)
  19. self.shortcut = nn.Sequential()
  20. if stride == 1 and in_planes != out_planes:
  21. self.shortcut = nn.Sequential(
  22. nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False),
  23. nn.BatchNorm2d(out_planes)
  24. )
  25. def forward(self, x):
  26. out = F.relu(self.bn1(self.conv1(x)))
  27. out = F.relu(self.bn2(self.conv2(out)))
  28. out = self.bn3(self.conv3(out))
  29. out += self.shortcut(x) if self.stride == 1 else out
  30. return out
  31. class MobileNetV2(nn.Module):
  32. def __init__(self, num_classes=10):
  33. super(MobileNetV2, self).__init__()
  34. self.cfgs = [
  35. # t, c, n, s
  36. [1, 16, 1, 1],
  37. [6, 24, 2, 1],
  38. [6, 32, 3, 2],
  39. [6, 64, 4, 2],
  40. [6, 96, 3, 1],
  41. [6, 160, 3, 2],
  42. [6, 320, 1, 1],
  43. ]
  44. self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)
  45. self.bn1 = nn.BatchNorm2d(32)
  46. self.layers = self._make_layers(in_planes=32)
  47. self.conv2 = nn.Conv2d(320, 1280, kernel_size=1, bias=False)
  48. self.bn2 = nn.BatchNorm2d(1280)
  49. self.linear = nn.Linear(1280, num_classes)
  50. def _make_layers(self, in_planes):
  51. layers = []
  52. for t, c, n, s in self.cfgs:
  53. for i in range(n):
  54. stride = s if i == 0 else 1
  55. layers.append(Block(in_planes, c, t, stride))
  56. in_planes = c
  57. return nn.Sequential(*layers)
  58. def forward(self, x):
  59. out = F.relu(self.bn1(self.conv1(x)))
  60. out = self.layers(out)
  61. out = F.relu(self.bn2(self.conv2(out)))
  62. out = F.avg_pool2d(out, 4)
  63. out = out.view(out.size(0), -1)
  64. out = self.linear(out)
  65. return out
  66. if __name__ == '__main__':
  67. train_data = CIFAR10('cifar', train=True, transform=transforms.ToTensor())
  68. data = DataLoader(train_data, batch_size=148, shuffle=True)
  69. device = torch.device("cuda")
  70. net = MobileNetV2().to(device)
  71. print(net)
  72. cross = nn.CrossEntropyLoss().to(device)
  73. optimizer = torch.optim.Adam(net.parameters(), 0.0001)
  74. for epoch in range(10):
  75. for img, label in data:
  76. img = Variable(img).to(device)
  77. label = Variable(label).to(device)
  78. output = net.forward(img)
  79. loss = cross(output, label)
  80. loss.backward()
  81. optimizer.zero_grad()
  82. optimizer.step()
  83. pre = torch.argmax(output, 1)
  84. num = (pre == label).sum().item()
  85. acc = num / img.shape[0]
  86. print("epoch:", epoch + 1)
  87. print("loss:", loss.item())
  88. print("Accuracy:", acc)

        以上代码采用的是跟PyTorch官方模型一样的模型结构,在_make_layers函数中构建了7个Block块,每个Block块都是跟MobileNetV2一样的结构,通过自定义一个Block类来实现。在forward函数中,通过调用这7个Block块的方式构建整个网络的结构。在最后的分类层中,采用了一个线性层。 

        使用cifar10训练做测试。

训练10个epoch的效果

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/238601
推荐阅读
  

闽ICP备14008679号