1. 程式人生 > >【SSD】用caffe-ssd框架自帶VGG網路訓練自己的資料集

【SSD】用caffe-ssd框架自帶VGG網路訓練自己的資料集



一、挑選資料集

我先是從ImageNet官網下載了所有關於杯子的圖片

然後從ILSVRC2011,ILSVRC2012,ILSVRC2013和ILSVRC2015資料集通過搜尋xml中杯子的代號挑出了包含杯子的資料集。



二、處理xml檔案

我只需要杯子的資訊,其他物體資訊要從xml檔案中刪掉。否則生成lmdb檔案的時候會出現錯誤,提示“Unknown name: xxxxxxxx”。xxxx就是除了杯子以外的物體的代號。

嘗試了很多方法,不多說,看下面具體步驟:

1.將Annotations資料夾改名為:Annos

2.新建一個空資料夾名字為:Annotations

3.修改下面名字為“delete_by_name.py”的python工具程式碼,只需要修改if not後面內容。引號內為你要保留的資料的代號。

4.執行python工具。

[python] view plain copy print?
  1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3. """ 
  4. Created on Tue Oct 31 10:03:03 2017 
  5. @author: hans 
  6. http://blog.csdn.net/renhanchi 
  7. """
  8. import os  
  9. import xml.etree.ElementTree as ET  
  10. origin_ann_dir = 'Annos/'
  11. new_ann_dir = 'Annotations/'
  12. for dirpaths, dirnames, filenames in
     os.walk(origin_ann_dir):  
  13.   for filename in filenames:  
  14.     if os.path.isfile(r'%s%s' %(origin_ann_dir, filename)):  
  15.       origin_ann_path = os.path.join(r'%s%s' %(origin_ann_dir, filename))  
  16.       new_ann_path = os.path.join(r'%s%s' %(new_ann_dir, filename))  
  17.       tree = ET.parse(origin_ann_path)  
  18.       root = tree.getroot()  
  19.       for object in root.findall('object'):  
  20.         name = str(object.find('name').text)  
  21.         ifnot (name == "n03147509"or \  
  22.                 name == "n03216710"or \  
  23.                 name == "n03438257"or \  
  24.                 name == "n03797390"or \  
  25.                 name == "n04559910"or \  
  26.                 name == "n07930864"):  
  27.           root.remove(object)  
  28.       tree.write(new_ann_path)  
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 31 10:03:03 2017

@author: hans

http://blog.csdn.net/renhanchi
"""

import os
import xml.etree.ElementTree as ET

origin_ann_dir = 'Annos/'
new_ann_dir = 'Annotations/'

for dirpaths, dirnames, filenames in os.walk(origin_ann_dir):
  for filename in filenames:
    if os.path.isfile(r'%s%s' %(origin_ann_dir, filename)):
      origin_ann_path = os.path.join(r'%s%s' %(origin_ann_dir, filename))
      new_ann_path = os.path.join(r'%s%s' %(new_ann_dir, filename))
      tree = ET.parse(origin_ann_path)
  
      root = tree.getroot()
      for object in root.findall('object'):
        name = str(object.find('name').text)
        if not (name == "n03147509" or \
                name == "n03216710" or \
                name == "n03438257" or \
                name == "n03797390" or \
                name == "n04559910" or \
                name == "n07930864"):
          root.remove(object)
  
      tree.write(new_ann_path)


三、生成訓練集和驗證集txt檔案

先新建一個名字為doc的資料夾

下面名字為“cup_list.sh”程式碼並不是我最終使用的,你們根據自己情況做適當修改。

[python] view plain copy print?
  1. #!/bin/sh
  2. classes=(JPEGImages Annotations)  
  3. root_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )  
  4. for dataset in train val  
  5. do  
  6.         if [ $dataset == "train" ]  
  7.         then  
  8.                 data_dir=(ILSVRC2015_train ILSVRC2015_val ILSVRC_train ImageNet)  
  9.         fi  
  10.         if [ $dataset == "val" ]  
  11.         then  
  12.                 data_dir=(ILSVRC_val)  
  13.         fi  
  14.         for cla in ${data_dir[@]}  
  15.         do  
  16.             forclassin ${classes[@]}  
  17.             do  
  18.                 find ./$cla/$class/ -name "*.jpg" >> ${class}_${dataset}.txt  
  19.             done  
#!/bin/sh

classes=(JPEGImages Annotations)
root_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )

for dataset in train val
do
        if [ $dataset == "train" ]
        then
                data_dir=(ILSVRC2015_train ILSVRC2015_val ILSVRC_train ImageNet)
        fi
        if [ $dataset == "val" ]
        then
                data_dir=(ILSVRC_val)
        fi
        for cla in ${data_dir[@]}
        do
	        for class in ${classes[@]}
	        do
		        find ./$cla/$class/ -name "*.jpg" >> ${class}_${dataset}.txt
	        done
[python] view plain copy print?
  1. forclassin ${classes[@]}  
  2. do  
  3.  find ./$cla/$class/ -name "*.jpg" >> ${class}_${dataset}.txt  
  4. done  
	      for class in ${classes[@]}
	      do
		      find ./$cla/$class/ -name "*.jpg" >> ${class}_${dataset}.txt
	      done
done paste -d' ' JPEGImages_${dataset}.txt Annotations_${dataset}.txt >> temp_${dataset}.txt cat temp_${dataset}.txt | awk 'BEGIN{srand()}{print rand()"\t"$0}' | sort -k1,1 -n | cut -f2- > $dataset.txt if [ $dataset == "val" ] then /home/hans/caffe-ssd/build/tools/get_image_size $root_dir $dataset.txt $dataset"_name_size.txt" fi rm temp_${dataset}.txt rm JPEGImages_${dataset}.txt rm Annotations_${dataset}.txtdonemv train.txt doc/mv val.txt doc/mv val_name_size.txt doc/



四、寫labelmap_cup.prototxt

這個檔案放到doc目錄下。

有幾個問題需要注意。

1.label 0 必須是background

2.雖然我只檢測杯子,但是xml檔案中杯子name的程式碼有好幾個。

    我一開始將所有label都設定為1,後來生成lmdb檔案的時候報錯。

    我只能乖乖的按順序寫下去,不過問題不大。反正知道1到6都是杯子就好。


五、生成lmdb檔案

這先是出現了上面提到的Unknown name錯誤,通過修改xml解決了。

後來又出現呼叫caffe模組的Symbol錯誤,反正你們跟我走就好,錯不了。

先修改一個檔案caffe-ssd/scripts/create_annoset.py



然後執行cup_data.sh

[python] view plain copy print?
  1. cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )  
  2. root_dir=/home/hans/caffe-ssd  
  3. redo=1
  4. data_root_dir="${cur_dir}"
  5. dataset_name="doc"
  6. mapfile="${cur_dir}/doc/labelmap_cup.prototxt"
  7. anno_type="detection"
  8. db="lmdb"
  9. min_dim=0
  10. max_dim=0
  11. width=0
  12. height=0
  13. extra_cmd="--encode-type=JPEG --encoded"
  14. if [ $redo ]  
  15. then  
  16.   extra_cmd="$extra_cmd --redo"
  17. fi  
  18. for subset in train val  
  19. do  
  20.   python $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-map-file=$mapfile --min-dim=$min_dim \  
  21. --max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir \  
  22. $cur_dir/$dataset_name/$subset.txt $data_root_dir/$dataset_name/$subset"_"$db ln/  
  23. done  
  24. rm -rf  ln/  
cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
root_dir=/home/hans/caffe-ssd

redo=1
data_root_dir="${cur_dir}"
dataset_name="doc"
mapfile="${cur_dir}/doc/labelmap_cup.prototxt"
anno_type="detection"
db="lmdb"
min_dim=0
max_dim=0
width=0
height=0

extra_cmd="--encode-type=JPEG --encoded"
if [ $redo ]
then
  extra_cmd="$extra_cmd --redo"
fi
for subset in train val
do
  python $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-map-file=$mapfile --min-dim=$min_dim \
--max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir \
$cur_dir/$dataset_name/$subset.txt $data_root_dir/$dataset_name/$subset"_"$db ln/
done
rm -rf  ln/


六、訓練

先去下載預訓練模型放到doc目錄下。

修改訓練程式碼真是一件熬心熬力的事兒,路徑太多,問題也不少。還好github issues上作業挺給力。

先放出我的ssd_pascal.py程式碼:

[python] view plain copy print?
  1. from __future__ import print_function  
  2. import sys  
  3. sys.path.append("/home/hans/caffe-ssd/python")  #####改
  4. import caffe  
  5. from caffe.model_libs import *  
  6. from google.protobuf import text_format  
  7. import math  
  8. import os  
  9. import shutil  
  10. import stat  
  11. import subprocess  
  12. # Add extra layers on top of a "base" network (e.g. VGGNet or Inception).
  13. def AddExtraLayers(net, use_batchnorm=True, lr_mult=1):  
  14.     use_relu = True
  15.     # Add additional convolutional layers.
  16.     # 19 x 19
  17.     from_layer = net.keys()[-1]  
  18.     # TODO(weiliu89): Construct the name using the last layer to avoid duplication.
  19.     # 10 x 10
  20.     out_layer = "conv6_1"
  21.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 256101,  
  22.         lr_mult=lr_mult)  
  23.     from_layer = out_layer  
  24.     out_layer = "conv6_2"
  25.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 512312,  
  26.         lr_mult=lr_mult)  
  27.     # 5 x 5
  28.     from_layer = out_layer  
  29.     out_layer = "conv7_1"
  30.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 128101,  
  31.       lr_mult=lr_mult)  
  32.     from_layer = out_layer  
  33.     out_layer = "conv7_2"
  34.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 256312,  
  35.       lr_mult=lr_mult)  
  36.     # 3 x 3
  37.     from_layer = out_layer  
  38.     out_layer = "conv8_1"
  39.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 128101,  
  40.       lr_mult=lr_mult)  
  41.     from_layer = out_layer  
  42.     out_layer = "conv8_2"
  43.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 256301,  
  44.       lr_mult=lr_mult)  
  45.     # 1 x 1
  46.     from_layer = out_layer  
  47.     out_layer = "conv9_1"
  48.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 128101,  
  49.       lr_mult=lr_mult)  
  50.     from_layer = out_layer  
  51.     out_layer = "conv9_2"
  52.     ConvBNLayer(net, from_layer, out_layer, use_batchnorm, use_relu, 256301,  
  53.       lr_mult=lr_mult)  
  54.     return net  
  55. ### Modify the following parameters accordingly ###
  56. # The directory which contains the caffe code.
  57. # We assume you are running the script at the CAFFE_ROOT.
  58. caffe_root = "/home/hans/caffe-ssd"#####改
  59. # Set true if you want to start training right after generating all files.
  60. run_soon = True
  61. # Set true if you want to load from most recently saved snapshot.
  62. # Otherwise, we will load from the pretrain_model defined below.
  63. resume_training = True
  64. # If true, Remove old model files.
  65. remove_old_models = False
  66. # The database file for training data. Created by data/VOC0712/create_data.sh
  67. train_data = "/home/hans/data/ImageNet/Detection/cup/doc/train_lmdb"#########改
  68. # The database file for testing data. Created by data/VOC0712/create_data.sh
  69. test_data = "/home/hans/data/ImageNet/Detection/cup/doc/val_lmdb"########改
  70. # Specify the batch sampler.
  71. resize_width = 300
  72. resize_height = 300
  73. resize = "{}x{}".format(resize_width, resize_height)  
  74. batch_sampler = [  
  75.         {  
  76.                 'sampler': {  
  77.                         },  
  78.                 'max_trials'1,  
  79.                 'max_sample'1,  
  80.         },  
  81.         {  
  82.                 'sampler': {  
  83.                         'min_scale'0.3,  
  84.                         'max_scale'1.0,  
  85.                         'min_aspect_ratio'0.5,  
  86.                         'max_aspect_ratio'2.0,  
  87.                         },  
  88.                 'sample_constraint': {  
  89.                         'min_jaccard_overlap'0.1,  
  90.                         },  
  91.                 'max_trials'50,  
  92.                 'max_sample'1,  
  93.         },  
  94.         {  
  95.                 'sampler': {  
  96.                         'min_scale'0.3,  
  97.                         'max_scale'1.0,  
  98.                         'min_aspect_ratio'0.5,  
  99.                         'max_aspect_ratio'2.0,  
  100.                         },  
  101.                 'sample_constraint': {  
  102.                         'min_jaccard_overlap'0.3,  
  103.                         },  
  104.                 'max_trials'50,  
  105.                 'max_sample'1,  
  106.         },  
  107.         {  
  108.                 'sampler': {  
  109.                         'min_scale'0.3,  
  110.                         'max_scale'1.0,  
  111.                         'min_aspect_ratio'0.5,  
  112.                         'max_aspect_ratio'2.0,  
  113.                         },  
  114.                 'sample_constraint': {  
  115.                         'min_jaccard_overlap'0.5,  
  116.                         },  
  117.                 'max_trials'50,  
  118.                 'max_sample'1,  
  119.         },  
  120.         {  
  121.                 'sampler': {  
  122.                         'min_scale'0.3,  
  123.                         'max_scale'1.0,  
  124.                         'min_aspect_ratio'0.5,  
  125.                         'max_aspect_ratio'2.0,  
  126.                         },  
  127.                 'sample_constraint': {  
  128.                         'min_jaccard_overlap'0.7,  
  129.                         },  
  130.                 'max_trials'50,  
  131.                 'max_sample'1,  
  132.         },  
  133.         {  
  134.                 'sampler': {  
  135.                         'min_scale'0.3,  
  136.                         'max_scale'1.0,  
  137.                         'min_aspect_ratio'0.5,  
  138.                         'max_aspect_ratio'2.0,  
  139.                         },  
  140.                 'sample_constraint': {  
  141.                         'min_jaccard_overlap'0.9,  
  142.                         },  
  143.                 'max_trials'50,  
  144.                 'max_sample'1,  
  145.         },  
  146.         {  
  147.                 'sampler': {  
  148.                         'min_scale'0.3,  
  149.                         'max_scale'1.0,  
  150.                         'min_aspect_ratio'0.5,  
  151.                         'max_aspect_ratio'2.0,  
  152.                         },  
  153.                 'sample_constraint': {  
  154.                         'max_jaccard_overlap'1.0,  
  155.                         },  
  156.                 'max_trials'50,  
  157.                 'max_sample'1,  
  158.         },  
  159.         ]  
  160. train_transform_param = {  
  161.         'mirror'True,  
  162.         'mean_value': [104117123],  
  163.         'force_color'True,  ####改
  164.         'resize_param': {  
  165.                 'prob'1,  
  166.                 'resize_mode': P.Resize.WARP,  
  167.                 'height': resize_height,  
  168.                 'width': resize_width,  
  169.                 'interp_mode': [  
  170.                         P.Resize.LINEAR,  
  171.                         P.Resize.AREA,  
  172.                         P.Resize.NEAREST,  
  173.                         P.Resize.CUBIC,  
  174.                         P.Resize.LANCZOS4,  
  175.                         ],  
  176.                 },  
  177.         'distort_param': {  
  178.                 'brightness_prob'0.5,  
  179.                 'brightness_delta'32,  
  180.                 'contrast_prob'0.5,  
  181.                 'contrast_lower'0.5,  
  182.                 'contrast_upper'1.5,  
  183.                 'hue_prob'0.5,  
  184.                 'hue_delta'18,  
  185.                 'saturation_prob'0.5,  
  186.                 'saturation_lower'0.5,  
  187.                 'saturation_upper'1.5,  
  188.                 'random_order_prob'0.0,  
  189.                 },  
  190.         'expand_param': {  
  191.                 'prob'0.5,  
  192.                 'max_expand_ratio'4.0,  
  193.                 },  
  194.         'emit_constraint': {  
  195.             'emit_type': caffe_pb2.EmitConstraint.CENTER,  
  196.             }  
  197.         }  
  198. test_transform_param = {  
  199.         'mean_value': [104117123],  
  200.         'force_color'True,    ####改
  201.         'resize_param': {  
  202.                 'prob'1,  
  203.                 'resize_mode': P.Resize.WARP,  
  204.                 'height': resize_height,  
  205.                 'width': resize_width,  
  206.                 'interp_mode': [P.Resize.LINEAR],  
  207.                 },  
  208.         }  
  209. # If true, use batch norm for all newly added layers.
  210. # Currently only the non batch norm version has been tested.
  211. use_batchnorm = False
  212. lr_mult = 1
  213. # Use different initial learning rate.
  214. if use_batchnorm:  
  215.     base_lr = 0.0004
  216. else:  
  217.     # A learning rate for batch_size = 1, num_gpus = 1.
  218.     base_lr = 0.00004
  219. root = "/home/hans/data/ImageNet/Detection/cup"####改
  220. # Modify the job name if you want.
  221. job_name = "SSD_{}".format(resize)   ####改
  222. # The name of the model. Modify it if you want.
  223. model_name = "VGG_CUP_{}".format(job_name)    ####改
  224. # Directory which stores the model .prototxt file.
  225. save_dir = "{}/doc/{}".format(root, job_name)    ####改
  226. # Directory which stores the snapshot of models.
  227. snapshot_dir = "{}/models/{}".format(root, job_name)    ####改
  228. # Directory which stores the job script and log file.
  229. job_dir = "{}/jobs/{}".format(root, job_name)    ####改
  230. # Directory which stores the detection results.
  231. output_result_dir = "{}/results/{}".format(root, job_name)    ####改
  232. # model definition files.
  233. train_net_file = "{}/train.prototxt".format(save_dir)  
  234. test_net_file = "{}/test.prototxt".format(save_dir)  
  235. deploy_net_file = "{}/deploy.prototxt".format(save_dir)  
  236. solver_file = "{}/solver.prototxt".format(save_dir)  
  237. # snapshot prefix.
  238. snapshot_prefix = "{}/{}".format(snapshot_dir, model_name)  
  239. # job script path.
  240. job_file = "{}/{}.sh".format(job_dir, model_name)  
  241. # Stores the test image names and sizes. Created by data/VOC0712/create_list.sh
  242. name_size_file = "{}/doc/val_name_size.txt".format(root)    ####改
  243. # The pretrained model. We use the Fully convolutional reduced (atrous) VGGNet.
  244. pretrain_model = "{}/doc/VGG_ILSVRC_16_layers_fc_reduced.caffemodel".format(root)    ####改
  245. # Stores LabelMapItem.
  246. label_map_file = "{}/doc/labelmap_cup.prototxt".format(root)    ####改
  247. # MultiBoxLoss parameters.
  248. num_classes = 7####改
  249. share_location = True
  250. background_label_id=0
  251. train_on_diff_gt = True
  252. normalization_mode = P.Loss.VALID  
  253. code_type = P.PriorBox.CENTER_SIZE  
  254. ignore_cross_boundary_bbox = False
  255. mining_type = P.MultiBoxLoss.MAX_NEGATIVE  
  256. neg_pos_ratio = 3.
  257. loc_weight = (neg_pos_ratio + 1.) / 4.
  258. multibox_loss_param = {  
  259.     'loc_loss_type': P.MultiBoxLoss.SMOOTH_L1,  
  260.     'conf_loss_type': P.MultiBoxLoss.SOFTMAX,  
  261.     'loc_weight': loc_weight,  
  262.     'num_classes': num_classes,  
  263.     'share_location': share_location,  
  264.     'match_type': P.MultiBoxLoss.PER_PREDICTION,  
  265.     'overlap_threshold'0.5,  
  266.     'use_prior_for_matching'True,  
  267.     'background_label_id': background_label_id,  
  268.     'use_difficult_gt': train_on_diff_gt,  
  269.     'mining_type': mining_type,  
  270.     'neg_pos_ratio': neg_pos_ratio,  
  271.     'neg_overlap'0.5,  
  272.     'code_type': code_type,  
  273.     'ignore_cross_boundary_bbox': ignore_cross_boundary_bbox,  
  274.     }  
  275. loss_param = {  
  276.     'normalization': normalization_mode,  
  277.     }  
  278. # parameters for generating priors.
  279. # minimum dimension of input image
  280. min_dim = 300
  281. # conv4_3 ==> 38 x 38
  282. # fc7 ==> 19 x 19
  283. # conv6_2 ==> 10 x 10
  284. # conv7_2 ==> 5 x 5
  285. # conv8_2 ==> 3 x 3
  286. # conv9_2 ==> 1 x 1
  287. mbox_source_layers = ['conv4_3''fc7''conv6_2''conv7_2''conv8_2''conv9_2']  
  288. # in percent %
  289. min_ratio = 20
  290. max_ratio = 90
  291. step = int(math.floor((max_ratio - min_ratio) / (len(mbox_source_layers) - 2)))  
  292. min_sizes = []  
  293. max_sizes = []  
  294. for ratio in xrange(min_ratio, max_ratio + 1, step):  
  295.   min_sizes.append(min_dim * ratio / 100.)  
  296.   max_sizes.append(min_dim * (ratio + step) / 100.)  
  297. min_sizes = [min_dim * 10 / 100.] + min_sizes  
  298. max_sizes = [min_dim * 20 / 100.] + max_sizes  
  299. steps = [8163264100300]  
  300. aspect_ratios = [[2], [23], [23], [23], [2], [2]]  
  301. # L2 normalize conv4_3.
  302. normalizations = [20, -1, -1, -1, -1, -1]  
  303. # variance used to encode/decode prior bboxes.
  304. if code_type == P.PriorBox.CENTER_SIZE:  
  305.   prior_variance = [0.10.10.20.2]  
  306. else:  
  307.   prior_variance = [0.1]  
  308. flip = True
  309. clip = False
  310. # Solver parameters.
  311. # Defining which GPUs to use.
  312. gpus = "7"####改
  313. gpulist = gpus.split(",")  
  314. num_gpus = len(gpulist)  
  315. # Divide the mini-batch to different GPUs.
  316. batch_size = 32
  317. accum_batch_size = 32
  318. iter_size = accum_batch_size / batch_size  
  319. solver_mode = P.Solver.CPU  
  320. device_id = 0
  321. batch_size_per_device = batch_size  
  322. if num_gpus > 0:  
  323.   batch_size_per_device = int(math.ceil(float(batch_size) / num_gpus))  
  324.   iter_size = int(math.ceil(float(accum_batch_size) / (batch_size_per_device * num_gpus)))  
  325.   solver_mode = P.Solver.GPU  
  326.   device_id = int(gpulist[0])  
  327. if normalization_mode == P.Loss.NONE:  
  328.   base_lr /= batch_size_per_device  
  329. elif normalization_mode == P.Loss.VALID:  
  330.   base_lr *= 25. / loc_weight  
  331. elif normalization_mode == P.Loss.FULL:  
  332.   # Roughly there are 2000 prior bboxes per image.
  333.   # TODO(weiliu89): Estimate the exact # of priors.
  334.   base_lr *= 2000.
  335. # Evaluate on whole test set.
  336. num_test_image = 2000####改
  337. test_batch_size = 8
  338. # Ideally test_batch_size should be divisible by num_test_image,
  339. # otherwise mAP will be slightly off the true value.
  340. test_iter = int(math.ceil(float(num_test_image) / test_batch_size))  
  341. solver_param = {  
  342.     # Train parameters
  343.     'base_lr': base_lr,  
  344.     'weight_decay'0.0005,  
  345.     'lr_policy'"multistep",  
  346.     'stepvalue': [80000100000120000],  
  347.     'gamma'0.1,  
  348.     'momentum'0.9,  
  349.     'iter_size': iter_size,  
  350.     'max_iter'120000,  
  351.     'snapshot'80000,  
  352.     'display'10,  
  353.     'average_loss'10,  
  354.     'type'"SGD",  
  355.     'solver_mode': solver_mode,  
  356.     'device_id': device_id,  
  357.     'debug_info'False,  
  358.     'snapshot_after_train'True,  
  359.     # Test parameters
  360.     'test_iter': [test_iter],  
  361.     'test_interval'100,  
  362.     'eval_type'"detection",  
  363.     'ap_version'"11point",  
  364.     'test_initialization'True,  
  365.     }  
  366. # parameters for generating detection output.
  367. det_out_param = {  
  368.     'num_classes': num_classes,  
  369.     'share_location': share_location,  
  370.     'background_label_id': background_label_id,  
  371.     'nms_param': {'nms_threshold'0.45'top_k'400},  
  372.     'save_output_param': {  
  373.         'output_directory': output_result_dir,  
  374.