8.Mobilenetv2网络代码实现
代码如下:
import math
import os
import numpy as npimport torch
import torch.nn as nn
import torch.utils.model_zoo as model_zoo#1.建立带有bn的卷积网络
def conv_bn(inp, oup, stride):return nn.Sequential(nn.Conv2d(inp,oup,3,stride,bias=False),nn.BatchNorm2d(oup),nn.ReLU6(inplace=True))#2.建立卷积核是1x1的卷积网络
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]hidden_dim=round(inp*expand_ratio)self.use_res_connect=self.stride==1 and inp==oupif expand_ratio == 1:self.conv=nn.Sequential(# --------------------------------------------## 进行3x3的逐层卷积,进行跨特征点的特征提取# --------------------------------------------#nn.Conv2d(hidden_dim,hidden_dim,3,stride, 1, groups=hidden_dim, bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# -----------------------------------## 利用1x1卷积进行通道数的调整# -----------------------------------#nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),nn.BatchNorm2d(oup),)else:self.conv=nn.Sequential(# -----------------------------------## 利用1x1卷积进行通道数的上升# -----------------------------------#nn.Conv2d(inp,hidden_dim,1,1,0,bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# --------------------------------------------## 进行3x3的逐层卷积,进行跨特征点的特征提取# --------------------------------------------#nn.Conv2d(hidden_dim,hidden_dim,3,stride, 1, groups=hidden_dim, bias=False),nn.BatchNorm2d(hidden_dim),nn.ReLU6(inplace=True),# -----------------------------------## 利用1x1卷积进行通道数的下降# -----------------------------------#nn.Conv2d(hidden_dim, 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)#搭建MobileNetV2网络
class MobileNetV2(nn.Module):def __init__(self, n_class=1000, input_size=224, width_mult=1.):super(MobileNetV2, self).__init__()block=InvertedResidualinput_channel=32last_channel=1280interverted_residual_setting = [# t, c, n, s[1, 16, 1, 1], # 256, 256, 32 -> 256, 256, 16[6, 24, 2, 2], # 256, 256, 16 -> 128, 128, 24 2[6, 32, 3, 2], # 128, 128, 24 -> 64, 64, 32 4[6, 64, 4, 2], # 64, 64, 32 -> 32, 32, 64 7[6, 96, 3, 1], # 32, 32, 64 -> 32, 32, 96[6, 160, 3, 2], # 32, 32, 96 -> 16, 16, 160 14[6, 320, 1, 1], # 16, 16, 160 -> 16, 16, 320]assert input_size % 32 == 0input_channel = int(input_channel * width_mult)self.last_channel = int(last_channel * width_mult) if width_mult > 1.0 else last_channel# 512, 512, 3 -> 256, 256, 32self.features=[conv_bn(3,input_channel,2)]for t,c,n,s in interverted_residual_setting:output_channel=int(c*width_mult)for i in range(n):if i==0:self.features.append(block(input_channel,output_channel,s, expand_ratio=t))else:self.features.append(block(input_channel,output_channel,1, expand_ratio=t))# input_channel修改为该轮的输出层数input_channel = output_channelself.features.append(conv_1x1_bn(input_channel, self.last_channel))self.features=nn.Sequential(*self.features)self.classifier=nn.Sequential(nn.Dropout(0.2),nn.Linear(self.last_channel,n_class))self._initialize_weights()def forward(self,x):x=self.features(x)x=x.mean(3).mean(2)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_()if __name__ == '__main__':print("........................................")#数据集生成input=torch.randn(1,3,224,224)print(input.shape)#MobileNetV2的输出ss=MobileNetV2()# print(ss)output=ss(input)print(output.shape)