Object detection Transfer Learning

Hi,
I’m trying to transfer-learn with yolo3_darknet53_voc
I have a train_plate.rec file with labelled example. Training SSD on SageMaker works fine so there is presumably no problem with the .rec file.
In gluoncv I’m doing the following:

train_data = gluon.data.DataLoader(
        dataset=mx.gluon.data.RecordFileDataset('train_plate.rec'),
        batch_size=32,
        shuffle=True,
        last_batch='rollover',
        num_workers=4)

ctx = [mx.cpu()]

net = gcv.model_zoo.get_model('yolo3_darknet53_voc', pretrained=True)

net.reset_class(classes)

Then calling net.collect_params().reset_ctx(ctx) returns "ValueError: Cannot reset context for Parameter 'yolov30_yolooutputv30_conv0_weight' because it has not been initialized." What is wrong?

using ssd_512_vgg16_atrous_voc instead of yolo3_darknet53_voc produces no error

Hey there,

My guess is that when you run net.reset_class(classes) some of the weights specifically yolov30_yolooutputv30_conv0_weight, yolov30_yolooutputv31_conv0_weight etc become uninitialized.

Taking a look at the reset_class function here: https://gluon-cv.mxnet.io/_modules/gluoncv/model_zoo/yolo/yolo3.html shows that that is indeed the case.

This line

self.prediction = nn.Conv2D(
            all_pred, kernel_size=1, padding=0, strides=1, prefix=self.prediction.prefix)

shows the creation of a new convolution layer in the reset_class function, so you’ll need to initialize the weights for that layer before you can copy to the context you want. You can use something like below to initialize the specific parameters created if you really need the reset_class function.

import mxnet as mx

import gluoncv as gcv

net.reset_class(classes)

net.collect_params('yolov30_yolooutputv.*_conv*').initialize()

net.collect_params().reset_ctx(ctx)

try this:

self.net = get_model('ssd_512_vgg16`Preformatted text`_atrous_custom', classes=self.classes, pretrained_base=False, transfer='voc')
for param in self.net.collect_params().values():
    if param._data is None:       
        param.initialize()
1 Like

Hi, I have trained the yolo v3 network with pretrained weights and custom data successful, you can check my blog to find out how to do it if you are interesting.

1 Like

hi!

I have solved this issue by means of using the yolo3_darknet53_custom model from the model zoo. This one expects a list of the new classes that will be used to train your model. Here are the modifications I did to the file (I am currently training locally and plan to move this to BYOM scripting mode):

# classes
classes=train_dataset.classes
# network
if args.dataset in ['voc','coco']:
    net_name = '_'.join(('yolo3', args.network, args.dataset))
else:
    net_name = '_'.join(('yolo3', args.network, 'custom'))
args.save_prefix += net_name
# use sync bn if specified
if args.syncbn and len(ctx) > 1:
    print('Requested sync batch normalization')
    net = get_model(net_name, pretrained_base=True, norm_layer=gluon.contrib.nn.SyncBatchNorm,
                    norm_kwargs={'num_devices': len(ctx)})
    net.reset_class(classes)
    if args.pretrained:
        print("Will load pretrained weights of COCO")
        async_net = get_model(net_name, pretrained_base=False,pretrained=True,ctx=ctx,classes=classes)
    else:
        print("Will load non pretrained weights")
        async_net = get_model(net_name, pretrained_base=False,pretrained=False,ctx=ctx,classes=classes)  # used by cpu worker
else:
    print('No sync batch normalization will be performed')
    if args.pretrained:
        print("Will load pretrained weights of COCO")
        net = get_model(net_name, pretrained_base=True,pretrained=True,ctx=ctx,classes=classes)
    else:
        print("Will load non pretrained weights")
        net = get_model(net_name, pretrained_base=True,pretrained=False,ctx=ctx,classes=classes)

Hope this helps! Happy training!