Tensorflow Lite模型部署实战教程--yolov5替换backbone为MobileNet-V2_人工智能

目录

1.MobileNetv2的 bottleneck 和 Pwconv实现

1.1 Mobilenetv2的bottleneck: InvertedResidual

1.2Pointwise Convolution实现 

2.搭建模型配置文件


 Tensorflow Lite模型部署实战教程是一系列嵌入式Linux平台上的模型部署教程。

????基于的硬件平台:i.MX8MPlus EVK

????BSP版本:L5.10.52_2.1.0

????Tensorflow Lite版本:2.5.0

这一节我们将替换yolov5 的backbone为MobileNet-V2网络结构,并进行模型训练。

1.MobileNetv2的 bottleneck 和 Pwconv实现

首先,需要在models/common.py里,实现MobileNetv2的 bottleneck 和 Pwconv。

1.1 Mobilenetv2的bottleneck: InvertedResidual

在models/common.py里,实现MobileNetv2的 bottleneck 。网络结构就不在赘述了,论文里都有。

#mobilenet  Bottleneck  InvertedResidual  
class BottleneckMOB(nn.Module):  
    #c1:inp  c2:oup s:stride  expand_ratio:t  
    def __init__(self, c1, c2, s, expand_ratio):  
        super(BottleneckMOB, self).__init__()  
        self.s = s  
        hidden_dim = round(c1 * expand_ratio)  
        self.use_res_connect = self.s == 1 and c1 == c2  
        if expand_ratio == 1:  
            self.conv = nn.Sequential(  
                # dw  
                nn.Conv2d(hidden_dim, hidden_dim, 3, s, 1, groups=hidden_dim, bias=False),  
                nn.BatchNorm2d(hidden_dim),  
                nn.ReLU6(inplace=True),  
                # pw-linear  
                nn.Conv2d(hidden_dim, c2, 1, 1, 0, bias=False),  
                nn.BatchNorm2d(c2),  
            )  
        else:  
            self.conv = nn.Sequential(  
                # pw  
                nn.Conv2d(c1, hidden_dim, 1, 1, 0, bias=False),  
                nn.BatchNorm2d(hidden_dim),  
                nn.ReLU6(inplace=True),  
                # dw  
                nn.Conv2d(hidden_dim, hidden_dim, 3, s, 1, groups=hidden_dim, bias=False),  
                nn.BatchNorm2d(hidden_dim),  
                nn.ReLU6(inplace=True),  
                # pw-linear  
                nn.Conv2d(hidden_dim, c2, 1, 1, 0, bias=False),  
                nn.BatchNorm2d(c2),  
            )  
​
    def forward(self, x):  
        if self.use_res_connect:  
            return x + self.conv(x)  
        else:  
            return self.conv(x)  

1.2Pointwise Convolution实现 

实现点云卷积:

class PW_Conv(nn.Module):  
    def __init__(self, c1, c2):  # ch_in, ch_out  
        super(PW_Conv, self).__init__()  
        self.conv = nn.Conv2d(c1, c2, 1, 1, 0, bias=False)  
        self.bn = nn.BatchNorm2d(c2)  
        self.act = nn.ReLU6(inplace=True)  
​
    def forward(self, x):  
        return self.act(self.bn(self.conv(x))) 

接着需要在yolov5的读取模型配置文件的代码(models/yolo.py的parse_model函数)进行修改,使得能够调用到上面的模块,只需修改下面这部分代码。

n = max(round(n * gd), 1) if n > 1 else n  # depth gain  
if m in [nn.Conv2d, Conv, Bottleneck, SPP, DWConv, MixConv2d, Focus, CrossConv, BottleneckCSP, C3, PW_Conv, BottleneckMOB]:  
    c1, c2 = ch[f], args[0] 

并且需要在import引用处加入PW_Conv,BottleneckMOB这两个模块。

from models.common import Conv, Bottleneck,SPP, DWConv, Focus, BottleneckCSP, Concat, NMS, autoShape, PW_Conv,BottleneckMOB
2.搭建模型配置文件

然后就是搭建我们的模型配置文件,我在yolov5s.yaml的基础上进行修改,将yolov5s的backbone替换成mobilenetv2,重新建立了一个模型配置文件yolov5-mobilenetv2.yaml。

# parameters  
nc: 1  # number of classes  
depth_multiple: 0.33  # model depth multiple  
width_multiple: 0.50  # layer channel multiple  
​
# anchors  
anchors:  
  - [116,90, 156,198, 373,326]  # P5/32  
  - [30,61, 62,45, 59,119]  # P4/16  
  - [10,13, 16,30, 33,23]  # P3/8  
​
# YOLOv5 backbone: mobilenet v2  
backbone:  
  # [from, number, module, args]  
  [[-1, 1, nn.Conv2d, [32, 3, 2]],  # 0-P1/2   oup, k, s     640  
   [-1, 1, BottleneckMOB, [16, 1, 1]],  # 1-P2/4   oup, s, t 320  
   [-1, 2, BottleneckMOB, [24, 2, 6]],  #                    320  
   [-1, 1, PW_Conv, [256]],  #4  output p3                   160  
   [-1, 3, BottleneckMOB, [32, 2, 6]],  # 3-P3/8             160  
   [-1, 4, BottleneckMOB, [64, 1, 6]],  # 5                  80  
   [-1, 1, PW_Conv, [512]],  #7 output p4  6                 40  
   [-1, 3, BottleneckMOB, [96, 2, 6]],  # 7                  80  
   [-1, 3, BottleneckMOB, [160, 1, 6,]], #                   40  
   [-1, 1, BottleneckMOB, [320, 1, 6,]], #                   40  
   [-1, 1, nn.Conv2d, [1280, 1, 1]],     #                   40  
   [-1, 1, SPP, [1024, [5, 9, 13]]],  #11     #              40  
  ]  
​
# YOLOv5 head  
head:  
  [[-1, 3, BottleneckCSP, [1024, False]],  # 12             40  
​
   [-1, 1, Conv, [512, 1, 1]],                      #       40  
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],      #       40  
   [[-1, 6], 1, Concat, [1]],  # cat backbone P4-7  #       80  
   [-1, 3, BottleneckCSP, [512, False]],  # 16      #       80  
​
   [-1, 1, Conv, [256, 1, 1]],                      #       80  
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],      #       160  
   [[-1, 3], 1, Concat, [1]],  # cat backbone P3-4          160  
   [-1, 3, BottleneckCSP, [256, False]],            #       160  
   [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 21 (P3/8-small)   #        160  
​
   [-2, 1, Conv, [256, 3, 2]],                     #       160  
   [[-1, 17], 1, Concat, [1]],  # cat head P4      #       160  
   [-1, 3, BottleneckCSP, [512, False]],           #       160  
   [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 25 (P4/16-medium)  #       160  
​
   [-2, 1, Conv, [512, 3, 2]],                     #       160  
   [[-1, 13], 1, Concat, [1]],  # cat head P5-13   #      160  
   [-1, 3, BottleneckCSP, [1024, False]],          #      160  
   [-1, 1, nn.Conv2d, [na * (nc + 5), 1, 1]],  # 29 (P5/32-large)           160  
​
   [[21, 25, 29], 1, Detect, [nc, anchors]],  # Detect(P5, P4, P3)     nc:number class, na:number of anchors  
  ]  

到这我们就实现了将yolov5的backbone替换成了mobilenetv2。在使用时只需要将网络结构配置参数—cfg修改成 –cfg yolov5-mobilenet.yaml。

训练指令:

python train.py --data coco.yaml --cfg yolov5-mobilenet.yaml--weights '' --batch-size 64

到这里,yolov5就会使用MobileNet-V2网络结构进行训练啦~~????????