• mmdetection 选用自定义 backbone训练


    学习率

    lr = (base_lr / 8) x num_gpus x (img_per_gpu/2)

    其中 base_lr 是源码中给定的 学习率,这是在 8张GPU上面,每张GPU上面放2张图片得到的学习率,所以当对应的GPU数目和每张GPU上的图片数目发生改变时,学习率成正比例变化。

    选用新的backbone来训练

    这里选用 res2net_26w_6s 作为backbone;
    以cascade_rcnn_r50_fpn_1x.py 作为config文件

    • mmdetection-mastermmdetmodelsackbones中新建一个 res2net.py文件,并将模型代码复制进去 https://github.com/Res2Net/Res2Net-PretrainedModels/blob/master/res2net.py

    • 由于这里需要多尺度特征图,可参考 原有的 resnet.py,返回的是stage1,stage2,stage3,stage4组成的list,因此新增的 res2net.py的代码需要进行修改

      • 1). 源码:
        class Res2Net(nn.Module):
           def __init__(self, block, layers, baseWidth = 26, scale = 4, num_classes=1000):
      

      修改:添加一个register;需要再import from ..registry import BACKBONES; 同时把block中的参数先写上默认参数,不然后面的config文件中传 block名字时比较麻烦

        @BACKBONES.register_module
        class Res2Net(nn.Module):
           def __init__(self, block=Bottle2neck, layers=[3,4,6,3], baseWidth=26, scale=6, num_classes=1000):
      
      • 2). 源码:class Res2Net下面的 forward

            def forward(self, x):
            x = self.conv1(x)
            x = self.bn1(x)
            x = self.relu(x)
            x = self.maxpool(x)
        
            x = self.layer1(x)
            x = self.layer2(x)
            x = self.layer3(x)
            x = self.layer4(x)
        
            x = self.avgpool(x)
            x = x.view(x.size(0), -1)
            x = self.fc(x)
        
            return x
        

        修改:返回stage1, stage2,stage3,stage4

            def forward(self, x):
            x = self.conv1(x)
            x = self.bn1(x)
            x = self.relu(x)
            x = self.maxpool(x)
        
            x1 = self.layer1(x)
            x2 = self.layer2(x1)
            x3 = self.layer3(x2)
            x4 = self.layer4(x3)
        
            #x = self.avgpool(x)
            #x = x.view(x.size(0), -1)
            #x = self.fc(x)
        
            return [x1,x2,x3,x4]
        
      • 3). 增加一个 init_weights函数(这边是不添加就报错,所以就直接从 resnet.py 中复制过来了),如resnet.py中一样,修改对应的block名称

          def init_weights(self, pretrained=None):
            if isinstance(pretrained, str):
                from mmdet.apis import get_root_logger
                logger = get_root_logger()
                load_checkpoint(self, pretrained, strict=False, logger=logger)
            elif pretrained is None:
                for m in self.modules():
                    if isinstance(m, nn.Conv2d):
                        kaiming_init(m)
                    elif isinstance(m, (_BatchNorm, nn.GroupNorm)):
                        constant_init(m, 1)
      
                if self.dcn is not None:
                    for m in self.modules():
                        if isinstance(m, Bottle2neck) and hasattr(
                                m, 'conv2_offset'):
                            constant_init(m.conv2_offset, 0)
      
                if self.zero_init_residual:
                    for m in self.modules():
                        if isinstance(m, Bottle2neck):
                            constant_init(m.norm3, 0)
                        # elif isinstance(m, BasicBlock):
                        #     constant_init(m.norm2, 0)
            else:
                raise TypeError('pretrained must be a str or None')
      
    • 修改 config 文件,cascade_rcnn_r50_fpn_1x.py
      源码:

    # model settings
    model = dict(
        type='CascadeRCNN',
        num_stages=3,
        pretrained='torchvision://resnet50',
        backbone=dict(
            type='ResNet',
            depth=50,
            num_stages=4,
            out_indices=(0, 1, 2, 3),
            frozen_stages=1,
            style='pytorch'),
    

    修改:

    model = dict(
        type='CascadeRCNN',
        num_stages=3,
        #pretrained='torchvision://resnet50',
        pretrained='/media/mtc/dac70756-6922-445c-9cbe-58847ebdc56f/zql/mmdetection/pretrained_models/res2net50_26w_6s-19041792.pth',
        backbone=dict(
            type='Res2Net',
            layers=[3,4,6,3], baseWidth=26, scale=6, num_classes=1000,
            ),
    
  • 相关阅读:
    Java中的函数传递
    Java中的native关键字浅析(JNI)
    抽象类简单举例
    提升java性能的基本方法
    Java中throw和throws的区别
    直接插入排序以及java实现
    Java实现定时任务的三种方法
    Java求素数的算法
    Hibernate基于注解的元数据
    Java多线程之Callable接口的实现
  • 原文地址:https://www.cnblogs.com/qiulinzhang/p/12252033.html
Copyright © 2020-2023  润新知