利用自己的数据集使用VGG16训练Faster R-CNN

目录

1建立数据集

1.1图片

1.2xml文件 

1.3数据集划分

2下载ImageNet数据集下预训练得到的模型

3修改prototxt配置文件

3.1修改train.prototxt

3.2修改test.prototxt

3.3修改solver.prototxt

3.4修改pascal_voc.py

3.5修改imdb.py

3.6修改train_net.py(运行train_net.py进行训练时修改)

3.7修改config.py(运行train_net.py进行训练时修改)

3.8修改faster_rcnn_end2end.sh(采用脚本训练时修改)

4.1训练准备

4.2模型训练

4.2.1通过运行脚本命令来训练模型

4.2.2通过运行py文件来训练模型

5测试模型

6Demo

6.1准备

6.2运行Demo


1建立数据集

        数据集格式应和VOC2007相同。

1.1图片

        图片命名按照VOC2007标准格式,如“000001.jpg”形式。训练集中所有的图片重命名后放在路径py-faster-rcnn\data\VOCdevkit2007\VOC2007\JPEGImages下。

1.2xml文件 

        利用labelImg工具对图片自定义绘制包围框,并生成与图片对应的xml文件,如000001.xml。生成的所有的xml文件放在路径py-faster-rcnn\data\VOCdevkit2007\VOC2007\Annotations下。

1.3数据集划分

        利用xml文件划分数据集,生成trainval.txt、train.txt、test.txt和val.txt文件。将生成的四个txt文件放在路径py-faster-rcnn\data\VOCdevkit2007\VOC2007\ImagesSets\Main下。参考下面的python程序:py-faster-rcnn划分数据集(训练集、验证集、训练验证集、测试集)

2下载ImageNet数据集下预训练得到的模型

        运行命令:

  $ cd py-fasyer-rcnn
  $ ./data/scripts/fetch_imagenet_models.sh

        下载的model保存在py-fasyer-rcnn /data/文件夹下,名称为imagenet_models。

├── caffe-fast-rcnn              # caffe框架目录

├── data       # 用来存放pretrained模型以及读取文件的cache缓存,还有一些下载模型的脚本

│   ├── cache

│   ├── demo

│   ├── ......

│   ├── scripts

│   ├── VOCdevkit             

│   ├── imagenet_models

│   │   ├── VGG16.v2.caffemodel

│   │   ├── VGG_CNN_M_1024.v2.caffemodel

│   │   └── ZF.v2.caffemodel 

│   └── ......                     

├── experiments                 # 存放配置文件以及运行的log文件

└── .....

3修改prototxt配置文件

        使用基于VGG16模型的近似联合训练方法(端对端)训练和测试Faster R-CNN,需要更改以下配置文件:

3.1修改train.prototxt

     文件路径py-faster-rcnn /models/pascal_voc/VGG16/faster_rcnn_end2end/train.prototxt

①修改input-data层(第11行)

    将原先的num_classes的“21”改成“**”(**为实际类别数+1(背景)):

layer {
  name: 'input-data'
  type: 'Python'
  top: 'data'
  top: 'im_info'
  top: 'gt_boxes'
  python_param {
  module: 'roi_data_layer.layer'
  layer: 'RoIDataLayer'
  param_str: "'num_classes': 21"     //目标类别数+1
  }
}

②修改roi-data层(第530行)

    将原先的num_classes的“21”改成“**”(**为实际类别数+1(背景)):

layer {
  name: 'roi-data'
  type: 'Python'
  bottom: 'rpn_rois'
  bottom: 'gt_boxes'
  top: 'rois'
  top: 'labels'
  top: 'bbox_targets'
  top: 'bbox_inside_weights'
  top: 'bbox_outside_weights'
  python_param {
    module: 'rpn.proposal_target_layer'
    layer: 'ProposalTargetLayer'
    param_str: "'num_classes': 21"     //目标类别数+1
  }
}

③修改cls_score层(第620行)

    将原先的num_classes的“21”改成“**”(**为实际类别数+1(背景)):

layer {
  name: "cls_score"
  type: "InnerProduct"
  bottom: "fc7"
  top: "cls_score"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 21     //目标类别数+1
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

④修改bbox_pred层(第643行)

    将原来的num_output的“84”改成“**”(**为(实际类别数+1(背景))*4):

layer {
  name: "bbox_pred"
  type: "InnerProduct"
  bottom: "fc7"
  top: "bbox_pred"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 84    //(目标类别数+1)*4
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

3.2修改test.prototxt

    文件路径py-faster-rcnn /models/pascal_voc/VGG16/faster_rcnn_end2end/test.prototxt。test.prototxt中没有input-data层,只需修改cls_score层和bbox_pred层的方式即可。

①修改cls_score层(第567行)

    将原先的num_classes的“21”改成“**”(**为实际类别数+1(背景)):

layer {
  name: "cls_score"
  type: "InnerProduct"
  bottom: "fc7"
  top: "cls_score"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 21     //目标类别数+1
    weight_filler {
      type: "gaussian"
      std: 0.01
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

②修改bbox_pred层(第592行)

    将原来的num_output的“84”改成“**”(**为(实际类别数+1(背景))*4):

layer {
  name: "bbox_pred"
  type: "InnerProduct"
  bottom: "fc7"
  top: "bbox_pred"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 84    //(目标类别数+1)*4
    weight_filler {
      type: "gaussian"
      std: 0.001
    }
    bias_filler {
      type: "constant"
      value: 0
    }
  }
}

3.3修改solver.prototxt

        文件路径py-faster-rcnn/models/pascal_voc/VGG16/faster_rcnn_end2end/solver.prototxt。该文件可以修改最大迭代次数等。

3.4修改pascal_voc.py

        文件路径py-faster-rcnn/ lib/datasets/pascal_voc.py。这里的类别以及之前的类别名称最好是全部小写,假如是大写的话,则会报keyError的错误。将其中的类别改为自己的。

self._classes = ('__background__',    # always index 0
                     'car tail', 'car head', 'car turn', 'car crosswide',
                     'bus tail', 'bus head', 'bus turn', 'bus crosswide',
                     'truck tail','truck head', 'truck turn', 'truck crosswide',        
                     'person','cyclist', 'cycle','tricycle','barricade','misc')

3.5修改imdb.py

文件路径py-faster-rcnn/lib/datasets/imdb.py。

def append_flipped_images(self):
        num_images = self.num_images
        # widths = self._get_widths()   # 修改前
        widths = [PIL.Image.open(self.image_path_at(i)).size[0]  # 修改后
                  for i in xrange(num_images)]               # 修改后
        for i in xrange(num_images):
            boxes = self.roidb[i]['boxes'].copy()
            oldx1 = boxes[:, 0].copy()
            oldx2 = boxes[:, 2].copy()
            boxes[:, 0] = widths[i] - oldx2 – 1
            for b in range(len(boxes)):    # 添加
                if boxes[b][2] < boxes[b][0]:   # 添加
                    boxes[b][0] = 0    # 添加
            print boxes[:, 0]      ####?
            boxes[:, 2] = widths[i] - oldx1 - 1
            print boxes[:, 0]      ####?
            assert (boxes[:, 2] >= boxes[:, 0]).all()
            entry = {'boxes' : boxes,
                     'gt_overlaps' : self.roidb[i]['gt_overlaps'],
                     'gt_classes' : self.roidb[i]['gt_classes'],
                     'flipped' : True}
            self.roidb.append(entry)
        self._image_index = self._image_index * 2

3.6修改train_net.py(运行train_net.py进行训练时修改)

        文件路径py-faster-rcnn/tools/train_net.py。可以为其中的命令行参数设置默认值,这样就不用每次训练时都在命令行设置多个参数了。

3.7修改config.py(运行train_net.py进行训练时修改)

        文件路径py-faster-rcnn/lib/fast_rcnn/config.py。

        修改:

 __C.TRAIN.SNAPSHOT_ITERS=10000

        该参数确定了模型每训练多少次保存一次快照,源码设置的是10000,根据自己设置的最大迭代次数来合理修改(它的值小于最大迭代次数,不然训练了半天一个模型都没保存)。

3.8修改faster_rcnn_end2end.sh(采用脚本训练时修改)

    文件路径:py-faster-rcnn/experiments/scripts/faster_rcnn_end2end.sh

    若调用脚本faster_rcnn_end2end.sh训练模型,则可以在文件中修改最大迭代次数。

  TRAIN_IMDB="coco_2014_train"
  TEST_IMDB="coco_2014_minival"
  PT_DIR="coco"
  ITERS=490000

4模型训练

4.1训练准备

        在训练新模型时候,为防止与之前的模型搞混,需要删除以下文件:

①删除py-faster-rcnn下的output文件夹;

②删除py-faster-rcnn/data/cache中的文件;

③删除py-faster-rcnn/data/VOCdevkit2007/annotations_cache中的文件。

        通过运行命令删除:

  sudo rm -rf ~/py-faster-rcnn/output/*
  sudo rm -rf ~/py-faster-rcnn/data/cache/*
  sudo rm -rf ~/py-faster-rcnn/data/VOCdevkit2007/annotations_cache/*
  sudo rm -rf ~/py-faster-rcnn/data/VOCdevkit2007/results/VOC2007/Main/*

4.2模型训练

4.2.1通过运行脚本命令来训练模型

  $ cd py-faster-rcnn
  $ sudo ./experiments/scripts/faster_rcnn_end2end.sh  0  VGG16  pascal_voc

其中,

  $ sudo  ./experiments/scripts/faster_rcnn_end2end.sh [GPU_ID]  [NET]  [--set ...]

(1)GPU_ID为训练所用的GPU,如果只有一块GPU,则为0;

(2)NET为使用的网络模型,可选择ZF、VGG_CNN_M_1024、VGG16;

(3)--set允许配置fast_rcnn.config文件中的各种选项。

4.2.2通过运行py文件来训练模型

  $ cd py-faster-rcnn
  $ sudo python ./tools/train_net.py --gpu 0 --solver models/pascal_voc/VGG16/faster_rcnn_end2end/solver.prototxt --weights data/imagenet_models/VGG16.v2.caffemodel --imdb voc_2007_trainval --cfg experiments/cfgs/faster_rcnn_end2end.yml 

        其中,

--gpu:代表机器上的GPU编号。

--solver:代表模型的配置文件,train.prototxt的文件路径已经包含在这个文件之中。

--weights:代表初始化的权重文件,这里用的是Imagenet上预训练好的模型,大型的网络我们选择用VGG_16.v2.caffemodel。

--imdb:给出的训练的数据库名字需要在factory.py的_sets中,在文件里面有_sets[‘hs’],train_net.py:这个文件会调用factory.py再生成hs这个类,来读取数据。

        训练完成后生成的模型保存在路径py-faster-rcnn\output\faster_rcnn_end2end\voc_2007_trainval下。

5测试模型

        运行命令(将vgg16_faster_rcnn_iter_10000.caffemodel修改为自己训练得到的模型):

  $ cd py-faster-rcnn
  $ sudo python ./tools/test_net.py --gpu 0 --def models/pascal_voc/VGG16/faster_rcnn_end2end/test.prototxt --net output/faster_rcnn_end2end/voc_2007_trainval/vgg16_faster_rcnn_iter_10000.caffemodel --imdb voc_2007_test --cfg experiments/cfgs/faster_rcnn_end2end.yml

      若测试时出现报错:IndexError:too many indices for array

原因:样本量太少,某些类别在测试集中没有,路径data/VOCdevkit2007/results/VOC2007/main.下生成的对应的txt文件是空的。

解决办法:在路径py-faster-rcnn/lib/datasets/voc_eval.py中的BB=BB[sorted_ind,:]上面一行添加语句if len(BB) !=0:(注意if后要缩进)

6Demo

6.1准备

        训练完成之后,将训练得到的py-faster-rcnn\output\faster_rcnn_end2end\voc_2007_trainval中的caffemodel拷贝至py-faster-rcnn\data\faster_rcnn_models下。

        修改py-faster-rcnn\tools\下demo.py的配置:

(1)修改CLASSES(第27行)

    把里面的原始标签全部改为自己的标签:

CLASSES = ('__background__',
           'car tail', 'car head', 'car turn', 'car crosswide',
            'bus tail', 'bus head', 'bus turn', 'bus crosswide', 
                   'truck tail','truck head', 'truck turn', 'truck crosswide', 
                        'person','cyclist','cycle','tricycle','barricade','misc')

(2)修改NETS(第39行)

    将VGG16_faster_rcnn_final.caffemodel修改为自己训练得到的模型:

NETS = {'vgg16': ('VGG16',
               'VGG16_faster_rcnn_final.caffemodel'),  
        'zf': ('ZF',
               'ZF_faster_rcnn_final.caffemodel'),
        'resnet50': ('ResNet-50',
               'ResNet-50_faster_rcnn_final.caffemodel')}

(3)修改prototxt(第124行)

    由于prototxt默认配置为faster_rcnn_alt_opt,所以需要修改为faster_rcnn_end2end。

将:

prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                            'faster_rcnn_alt_opt', 'faster_rcnn_test.pt')

     修改为:

    prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                             'faster_rcnn_end2end', 'test.prototxt')

(4)修改im_names(第148行)

    将内容修改为需要测试的图片名字,并把测试图片放在py-faster-rcnn\data\demo中,并按照训练图片的命名格式和大小来修改测试图片。

    例如测试图片为:

利用自己的数据集使用VGG16训练Faster R-CNN_第1张图片

     将:

  im_names = ['000456.jpg', '000542.jpg', '001150.jpg', '001763.jpg', '004545.jpg']

     修改为:

  im_names = ['000001.jpg', '000002.jpg', '000003.jpg', '000004.jpg', '000005.jpg', '000006.jpg']

6.2运行Demo

(1)将默认的模型改为VGG16

    在py-faster-rcnn\tools\demo.py的def parse_args()里修改默认参数:

parser.add_argument (
					‘–net’, 
					dest=’demo_net’, 
					help=’Network to use [vgg16]’,   
					choices=NETS.keys(),
					 default=’vgg16’         # 修改为vgg16
				 ) 

(2)运行

运行命令:

  $ cd py-faster-rcnn
  $ sudo python ./tools/demo.py

若不修改默认的模型,则运行命令:

  $ cd py-faster-rcnn
  $ sudo python ./tools/demo.py  --net vgg16

你可能感兴趣的:(深度学习,py-faster-rcnn)