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-master\mmdet\models\backbones
中新建一个 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,
),