概述
faster_rcnn_code_analyze
这篇博文主要是按照faster rcnn的训练流程完成对faster rcnn的分析。
Faster_rcnn框架的配置
首先按照https://github.com/rbgirshick/py-faster-rcnn中的说明,完成Faster rcnn的配置。这里注意要将WITH_PYTHON_LAYER := 1。此外,如果要使用cudnn进行加速的话,因为Faster Rcnn原版本使用的是cudnn_v4,所以直接编译的话会出现错误。所以需要修改几个文件。下载最新的caffe代码,按照如下的方式修改
Faster rcnn代码。
1. 用最新caffe源码的以下文件替换掉faster rcnn 的对应文件
include/caffe/layers/cudnn_relu_layer.hpp
src/caffe/layers/cudnn_relu_layer.cpp
src/caffe/layers/cudnn_relu_layer.cu
include/caffe/layers/cudnn_sigmoid_layer.hpp
src/caffe/layers/cudnn_sigmoid_layer.cpp
src/caffe/layers/cudnn_sigmoid_layer.cu
include/caffe/layers/cudnn_tanh_layer.hpp
src/caffe/layers/cudnn_tanh_layer.cpp
src/caffe/layers/cudnn_tanh_layer.cu
2. 用caffe源码中的这个文件替换掉faster rcnn 对应文件
include/caffe/util/cudnn.hpp
3. 将 faster rcnn 中的 src/caffe/layers/cudnn_conv_layer.cu 文件中的所有
cudnnConvolutionBackwardData_v3 函数名替换为 cudnnConvolutionBackwardData
cudnnConvolutionBackwardFilter_v3函数名替换为 cudnnConvolutionBackwardFilter
这样的话,就可以编译通过了。
Fastercnn代码分析
配置完成以后,我用faster rcnn完成了kaggle中检测鲸鱼的实验https://www.kaggle.com/c/noaa-right-whale-recognition 因为我的目标主要是完成鲸鱼头部的检测,所以没有做识别。
为了简单起见,我只用了2679张鲸鱼图片作为训练集,按照VOC2007格式整理数据,我的数据格式如下:
py-faster-rcnn/data/Whale_devkit
/data
/Annotations 注释文件
/Images 鲸鱼图片
/ImageSets 训练图片名称集合
整理完数据后,我就开始进行训练了。Basenet使用的VGG16,采用了end2end的方式,迭代了1000次,得到最终的训练模型。训练完以后在py-faster-rcnn/experiments/logs目录下会得到训练的日志文件,下面我就按照这个日志文件完成对faster rcnn的代码分析。
训练的脚本使用的是py-faster-rcnn/experiments/scripts/faster_rcnn_end2end_whale.sh,在其中需要定义自己的数据集的名称,我这里取名为whale,里面需要指定三个参数。
TRAIN_IMDB="Whale_train" #这个将用到后面初始化数据集类
PT_DIR="Whale"
#指定输出的目录
ITERS=1000
#最大的迭代次数
下面实际上调用train_net.py进行训练:
time ../../tools/train_net.py --gpu ${GPU_ID}
--solver ../../models/${PT_DIR}/${NET}/faster_rcnn_end2end/solver.prototxt
--weights ../../data/imagenet_models/${NET}.v2.caffemodel
--imdb ${TRAIN_IMDB}
--iters ${ITERS}
--cfg ../cfgs/faster_rcnn_end2end.yml
${EXTRA_ARGS}
打开train_net.py分析main函数,上面只是设定训练的参数,需要注意的是--cfg ../cfgs/faster_rcnn_end2end.yml,这里指定了网络的配置文件,在config.py中已经有了默认的配置参数,不要直接修改它,使用自己写的yaml_file文件指明自己需要的参数值,调用cfg_from_file()去覆盖默认值。config.py中使用了Python的easydict方式,相比dict,easydict可以直接用.完成对key值的设置。我的配置参数如下:
Using config:
{'DATA_DIR': '/home/cjt/chen_obj/detection/py-faster-rcnn/data',
'DEDUP_BOXES': 0.0625,
'EPS': 1e-14,
'EXP_DIR': 'faster_rcnn_end2end',
'GPU_ID': 0,
'MATLAB': 'matlab',
'MODELS_DIR': '/home/cjt/chen_obj/detection/py-faster-rcnn/models/Whale',
'PIXEL_MEANS': array([[[ 102.9801,
115.9465,
122.7717]]]),
'RNG_SEED': 3,
'ROOT_DIR': '/home/cjt/chen_obj/detection/py-faster-rcnn',
'TEST': {'BBOX_REG': True,
'HAS_RPN': True,
'MAX_SIZE': 1000,
'NMS': 0.3,
'PROPOSAL_METHOD': 'selective_search',
'RPN_MIN_SIZE': 16,
'RPN_NMS_THRESH': 0.7,
'RPN_POST_NMS_TOP_N': 300,
'RPN_PRE_NMS_TOP_N': 6000,
'SCALES': [600],
'SVM': False},
'TRAIN': {'ASPECT_GROUPING': True,
'BATCH_SIZE': 128,
'BBOX_INSIDE_WEIGHTS': [1.0, 1.0, 1.0, 1.0],
'BBOX_NORMALIZE_MEANS': [0.0, 0.0, 0.0, 0.0],
'BBOX_NORMALIZE_STDS': [0.1, 0.1, 0.2, 0.2],
'BBOX_NORMALIZE_TARGETS': True,
'BBOX_NORMALIZE_TARGETS_PRECOMPUTED': True,
'BBOX_REG': True,
'BBOX_THRESH': 0.5,
'BG_THRESH_HI': 0.5,
'BG_THRESH_LO': 0.0,
'FG_FRACTION': 0.25,
'FG_THRESH': 0.5,
'HAS_RPN': True,
'IMS_PER_BATCH': 1,
'MAX_SIZE': 1000,
'PROPOSAL_METHOD': 'gt',
'RPN_BATCHSIZE': 256,
'RPN_BBOX_INSIDE_WEIGHTS': [1.0, 1.0, 1.0, 1.0],
'RPN_CLOBBER_POSITIVES': False,
'RPN_FG_FRACTION': 0.5,
'RPN_MIN_SIZE': 16,
'RPN_NEGATIVE_OVERLAP': 0.3,
'RPN_NMS_THRESH': 0.7,
'RPN_POSITIVE_OVERLAP': 0.7,
'RPN_POSITIVE_WEIGHT': -1.0,
'RPN_POST_NMS_TOP_N': 2000,
'RPN_PRE_NMS_TOP_N': 12000,
'SCALES': [600],
'SNAPSHOT_INFIX': '',
'SNAPSHOT_ITERS': 10000,
'USE_FLIPPED': True,
'USE_PREFETCH': False},
'USE_GPU_NMS': True}
接着分析train_net.py
imdb, roidb = combined_roidb(args.imdb_name)#返回whale对应类的对象和groundtruth+翻转后的roidb.
def combined_roidb(imdb_names):
def get_roidb(imdb_name):
imdb = get_imdb(imdb_name)
#调用factory.py中的get_imdb()
#根据imdb_name,调用了whale类的构造函数,返回了whale类的一个对象。
#对于每个数据集中都有一个数据集.py与之对应.对于本文来说就是whale.py.whale.py主要定义了数据集的位置,如何读取注释文件生成groundtruth的roi等等.
print ‘Loaded dataset {:s}
for training’.format(imdb.name)
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)
#所有的数据集类都有一个lmdb基类,set_proposal_method主要定义了候选区域的产生方式.本例就是调用self.gt_roidb产生候选区域
#好,打开whale.py分析gt_roidb()
# def gt_roidb(self):
cache_file = os.path.join(self.cache_path, self.name+’_gt_roidb.pkl’)
#有那个缓存就直接读取,所以重新训练模型的时候要删除旧的cache
if os.path.exists(cache_file):
with open(cache_file, ‘rb’) as fid:
roidb = cPickle.load(fid)
print ‘{} gt roidb loaded from {}’.format(self.name, cache_file)
return roidb
gt_roidb = [self._load_whale_annotation(index)
for index in self.image_index]
#_load_whale_annotation()用来加载图片的注释文件,返回一个dict,这个dict就是对图片进行描述。
每个图片由以下信息描述:
{
‘boxes’ : boxes, #N*4的数组,N是本图片候选框的个数,表征ground truth的位置
‘gt_classes’: gt_classes, #长度为N的向量,每个框对应类别的index
‘gt_overlaps’ : overlaps, #N*num_cls,每个框对应的类别为1
‘flipped’ : False, #是否进行翻转
‘seg_areas’ : seg_areas
}
with open(cache_file, ‘wb’) as fid:
cPickle.dump(gt_roidb, fid, cPickle.HIGHEST_PROTOCOL)
print ‘wrote gt roidb to {}’.format(cache_file)
return gt_roidb
print 'Set proposal method: {:s}'.format(cfg.TRAIN.PROPOSAL_METHOD)
roidb = get_training_roidb(imdb)
#调用train.py中的get_training_roidb()得到训练时使用的roidb.
#get_training_roidb()中先调用了imdb.append_flipped_images(),增加翻转后的图像,设置这些图像的描述信息。
然后调用了roidb.py中的prepare_roidb。prepare_roidb主要是为了丰富图像的描述,增加了图像的描述信息。
{
'image':图像的路径
'width':图像的宽
'height':图像的高
'max_classes':向量,每个框对应的类别
'max_overlaps':就理解成这个框属于此类别的概率吧
}
return roidb
roidbs = [get_roidb(s) for s in imdb_names.split('+')]
roidb = roidbs[0]
#两个及以上的数据集
if len(roidbs) > 1:
for r in roidbs[1:]:
#扩展其他数据集的roidb
roidb.extend(r)
imdb = datasets.imdb.imdb(imdb_names)
else:
imdb = get_imdb(imdb_names)
return imdb, roidb
哈哈,一大部分函数分析完了,接着分析后面的东西。
get_output_dir只是设置输出目录而已。
好了,下面就开始调用train_net()进行训练了,分析一下train_net():
def train_net(solver_prototxt, roidb, output_dir,pretrained_model=None, max_iters=40000):
roidb = filter_roidb(roidb)
#过滤一些不符合规则的roidb,就像论文里面说的
#max_overlaps > 0.5即为前景
#BG_THRESH_LO<max_overlaps<BG_THRESH_HI即为背景
sw = SolverWrapper(solver_prototxt, roidb, output_dir,
pretrained_model=pretrained_model)
#定义SolverWrapper类的一个对象,我们去看看SolverWrapper类的构造函数:
#这里面有一点要注意:就是要看看如何计算bounding-box的回归目标
#这里主要是调用了roi_data_layer.roidb中的add_bbox_regression_targets函数
#在add_bbox_regression_targets中为图片描述roidb增加了一项:
{
'bbox_targets'
#计算当前图片的boxes需要回归的目标[通过_compute_targets函数得到]
#num_box*5的数组
}
#_compute_targets
#1 先找到gt对应的box,再找到前景对应的box(ex-ROI)
#2 计算每个ex ROI和gt ROI的IOU
通过bbox_overlaps()计算
#3 找到与每个ex ROI最接近的gt ROI
#4 return targets(num_boxes*5的一个数组),第一列是label,后四列是真实的转化参数
论文里面已经提到了我们的bbox回归只是为了学习转化参数,让预测的box更接近真实
的box
#在add_bbox_regression_targets中还有对targets减均值和除以方差的操作,但我知道其中有什么作用
#构造优化类对象
#加载预训练好的模型
print 'Solving...'
model_paths = sw.train_model(max_iters)
#开始训练
print 'done solving'
return model_paths
最后
以上就是优美抽屉为你收集整理的欢迎使用CSDN-markdown编辑器faster_rcnn_code_analyze的全部内容,希望文章能够帮你解决欢迎使用CSDN-markdown编辑器faster_rcnn_code_analyze所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复