Journey from Original RefineDet

This module will explain how to start from the original RefineDet repo and get the model provided in the model zoo.

Prerequisite

  • Internet connection avaliable

  • Vitis AI docker succesfully starts

  • Conda environment ‘vitis-ai-caffe’ is enabled by conda activate vitis-ai-caffe

RefineDet

RefineDet is an one-stage objection detection network that could achieve better accuracy than two-stage networks before it’s publication but still maintains comparable speed performance of one-stage networks.

RefineDet can be seen as an improved version of SSD with addition of anchor refinement module (ARM), object detection module (ODM) and transfer connection block (TCB) to improve accuracy.

The detailed introduction about network itself is beyond the scope of this module, please refer to the original paper.

Adopt RefineDet to Vitis AI

In order to train and deploy the network with Vitis AI toolchain and DPU, original RefineDet needs few modifications to make it compatitble. The RefineDet repository provides scripts based on its own Caffe version and also provide pretrained network with different resolution on VOC or COCO dataset.

Here we will base on Xilinx Caffe, the Xilinx version with support of common networks and our own networks, to show the steps to adopt original network onto Vitis AI. The model we used in last module from Vitis AI model zoo is originated from 320*320 resolution COCO model.

We will brake the work into following two part:

  • Fundemental modification to the original network

  • Customized modification to covert 320x320 model into 480x360 model

We will use COCO 320x320 model as the example in the rest of the module, please download it from links provided RefineDet author

https://drive.google.com/open?id=1BIVvkSQM8DarpeqOpjgPpDxUoFq9ZxKM

http://pan.baidu.com/s/1gf8J7Yr

Extract the file package and files will be like this

--- VGGNet
|   --- coco
|   |   --- refinedet_vgg16_320x320
|   |   |   --- coco_refinedet_vgg16_320x320_final.caffemodel
|   |   |   --- deploy.prototxt
|   |   |   --- multi_test_deploy.prototxt
|   |   |   --- single_test_deploy.prototxt
|   |   |   --- solver.prototxt
|   |   |   --- test.prototxt
|   |   |   --- train.prototxt
|   |   |   --- VGG16_COCO_320.py

Fundemental Modification

In order to make any RefineDet models work with Vitis AI, following basic modifications are needed

Item 1. Change ‘Normalize’ layer into ‘BatchNorm’ layer

In the original network, Normalize layers are used after conv4_3 and conv5_3 which are not supported by DPU. The solution is to use BatchNorm layer as the alternative.

Please note that the BatchNorm layer will be right after the conv layer (conv4_3 or conv5_3) and before ReLu layer (in place), thus the top and bottom field should all be the name of conv layer (conv4_3 or conv5_3).

Change from conv4_3_norm to conv4_3_bn

layer {
  name: "conv4_3_norm"
  type: "Normalize"
  bottom: "conv4_3"
  top: "conv4_3_norm"
  norm_param {
    across_spatial: false
    scale_filler {
      type: "constant"
      value: 10
    }
    channel_shared: false
  }
}
layer {
  name: "conv4_3_bn"
  type: "BatchNorm"
  bottom: "conv4_3"
  top: "conv4_3"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 1
    decay_mult: 0
  }
  param {
    lr_mult: 1
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  phase: TRAIN
  batch_norm_param {
    scale_filler {
      type: "constant"
      value: 1
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

Change from conv5_3_norm to conv5_3_bn

layer {
  name: "conv5_3_norm"
  type: "Normalize"
  bottom: "conv5_3"
  top: "conv5_3_norm"
  norm_param {
    across_spatial: false
    scale_filler {
      type: "constant"
      value: 8
    }
    channel_shared: false
  }
}
layer {
  name: "conv5_3_bn"
  type: "BatchNorm"
  bottom: "conv5_3"
  top: "conv5_3"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 1
    decay_mult: 0
  }
  param {
    lr_mult: 1
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  phase: TRAIN
  batch_norm_param {
    scale_filler {
      type: "constant"
      value: 1
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

Item 2. Merge ‘train.prototxt’ and ‘test.prototxt’ into ‘trainval.prototxt’ for simpilicity (Optional)

In order to montior both loss and mAP during the training process, we could add last four layers from the test.prototxt into the end of the train.protoxt. At the same time, add AnnotatedData layer for TEST phase to get input data for testing.

Add multi_gpu_testing: false into AnnotatedData layer for TEST phase.

An exmaple prototxt after merge is included here, i.e, refinedet_baseline.prototxt.

Item 3. Change the layer types of ‘arm_loss’, ‘odm_loss’, ‘detection_out’ and ‘detection_eval’ to be the type name in Xilinx Caffe

In Xilinx Caffe, in order to avoid potential confilct, the layer types using by RefineDet are renamed, which is shown in below table:

| Layer | Original Layer Type | Layer Type in Xilinx Caffe | | —- | —- | —- | | arm_loss | MultiBoxLoss | MultiBoxLossRefine | | odm_loss | MultiBoxLoss | MultiBoxLossRefine | | detection_out | DetectionOutput | DetectionOutputRefine | | detection_eval | DetectionEvaluate | DetectionEvaluateRefine |

Item 4. Modify path to the necessary files

In the AnnotatedData layer for trainning, please change

- the path to the folder holding the train LMDB file

    data_param {
    source: "../cf_refinedet_coco_480_360_0.96_5.08G/data/coco2014_lmdb/train2014_lmdb/"
    batch_size: 20
    backend: LMDB
    }

- the path to the labelmap file

    label_map_file: "../cf_refinedet_coco_480_360_0.96_5.08G/labelmap.prototxt"

In the AnnotatedData layer for testing, please change

- the path to the folder holding the train LMDB file

    data_param {
    source: "../cf_refinedet_coco_480_360_0.96_5.08G/data/coco2014_lmdb/val2014_lmdb/"
    batch_size: 10
    backend: LMDB
    multi_gpu_testing: false
    }


- the path to the labelmap file

    label_map_file: "../cf_refinedet_coco_480_360_0.96_5.08G/labelmap.prototxt"

In the detection_eval layer, please change

- the path to the name_size file 

    name_size_file: "../cf_refinedet_coco_480_360_0.96_5.08G/data/test_name_size.txt"

Item 5. Modify solver.prototxt to change hyperparameters

Configure the hyperparameters according to your own environment (like GPU memory size) and your own training strategy. Some parameters used are listed here as example.

base_lr: 0.01
max_iter: 200000
lr_policy: "multistep"
stepvalue: 80000
stepvalue: 160000
type: "SGD"
gamma: 0.1
momentum: 0.9
weight_decay: 0.0005
snapshot: 5000
solver_mode: GPU
test_initialization: True
eval_type: "detection"
ap_version: "11point"

Customized Modification

To customize the 320x320 COCO model into the 480x360 model provided in Vitis AI model zoo, apart from the fundemental changes mentioned above, extra modifications are needed.

RefineDet uses TCB, the FPN like structure from layer conv4_3, conv5_3, fc7 to conv 6_2 which constructed by three 2x downsampling and corrsponding three 2x upsampling in between. This structure has the strict requriement that the kernel size (k_w and k_h) of layer conv4_3 must be the multiple of 8 (2^3). Also, before conv4_3 there is also three 2x downsampling during feature extraction. If directly change resolution 320x320 to 480x360 on original network, the k_w and k_h of layer conv4_3 will be 60 and 45, which will result in error for following TCB structure.

In order to have a 480x360 resolution network, special modificaitons have been made to make k_w and k_h of conv4_3 to be 64 and 48, which are explained in detailed in item 2 below.

Item 1. Change input size from 320x320 to 480x360

In the AnnotatedData layers, change width and height value in resize_param to be 480 and 360

    resize_param {
      prob: 1
      resize_mode: WARP
      height: 360
      width: 480
      interp_mode: LINEAR
      interp_mode: AREA
      interp_mode: NEAREST
      interp_mode: CUBIC
      interp_mode: LANCZOS4
    }

Item 2. Change convlution layers, pooling layer parameters to support new resolution

If we use original network parameters and structure in 480x360 resolution, the feature map size after conv4_3 will be 60x45, which cannot satisfy the requirement of following TCB structure and result in error.

In order to arrive at the feature map size of 64x48 after conv4_3, we provide a version of implementation. Please note that this is just one way to achieve the requirment, and that the feature map size or network structure/parameter can be modified in many different ways.

| Layer | Parameter | Original | Modified | Feature Map Size | | :—-: | :—-: | :—-: | :—-: | :—-: | | conv1_1 | pad | 1 | 2 | 482x362 | | conv1_2 | pad | 1 | 2 | 484x364 | | conv2_2 | pad | 1 | 2 | 244x184 | | conv3_1 | pad | 1 | 2 | 124x94 | | conv3_2 | pad | 1 | 2 | 126x96 | | conv3_3 | kernel_size | 3 | 2 | 64x48 | | | stride | 1 | 2 | | | | pad_w | 1 | 1 | | | | pad_h | 1 | 0 | | | pool3 | | | delete | | | conv4_1 | bottom | pool3 | conv3_3 | 64x48 | | conv4_3_bn | | - | add | | | pool4 | | | delete | | | conv5_1 | kernel_size | 3 | 2 | 32x24 | | | stride | 1 | 2 | | | | pad | 1 | 0 | | | | bottom | pool4 | conv4_3 | | | conv5_3_bn | | - | add | | | pool5 | | | delete | | | fc6 | kernel_size | 3 | 2 | 16x12 | | | stride | 1 | 2 | | | | pad | 3 | 0 | | | | bottom | pool5 | conv5_3 | | | conv5_3_norm | | | delete | | | TL4_1 | bottom | conv5_3_norm | conv5_3 | | | conv4_3_norm | | | delete | | | TL3_1 | bottom | conv4_3_norm | conv4_3 | | | conv4_3_norm_mbox_loc | bottom | conv4_3_norm | conv4_3 | | | conv4_3_norm_mbox_conf | bottom | conv4_3_norm | conv4_3 | | | conv4_3_norm_mbox_priorbox | bottom | conv4_3_norm | conv4_3 | | | conv5_3_norm_mbox_loc | bottom | conv5_3_norm | conv5_3 | | | conv5_3_norm_mbox_conf | bottom | conv5_3_norm | conv5_3 | | | conv5_3_norm_mbox_priorbox | bottom | conv5_3_norm | conv5_3 | |

All the above-mentioned modification can be found in the exmaple prototxt refinedet_baseline.prototxt.

Item 3. Change class number from 81 to 2

There five layers that relate to class number, four convlution layers and one loss layer:

- In convolution_param of following layers, change num_output from 243 to 6. 
  P3_mbox_conf
  P4_mbox_conf
  P5_mbox_conf
  P6_mbox_conf
    
- In odm_loss layer, change num_classes from 81 to 2 

Train the Modified Network

Use standard VGG_ILSVRC_16_layers_fc_reduced.caffemodel as the initial weights and train the modified version from scratch. Get it by running command

wget http://vision.cs.unc.edu/wliu/projects/ParseNet/VGG_ILSVRC_16_layers_fc_reduced.caffemodel

Train the network with following command

caffe train -solver solver.prototxt -weights VGG_ILSVRC_16_layers_fc_reduced.caffemodel -gpu 0 2>&1 | tee train.log

Detection mAP during one experimental training process could be

I0601 08:43:36.417382 17132 net.cpp:280] This network produces output detection_eval
I0601 08:45:59.333092 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.152085
I0601 10:21:55.472414 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.171831
I0601 11:57:21.744807 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.276751
I0601 13:32:53.489629 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.263878
I0601 15:08:20.257485 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.289203
I0601 16:43:48.145087 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.305306
I0601 18:19:49.653108 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.350838
I0601 19:55:23.386104 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.337912
I0601 21:30:57.058233 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.322393
I0601 23:06:30.205420 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.356988
I0602 00:42:07.622771 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.324532
I0602 02:17:28.071298 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.359916
I0602 03:52:34.299418 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.427493
I0602 05:28:08.372817 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.419444
I0602 07:03:43.965183 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.382097
I0602 08:39:05.628803 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.552272
I0602 10:14:16.057716 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.557035
I0602 11:50:01.469343 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.566706
I0602 13:25:44.348400 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.545264
I0602 15:01:17.255231 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.652842
I0602 16:36:42.457309 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.658513
I0602 18:18:52.569782 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.687939
I0602 21:29:55.022497 17132 solver.cpp:901]     Test net output #0: detection_eval = 0.692454

The model zoo has provided well trained baseline model as well as other three optimized models in different pruning ratio, which are corrsponding to model 10 to 13 in model download page. All models could be used to test mAP and deploy onboard by Vitis AI toolchain.

Continue toolchain content at the main page.