Faster R-CNN 训练源码学习笔记
2018-01-07 20:47
411 查看
Faster R-CNN训练脚本:.\experiments\script_faster_rcnn_VOC2007_ZF.m文件
在这里,dataset包含train和test两部分,其中每部分又包括imdb和roidb两部分。这些会保存在目录:imdb\cache
以imdb_train为例,其包括的主要信息(这里面没有图像的实际数据,更多是一些索引和路径):
conf_proposal函数是proposal的配置文件,详见faster_rcnn\functions\rpn\proposal_config.m文件。conf_fast_rcnn同理。所谓set_cache_folder是只设置模型训练过程中的缓存目录,详见experiments\+Faster_RCNN_Train\set_cache_folder.m。比如output\rpn_cachedir\faster_rcnn_VOC2007_ZF_stage1_rpn这种目录。
proposal_prepare_chahors函数是训练脚本文件内部定义的函数(如下),它调用了两个函数:一个是proposal_calc_output_size函数,详见functions\rpn\proposal_calc_output_size.m,是建立网络输入图像的尺度(宽高)与其输出数据的尺度之间的映射关系,比如,输入一个600*800图像,conv_5层输出39*51的特征图,那么一对数据就是一条映射。proposal_generate_anchors函数详见functions\rpn\proposal_generate_anchors.m,是生成9(三种尺度,三种比例)个anchors的。
训练通过Faster_RCNN_Train的类函数do_proposal_train进行,该函数详见experiments\+Faster_RCNN_Train\do_proposal_train.m,该函数进一步调用functions\rpn目录下的proposal_train函数。proposal_train函数代码很长,这里不直接引用。按照作者的注解,该函数首先是配置,然后尝试寻找已经训练好的模型,之后进行初始化(包括打开日志,和caffe的相关初始化),然后准备训练数据和验证数据的信息(尚未开始读入图像),之后检查GPU显存是不是足够,最后就是训练(在迭代次数达到之前,一直进行训练。每次训练前,先根据索引读入minibatch的数据,然后执行训练步骤。而且还要检查是否执行验证,是否打印快照(保存中间模型))。最终,保存模型,关闭日志,重置caffe。
下面调用do_proposal_test函数执行两个测试,一是对训练集,二是对测试集。函数运行的结果是:dataset.roidb_train和dataset.roidb_test得到更新(更新后的数据集用于下一步训练fast rcnn):
这里附录do_proposal_test函数的部分(通过test过程生成的anchors,作为训练fast rcnn的输入数据):
训练fast rcnn的代码与训练rpn的代码相似。这里do_fast_rcnn_train用于训练,do_fast_rcnn_test用于测试,返回mAP(mean average precision)。参考models\fast_rcnn_prototxts\ZF\train_val.prototxt,可知训练时网络
b278
的输入数据有5个,分别是:data(输入图像数据),rois(输入包围盒坐标及其类别数据),labels(类别的标签),bbox_targets(包围盒的标签),bbox_loss_weights(包围盒损失权重)。在这里,其维度分别是:800*600*3*2(2代表每批包含两张图像),1*1*5*128,1*1*1*128,1*1*8*128,1*1*8*128。后两个维度里面的“8”是随着类别数量变化的,如果类别是k,则这里的维度为4*(k+1)。我这里k=1,因此维度为8。
与stage one proposal 不同的主要有两个地方:一是用stage one fast rcnn训练后的模型参数来初始化stage two proposal的模型;二是将训练时模型文件换成models\fast_rcnn_prototxts\ZF_fc6\train_val.prototxt,目的是固定卷积层,只微调RPN独有的层。ZF_fc6目录下的模型与ZF目录下的模型的区别在于:前者将前面的卷积层的学习率设置为0(如下图),那么在训练网络时,这里的参数就不会更新了。
之后,同样用这一步训练好的RPN生成一些建议框,用于下一步训练fast rcnn
类似地,它也是用stage one fast rcnn的训练好的模型参数初始化自己的网络模型,也是固定卷积层,只微调其全连接层。
比如,最终模型保存在:output\faster_rcnn_final\faster_rcnn_VOC2007_ZF\,内容如图:
function script_faster_rcnn_VOC2007_ZF() % script_faster_rcnn_VOC2007_ZF() % Faster rcnn training and testing with Zeiler & Fergus model % -------------------------------------------------------- % Faster R-CNN % Copyright (c) 2015, Shaoqing Ren % Licensed under The MIT License [see LICENSE for details] % -------------------------------------------------------- clc; clear mex; clear is_valid_handle; % to clear init_key run(fullfile(fileparts(fileparts(mfilename('fullpath'))), 'startup')); %% -------------------- CONFIG -------------------- opts.caffe_version = 'caffe_faster_rcnn'; opts.gpu_id = auto_select_gpu; active_caffe_mex(opts.gpu_id, opts.caffe_version); % do validation, or not opts.do_val = true; % model model = Model.ZF_for_Faster_RCNN_VOC2007; % cache base cache_base_proposal = 'faster_rcnn_VOC2007_ZF'; cache_base_fast_rcnn = ''; % train/test data dataset = []; use_flipped = true; dataset = Dataset.voc2007_trainval(dataset, 'train', use_flipped); dataset = Dataset.voc2007_test(dataset, 'test', false); %% -------------------- TRAIN -------------------- % conf conf_proposal = proposal_config('image_means', model.mean_image, 'feat_stride', model.feat_stride); conf_fast_rcnn = fast_rcnn_config('image_means', model.mean_image); % set cache folder for each stage model = Faster_RCNN_Train.set_cache_folder(cache_base_proposal, cache_base_fast_rcnn, model); % generate anchors and pre-calculate output size of rpn network [conf_proposal.anchors, conf_proposal.output_width_map, conf_proposal.output_height_map] ... = proposal_prepare_anchors(conf_proposal, model.stage1_rpn.cache_name, model.stage1_rpn.test_net_def_file); %% stage one proposal fprintf('\n***************\nstage one proposal \n***************\n'); % train model.stage1_rpn = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage1_rpn, opts.do_val); % test dataset.roidb_train = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false); dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, dataset.imdb_test, dataset.roidb_test); %% stage one fast rcnn fprintf('\n***************\nstage one fast rcnn\n***************\n'); % train model.stage1_fast_rcnn = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage1_fast_rcnn, opts.do_val); % test opts.mAP = Faster_RCNN_Train.do_fast_rcnn_test(conf_fast_rcnn, model.stage1_fast_rcnn, dataset.imdb_test, dataset.roidb_test); %% stage two proposal % net proposal fprintf('\n***************\nstage two proposal\n***************\n'); % train model.stage2_rpn.init_net_file = model.stage1_fast_rcnn.output_model_file; model.stage2_rpn = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage2_rpn, opts.do_val); % test dataset.roidb_train = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false); dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, dataset.imdb_test, dataset.roidb_test); %% stage two fast rcnn fprintf('\n***************\nstage two fast rcnn\n***************\n'); % train model.stage2_fast_rcnn.init_net_file = model.stage1_fast_rcnn.output_model_file; model.stage2_fast_rcnn = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage2_fast_rcnn, opts.do_val); %% final test fprintf('\n***************\nfinal test\n***************\n'); model.stage2_rpn.nms = model.final_test.nms; dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, dataset.imdb_test, dataset.roidb_test); opts.final_mAP = Faster_RCNN_Train.do_fast_rcnn_test(conf_fast_rcnn, model.stage2_fast_rcnn, dataset.imdb_test, dataset.roidb_test); % save final models, for outside tester Faster_RCNN_Train.gather_rpn_fast_rcnn_models(conf_proposal, conf_fast_rcnn, model, dataset); end function [anchors, output_width_map, output_height_map] = proposal_prepare_anchors(conf, cache_name, test_net_def_file) [output_width_map, output_height_map] ... = proposal_calc_output_size(conf, test_net_def_file); anchors = proposal_generate_anchors(cache_name, ... 'scales', 2.^[3:5]); end
1、初始准备
clc; clear mex; %清理mex文件 clear is_valid_handle; % to clear init_key run(fullfile(fileparts(fileparts(mfilename('fullpath'))), 'startup'));%运行根目录下的startup.m文件,添加搜索路径,创建目录。
2、配置
%% -------------------- CONFIG -------------------- opts.caffe_version = 'caffe_faster_rcnn';%caffe路径:external\caffe\matlab\caffe_faster_rcnn opts.gpu_id = auto_select_gpu; %自动选择显存最大的一个显卡,返回其显卡索引号 active_caffe_mex(opts.gpu_id, opts.caffe_version); %激活caffe % do validation, or not opts.do_val = true; %使用验证。就是在训练过程中通过验证集测评模型的表现 % model model = Model.ZF_for_Faster_RCNN_VOC2007;%模型配置,这个在experiments\+Model目录下 % cache base cache_base_proposal = 'faster_rcnn_VOC2007_ZF';%与缓存文件的文件名有关 cache_base_fast_rcnn = ''; % train/test data dataset = []; use_flipped = true; %使用“翻转”,就是将训练集通过水平翻转图像以实现数据增强。 dataset = Dataset.voc2007_trainval(dataset, 'train', use_flipped);%训练集和测试集信息 dataset = Dataset.voc2007_test(dataset, 'test', false);
在这里,dataset包含train和test两部分,其中每部分又包括imdb和roidb两部分。这些会保存在目录:imdb\cache
以imdb_train为例,其包括的主要信息(这里面没有图像的实际数据,更多是一些索引和路径):
3、训练准备
%% -------------------- TRAIN -------------------- % conf conf_proposal = proposal_config('image_means', model.mean_image, 'feat_stride', model.feat_stride); conf_fast_rcnn = fast_rcnn_config('image_means', model.mean_image); % set cache folder for each stage model = Faster_RCNN_Train.set_cache_folder(cache_base_proposal, cache_base_fast_rcnn, model); % generate anchors and pre-calculate output size of rpn network [conf_proposal.anchors, conf_proposal.output_width_map, conf_proposal.output_height_map] ... = proposal_prepare_anchors(conf_proposal, model.stage1_rpn.cache_name, model.stage1_rpn.test_net_def_file);
conf_proposal函数是proposal的配置文件,详见faster_rcnn\functions\rpn\proposal_config.m文件。conf_fast_rcnn同理。所谓set_cache_folder是只设置模型训练过程中的缓存目录,详见experiments\+Faster_RCNN_Train\set_cache_folder.m。比如output\rpn_cachedir\faster_rcnn_VOC2007_ZF_stage1_rpn这种目录。
proposal_prepare_chahors函数是训练脚本文件内部定义的函数(如下),它调用了两个函数:一个是proposal_calc_output_size函数,详见functions\rpn\proposal_calc_output_size.m,是建立网络输入图像的尺度(宽高)与其输出数据的尺度之间的映射关系,比如,输入一个600*800图像,conv_5层输出39*51的特征图,那么一对数据就是一条映射。proposal_generate_anchors函数详见functions\rpn\proposal_generate_anchors.m,是生成9(三种尺度,三种比例)个anchors的。
function [anchors, output_width_map, output_height_map] = proposal_prepare_anchors(conf, cache_name, test_net_def_file) [output_width_map, output_height_map] ... = proposal_calc_output_size(conf, test_net_def_file); anchors = proposal_generate_anchors(cache_name, ... 'scales', 2.^[3:5]); end
4、训练: stage one proposal
训练分为两个阶段(stage),每个阶段又分为训练rpn和训练fast rcnn,因此总共四块。这里介绍第一阶段的rpn训练。该网络用ImageNet预训练的模型初始化,并端到端微调用于区域建议任务。%% stage one proposal fprintf('\n***************\nstage one proposal \n***************\n'); % train model.stage1_rpn = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage1_rpn, opts.do_val); % test dataset.roidb_train = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false); dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage1_rpn, dataset.imdb_test, dataset.roidb_test);
训练通过Faster_RCNN_Train的类函数do_proposal_train进行,该函数详见experiments\+Faster_RCNN_Train\do_proposal_train.m,该函数进一步调用functions\rpn目录下的proposal_train函数。proposal_train函数代码很长,这里不直接引用。按照作者的注解,该函数首先是配置,然后尝试寻找已经训练好的模型,之后进行初始化(包括打开日志,和caffe的相关初始化),然后准备训练数据和验证数据的信息(尚未开始读入图像),之后检查GPU显存是不是足够,最后就是训练(在迭代次数达到之前,一直进行训练。每次训练前,先根据索引读入minibatch的数据,然后执行训练步骤。而且还要检查是否执行验证,是否打印快照(保存中间模型))。最终,保存模型,关闭日志,重置caffe。
下面调用do_proposal_test函数执行两个测试,一是对训练集,二是对测试集。函数运行的结果是:dataset.roidb_train和dataset.roidb_test得到更新(更新后的数据集用于下一步训练fast rcnn):
这里附录do_proposal_test函数的部分(通过test过程生成的anchors,作为训练fast rcnn的输入数据):
function roidb_new = do_proposal_test(conf, model_stage, imdb, roidb) aboxes = proposal_test(conf, imdb, ... 'net_def_file', model_stage.test_net_def_file, ... 'net_file', model_stage.output_model_file, ... 'cache_name', model_stage.cache_name); %每张图像生成约20000个数量级的anchors。 aboxes = boxes_filter(aboxes, model_stage.nms.per_nms_topN, model_stage.nms.nms_overlap_thres, model_stage.nms.after_nms_topN, conf.use_gpu); %过滤box,其数目降为2000数量级。 roidb_regions = make_roidb_regions(aboxes, imdb.image_ids); roidb_new = roidb_from_proposal(imdb, roidb, roidb_regions, ... 'keep_raw_proposal', false); end
5、训练:stage one fast rcnn
利用第一步的RPN生成的建议框,由Fast R-CNN训练一个单独的检测网络,这个检测网络同样是由ImageNet预训练的模型初始化的,这时候两个网络还没有共享卷积层。%% stage one fast rcnn fprintf('\n***************\nstage one fast rcnn\n***************\n'); % train model.stage1_fast_rcnn = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage1_fast_rcnn, opts.do_val); % test opts.mAP = Faster_RCNN_Train.do_fast_rcnn_test(conf_fast_rcnn, model.stage1_fast_rcnn, dataset.imdb_test, dataset.roidb_test);
训练fast rcnn的代码与训练rpn的代码相似。这里do_fast_rcnn_train用于训练,do_fast_rcnn_test用于测试,返回mAP(mean average precision)。参考models\fast_rcnn_prototxts\ZF\train_val.prototxt,可知训练时网络
b278
的输入数据有5个,分别是:data(输入图像数据),rois(输入包围盒坐标及其类别数据),labels(类别的标签),bbox_targets(包围盒的标签),bbox_loss_weights(包围盒损失权重)。在这里,其维度分别是:800*600*3*2(2代表每批包含两张图像),1*1*5*128,1*1*1*128,1*1*8*128,1*1*8*128。后两个维度里面的“8”是随着类别数量变化的,如果类别是k,则这里的维度为4*(k+1)。我这里k=1,因此维度为8。
6、训练:stage two proposal
开始第二阶段的训练。%% stage two proposal % net proposal fprintf('\n***************\nstage two proposal\n***************\n'); % train model.stage2_rpn.init_net_file = model.stage1_fast_rcnn.output_model_file; model.stage2_rpn = Faster_RCNN_Train.do_proposal_train(conf_proposal, dataset, model.stage2_rpn, opts.do_val); % test dataset.roidb_train = cellfun(@(x, y) Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, x, y), dataset.imdb_train, dataset.roidb_train, 'UniformOutput', false); dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, dataset.imdb_test, dataset.roidb_test);
与stage one proposal 不同的主要有两个地方:一是用stage one fast rcnn训练后的模型参数来初始化stage two proposal的模型;二是将训练时模型文件换成models\fast_rcnn_prototxts\ZF_fc6\train_val.prototxt,目的是固定卷积层,只微调RPN独有的层。ZF_fc6目录下的模型与ZF目录下的模型的区别在于:前者将前面的卷积层的学习率设置为0(如下图),那么在训练网络时,这里的参数就不会更新了。
之后,同样用这一步训练好的RPN生成一些建议框,用于下一步训练fast rcnn
7、训练:stage two fast rcnn
第二阶段的fast rcnn训练。%% stage two fast rcnn fprintf('\n***************\nstage two fast rcnn\n***************\n'); % train model.stage2_fast_rcnn.init_net_file = model.stage1_fast_rcnn.output_model_file; model.stage2_fast_rcnn = Faster_RCNN_Train.do_fast_rcnn_train(conf_fast_rcnn, dataset, model.stage2_fast_rcnn, opts.do_val);
类似地,它也是用stage one fast rcnn的训练好的模型参数初始化自己的网络模型,也是固定卷积层,只微调其全连接层。
8、最终测试
最终测试,用于评估本次训练的模型的表现。%% final test fprintf('\n***************\nfinal test\n***************\n'); model.stage2_rpn.nms = model.final_test.nms; dataset.roidb_test = Faster_RCNN_Train.do_proposal_test(conf_proposal, model.stage2_rpn, dataset.imdb_test, dataset.roidb_test); opts.final_mAP = Faster_RCNN_Train.do_fast_rcnn_test(conf_fast_rcnn, model.stage2_fast_rcnn, dataset.imdb_test, dataset.roidb_test);
9、保存最终模型
% save final models, for outside tester Faster_RCNN_Train.gather_rpn_fast_rcnn_models(conf_proposal, conf_fast_rcnn, model, dataset); end
比如,最终模型保存在:output\faster_rcnn_final\faster_rcnn_VOC2007_ZF\,内容如图:
相关文章推荐
- 七月算法深度学习笔记5--CNN训练注意事项与框架使用
- 卷积神经网络(CNN)学习笔记2:模型训练
- CTC学习笔记(五) eesen训练源码
- Faster R-CNN学习笔记
- CNN入门详解及TensorFlow源码实现--深度学习笔记
- 【深度学习】笔记7: CNN训练Cifar-10技巧 ---如何进行实验,如何进行构建自己的网络模型,提高精度
- 卷积神经网络(CNN)学习笔记2:模型训练
- 卷积神经网络(CNN)学习笔记2:模型训练
- CNN学习笔记(三)RCNN、Fast RCNN、Faster RCNN对比学习
- 【深度学习】笔记15 微软官方源码caffe的第一个测例Mnist训练运行配置
- caffe学习笔记之Caffe for Windows 训练cifar10
- [Paper 学习笔记] Effcient Multi-Scale 3D CNN with fully connected CRF for Brain Lesion Segmentation
- [TensorFlow学习笔记2]构建训练softmax分类器
- nginx 源码学习笔记(五)——nginx精粹-模块
- RealVNC源码学习笔记 一
- jQuery入门级学习笔记及源码,很好很强大的jQuery
- CAFFE源码学习笔记之七-layer_factory以及layer基类
- 比特币源码学习笔记(二)
- 学习笔记:springmvc4.3源码学习:spring解析配置文件过程