当前位置: 首页 > 工具软件 > scale9grid > 使用案例 >

目标检测的Tricks | 【Trick4】Multi-scale training与Multi-scale testing

樊宏邈
2023-12-01

如有错误,恳请指出。


1. Multi-scale training理论概要

多尺度训练对全卷积网络有效,一般设置几种不同尺度的图片,训练时每隔一定iterations随机选取一种尺度训练。这样训练出来的模型鲁棒性强,其可以接受任意大小的图片作为输入,使用尺度小的图片测试速度会快些,但准确度低,用尺度大的图片测试速度慢,但是准确度高。

训练时,预先定义几个固定的尺度,每个epoch随机选择一个尺度进行训练(实际中还是单个尺度的训练)。


2. Multi-scale training实现代码

YOLOv3-SPP代码:

def train_one_epoch(model, optimizer, data_loader, device, epoch,
                    print_freq, accumulate, img_size,
                    grid_min, grid_max, gs,
                    multi_scale=False, warmup=False, scaler=None):
    ...
    # Multi-Scale
    if multi_scale:
        # accumulate=16  batch_size=4
        # 每训练accumulate个batch(batch_size*accumulate张图片),就随机修改一次输入图片大小
        # 由于label已转为相对坐标,故缩放图片不影响label的值
        if ni % accumulate == 0:  # ni=batch总个数
            # 在给定最大最小输入尺寸范围内随机选取一个size(size为32的整数倍)
            img_size = random.randrange(grid_min, grid_max + 1) * gs  # img_size = 320~736
        sf = img_size / max(imgs.shape[2:])  # scale factor
    
        # 如果图片最大边长不等于img_size, 则缩放一个batch图片,并将长和宽调整到32的整数倍
        if sf != 1:
            # gs: (pixels) grid size
            ns = [math.ceil(x * sf / gs) * gs for x in imgs.shape[2:]]  # new shape (stretched to 32-multiple)
            # 核心代码: 对图像进行双线性插值来缩放
            imgs = F.interpolate(imgs, size=ns, mode='bilinear', align_corners=False)
    ...
    pred = model(imgs)
    
    
def train(hyp):
    ...
    # 图像要设置成32的倍数
    gs = 32  # (pixels) grid size
    assert math.fmod(imgsz_test, gs) == 0, "--img-size %g must be a %g-multiple" % (imgsz_test, gs)
    grid_min, grid_max = imgsz_test // gs, imgsz_test // gs
    
    if multi_scale:
        imgsz_min = opt.img_size // 1.5
        imgsz_max = opt.img_size // 0.667
    
        # 将给定的最大,最小输入尺寸向下调整到32的整数倍
        grid_min, grid_max = imgsz_min // gs, imgsz_max // gs
        imgsz_min, imgsz_max = int(grid_min * gs), int(grid_max * gs)
        imgsz_train = imgsz_max  # initialize with max size
        print("Using multi_scale training, image range[{}, {}]".format(imgsz_min, imgsz_max))
        
    ...
    # 多尺度训练
    for epoch in range(start_epoch, epochs):
        mloss, lr = train_util.train_one_epoch(model, optimizer, train_dataloader,
                                               device, epoch,
                                               accumulate=accumulate,  # 迭代多少batch才训练完64张图片
                                               img_size=imgsz_train,  # 输入图像的大小
                                               multi_scale=multi_scale,
                                               grid_min=grid_min,  # grid的最小尺寸
                                               grid_max=grid_max,  # grid的最大尺寸
                                               gs=gs,  # grid step: 32
                                               print_freq=50,  # 每训练多少个step打印一次信息
                                               warmup=True,
                                               scaler=scaler)
    ...

简要分析:

从代码上来看,其实Multi-scale Training的理念很简单,就是每次epoch的随机在一个范围内选择一个图像尺度进行训练。


3. Multi-scale testing理论概要

测试时,生成几个不同尺度的feature map,对每个Region Proposal,在不同的feature map上也有不同的尺度,我们选择最接近某一固定尺寸(即检测头部的输入尺寸)的Region Proposal作为后续的输入。

常见的FPN结构,就是使用了多尺度特征层来预测,这里不再介绍。用兴趣的可以看一下之前的关于FPN的笔记:FPN(特征金字塔)结构笔记


参考资料:

https://blog.csdn.net/qq_40992227/article/details/115980500

 类似资料: