mindspore(二)-yolov5的训练、改进及MindConverter的使用

mindspore-yolov5的训练、改进及MindConverter的使用

  • 目标检测
  • 训练环境
  • 准备
  • 开始训练
  • mindspore-yolov5的小改动
  • MindConverter
  • 总结

YOLO系列的目标检测算法发展迅速,yolov5在v4的基础上增加了一些训练的小tricks使得精度进一步提升,此次实验训练mindspore框架下的yolov5并进行简单的改进

目标检测

目标检测主要解决两个问题:
1.判定图像上有哪些目标物体,解决目标物体存在性的问题;
2.判定图像中目标物体的具体位置,解决目标物体在哪里的问题。
mindspore(二)-yolov5的训练、改进及MindConverter的使用_第1张图片


训练环境

mindspore-gpu=1.5.0
liunx操作系统

准备

获取官方的yolov5代码 链接: https://gitee.com/mindspore/models/tree/master/official/cv/yolov5
各个领域经典算法官方都给出了复现的代码,直接通过华为modelzoo获取
数据集准备 ,数据集的格式如下:

mindspore(二)-yolov5的训练、改进及MindConverter的使用_第2张图片
包含:训练图像数据,验证图像,以及两个json文件,至于如何制作这样的数据集,网上教程及代码很多可以参考

开始训练

在制作好数据集后,需要在default_config .yaml文件中修改数据集路径,预训练模型,yolov5的模式,类别数
修改好配置文件后执行下面命令

#run training example(1p) by python command
python train.py \
    --data_dir=xxx/dataset \
    --yolov5_version='yolov5s' \
    --is_distributed=0 \
    --lr=0.01 \
    --T_max=320
    --max_epoch=320 \
    --warmup_epochs=4 \
    --per_batch_size=32 \
    --lr_scheduler=cosine_annealing > log.txt 2>&1 &

然后就成功训练起来了
在这里插入图片描述

mindspore-yolov5的小改动

看了几篇中文核心,大抵上都是加了注意力模块,修改了损失函数等(甚至有几篇加的注意力和修改的损失都一样,离谱),那就仿照着做吧
做了以下优化:
1.yolov5的主干网络加入了SE注意力(只是用来测试,所以选择了最简单的注意力,已发表的核心主要加的是CA,ECA注意力等)
2.将giou损失修改为GIOU损失,提高边界框定位精度

SEnet的torch代码实现如下:

import torch
import torch.nn as nn
import math
class se_block(nn.Module):
    def __init__(self, channel, ratio=16):
        super(se_block, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
                nn.Linear(channel, channel // ratio, bias=False),
                nn.ReLU(inplace=True),
                nn.Linear(channel // ratio, channel, bias=False),
                nn.Sigmoid()
        )
    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y

现在需要做的就是将torch的算子用mindspore的算子去替换
SE的代码片段短,可以挨个将算子替换
但我一开始想加入ECA注意力,算子需要修改的比较多,并且由于对ms算子不太熟悉,总是报出一些错误,如数据类型等,比如对于一个算子,我到底是用ms.Tensor里面的还是ops里面的,得查阅API
于是,我发现了一个好东西第三方框架脚本转换! MindConverter

MindConverter

ms支持第三方框架如pytorch、tensflow的模型脚本转换
通过MindConverter我就不用在挨个研究算子的区别了
使用:
mindconverter --in_file src/CAattention.py --output convert --report convert/report
三个参数分别为:要转换的脚本,输出路径,生成的日志路径
通过以上的命令,就将torch的SE转为了ms的SE,但是MindConverter并不能将代码全部转换,需要在根据report文件的提示来手动微调,并且有时候转换的也不太对,亲测
生成的report文件:
mindspore(二)-yolov5的训练、改进及MindConverter的使用_第3张图片转换后的代码:

import mindspore.nn as nn
import mindspore.ops.operations as P
import mindspore.ops as ops
class eca_block(nn.Cell):
    def __init__(self, channel, ratio=16):
        super(eca_block, self).__init__()
        self.avg_pool = ops.AdaptiveAvgPool2D(1)
        self.fc = nn.SequentialCell([
                nn.Dense(in_channels=channel, out_channels=channel // ratio, has_bias=False),
                nn.ReLU(),
                nn.Dense(in_channels=channel // ratio, out_channels=channel, has_bias=False),
                nn.Sigmoid()
        ])
    def construct(self, x):
        b, c, _, _ = P.Shape()(x)
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y

然后将边界框损失修改为CIOU loss

def ciou(boxes1,boxes2):
    '''
    cal CIOU of two boxes or batch boxes
    :param boxes1:[xmin,ymin,xmax,ymax] or
                [[xmin,ymin,xmax,ymax],[xmin,ymin,xmax,ymax],...]
    :param boxes2:[xmin,ymin,xmax,ymax]
    :return:
    '''

    #cal the box's area of boxes1 and boxess
    boxes1Area = (boxes1[...,2]-boxes1[...,0])*(boxes1[...,3]-boxes1[...,1])
    boxes2Area = (boxes2[..., 2] - boxes2[..., 0]) * (boxes2[..., 3] - boxes2[..., 1])

    # cal Intersection
    left_up = np.maximum(boxes1[...,:2],boxes2[...,:2])
    right_down = np.minimum(boxes1[...,2:],boxes2[...,2:])

    inter_section = np.maximum(right_down-left_up,0.0)
    inter_area = inter_section[...,0] * inter_section[...,1]
    union_area = boxes1Area+boxes2Area-inter_area
    ious = np.maximum(1.0*inter_area/union_area,np.finfo(np.float32).eps)

    # cal outer boxes
    outer_left_up = np.minimum(boxes1[..., :2], boxes2[..., :2])
    outer_right_down = np.maximum(boxes1[..., 2:], boxes2[..., 2:])
    outer = np.maximum(outer_right_down - outer_left_up, 0.0)
    outer_diagonal_line = np.square(outer[...,0]) + np.square(outer[...,1])

    # cal center distance
    boxes1_center = (boxes1[..., :2] +  boxes1[...,2:]) * 0.5
    boxes2_center = (boxes2[..., :2] +  boxes2[...,2:]) * 0.5
    center_dis = np.square(boxes1_center[...,0]-boxes2_center[...,0]) +\
                 np.square(boxes1_center[...,1]-boxes2_center[...,1])

    # cal penalty term
    # cal width,height
    boxes1_size = np.maximum(boxes1[...,2:]-boxes1[...,:2],0.0)
    boxes2_size = np.maximum(boxes2[..., 2:] - boxes2[..., :2], 0.0)
    v = (4.0/np.square(np.pi)) * np.square((
            np.arctan((boxes1_size[...,0]/boxes1_size[...,1])) -
            np.arctan((boxes2_size[..., 0] / boxes2_size[..., 1])) ))
    alpha = v / (1-ious+v)
    #cal ciou
    cious = ious - (center_dis / outer_diagonal_line + alpha*v)

    return cious

运行train.py,成功训练
mindspore(二)-yolov5的训练、改进及MindConverter的使用_第4张图片

总结

1.yolov5的主干网络加入了SE注意力(只是用来测试,所以选择了最简单的注意力,已发表的核心主要加的是CA,ECA注意力等)
2.将giou损失修改为GIOU损失,提高边界框定位精度
3.MindConverter的使用

你可能感兴趣的:(计算机视觉,深度学习,人工智能)