如何mtp管理才能发展训练将Faster R-CNN训练起来

关于Faster R-CNN的一切——笔记3:Faster R-CNN
博主课题需要研究Faster RCNN,先后看了RCNN、Fast RCNN和Faster RCNN三篇paper,然而有点懵逼= =所以准备再捋一遍总结一下~
三、Faster R-CNN【Faster R-CNN--Towards Real-Time Object Detection with Region Proposal Networks.2015NIPS】
理解了R-CNN和Fast R-CNN之后,我们终于可以昂首阔步进入Faster R-CNN的解读啦~\(≧▽≦)/~啦啦啦
SPPnet和Fast R-CNN都加速了R-CNN的检测过程,然而瓶颈问题:region proposal computation却没有考虑。因此,Faster R-CNN的核心改进就是设计了一个Region Proposal Network(RPN),在每个图像位置输出一个预测的object bounding box和objectness score,这个网络与原来的Fast R-CNN共享conv feature map,所以几乎不增加计算量。
1.什么结构
网络输入是一张image
经过RPN生成一系列rectangular object proposals
image和它的object proposals一起送入Fast R-CNN网络,输出最终的检测结果
显然,最重要的就是这个Region Proposal Network(RPN)怎么设计,下面分析。
RPN的整体结构(1)首先生成conv feature map
明确一点,RPN与原来的Fast R-CNN网络共享从image生成conv feature map的过程。
例如对于VGG16,结构如下:
【image→conv3-64→conv3-64→pool2→conv3-128→conv3-128→pool2→conv3-256→conv3-256→conv3-256→pool2→
conv3-512→conv3-512→conv3-512→pool2→conv3-512→conv3-512→conv3-512→pool2→FC4096→FC4096→FC1000】
那么从image到最后一个conv3-512层这13个卷积层和4个pooling层是RPN和Fast R-CNN共享的,对于VGG16,最后一个conv3-512层输出的是512通道的W*H大小的(W和H=原图像宽高/16,因为有4个pooling层,每次大小减半)conv feature map,接下来的RPN操作就是基于这个conv feature map。
(2)在conv feature map的每个sliding window位置上生成特征向量
用一个n*n(本文是3*3)大小的滑动窗口(可以理解为卷积核)以1为步长在conv feature map上滑动。在每个sliding位置上,卷积核与它覆盖的conv featue map对应元素相乘并相加输出对应值,也就是卷积了。注意:conv feature map是3维的,对于VGG16而言是第三维是512通道,则每个通道独立的与卷积核作用,所以最后卷积核在每个滑动窗口位置都会生成一个1*512维的向量。然后,这个1*512维的向量被送入两个并列的FC层,一个分类的FC层输出分类结果,一个回归的FC层输出box
regressor也就是物体位置坐标。
上面所说的sliding window模式,在所有的空间位置上的FC层的参数是共享的,所以这样的结构很自然的可以被应用为一个n*n的卷积层和两个并列的1*1的卷积层【1*1的卷积层其实就是每个卷积核通道数与输入通道数相同,卷积核的个数就是你想要的输出维数。例如对于VGG16,每个卷积核是512通道。】。但是注意这样的n*n“卷积层”和我们平常理解的不太一样,我来解释一下:
我们平时理解的卷积层操作如下图所示。例如这是一个有2个filter的卷积层(因此输出是2通道的),每个filter是3通道的(与输入通道数相同)。输出volume中第1个通道里第一个位置的结果10是由filter w0的三个通道分别与输入volume的第一个receptive field的三个通道分别相乘然后相加的结果:10=1+4+4+1bias。
但是本文里面想表达的其实是如下图的意思:
所以如果要是想和普通的卷积层一样的话,应该如下图这么设置,简单地说第i个filter只有第i个通道是n*n个系数,其他通道都全为0,每个filter的n*n个系数文章中没有说一样不一样诶,可能需要实际跑一边代码看看了~。这样就可以应用普通的卷积层来完成RPN想要的sliding window模式。
(3)每个sliding window位置的特征向量送入两个并列的FC层做预测
有了特征向量,显然可以分类了,那么分几类?文章说我们要在这个sliding window位置根据它的特征向量同时预测出k个region proposals,那么回归的FC层输出就是4k维的了,因为每个proposal有4个坐标嘛~分类的FC层输出2k个分数来估计每个proposal是物体的概率和不是物体的概率。但是这k个proposal不是凭空整出来的,而是要相对一个参照,叫做archors,这也是RPN网络很核心的一个概念,下面详细说明:
平移不变的Anchors
在每个sliding window·的中心,定义3种尺度和3种aspect ratio共9种anchors。对于一个大小是W*H的conv feature map,一共有W*H*9个anchors。注意,anchors是圈出原image中的某块区域,所以按照Fast R-CNN RoI pooling层要完成的第一个任务【即把region
proposal投影到conv feature map上,参考博主的Fast R-CNN笔记啦啦啦~】,我们需要把sliding window【这是在conv feature map上的啊注意了】的中心坐标投影到原image上,然后就能找到原image上这些anchors应该对应的区域。这一点文章中并没有明确说出,但是可以推断出来。因为首先文章中使用的anchors最小也是128*128像素的,而feature map大小在40*60,所以anchors不可能是在feature
map上;然后,从archors的意义上我们来想,它是你的网络将要预测的region proposal的参照物对吧,region proposal是在原image上的对吧,所以anchors必然是在原image上的。但是sliding window是在conv feature map上的,所以我们一定会需要conv feature map往原image位置的映射,这就和Fast R-CNN要把原image上的region proposal投影到conv feature
map是一个道理,只不过过程反过来了,我说清楚了吧~#这是吐槽。。。我看paper的时候就这一点十分不解,还是看了SPPnet的文章才明白这个投影是什么鬼的,强烈谴责Faster R-CNN的作者╭(╯^╰)╮#
附上原paper的图总结一下RPN网络的结构:
(4)根据分类的score对region proposals进行非极大值抑制
先去掉所有IoU小于0.7的那些proposal,然后剩下的运行NMS(和以前一样了啦不再详细说)。然后用前N个region proposal送入Fast R-CNN进行物体检测。
2.怎么训练
显然,我们需要训练RPN和Fast R-CNN两个网络。首先以预训练的VGG16为例比较两个网络的结构:
所以为了共享conv feature map,两个网络的交替训练流程应该是:
用预训练模型初始化网络参数,然后fine-tune训练RPN
用同一个预训练模型初始化网络参数,然后fine-tune训练Fast R-CNN,使用RPN网络输出的region proposals
用Fast R-CNN初始化RPN(肯定是共有部分啦),固定共有的conv层(参数不再变化),只fine-tuned RPN独有的层
固定共有的conv层,fine-tune Fast R-CNN的FC层
Fast R-CNN不说了,就是和原Fast R-CNN的训练一毛一样只不过产生region proposals的方法由selective search变成RPN网络啦~
用ImageNet网络来初始化RPN和Fast R-CNN啦~比较了ZFnet和VGG16net两个。
RPN网络的fine-tune
#刚刚经历了电梯惊魂的博主回来继续写了......生命苦短,要好好珍惜,好好学习T T#
(1)首先是loss function怎么定义
先明确一下有两个任务:一是分类任务,即判断这个anchor是不是物体;二是回归任务,即给出bounding box的预测坐标。所以说这种multi task的东东,肯定有两个loss项啦:
i是一个mini-batch(在本文就是一张image和它里面的所有anchor)里的anchor的index;pi是算法输出的anchor i是物体的概率;pi*是anchor i的ground-thuth label;ti是一个四元素的向量,是算法预测的bounding box的参数化坐标;ti*是与一个正anchor相关的ground-truth box。
分类loss是两类上的log loss(是物体和不是物体),回归loss和Fast R-CNN中的定义一样。
关于ti和ti*,都是参数化的坐标,也就是都相对于anchor而定义,如下图,所以你可以理解为:在原image上有很多ground-truth box,现在人为的规定了很多anchor box,你的算法要做的事情其实就是把anchor box回归到离它最近的ground-truth box那里去~
(2)anchor的标签怎么定义
有两种情况anchor的标签是正:一种是与某个ground-truth box有最大的IoU的那些;另一种是与任何ground-truth的IoU都大于0.7的那些。
有一种情况anchor的标签是负:与所有的gound-truth box的IoU都小于0.3。
(3)其他训练细节
Mini-batch怎么采样:先随机采样一张图片,然后以1:1的比例从这张图随机采样256个anchors,如果正样本的数目少于128的话,只好用负样本填充mini-batch啦。也就是说1个mini-batch就是1张image和它的256个正负anchors。
新的卷积层用均值为0,标准差为0.01的高斯分布初始化,共享的那些层就用预训练的模型初始化啦。
前60k个mini-batch用学习率0.001,后20k个mini-batch用学习率0.0001。momentum是0.9,weight decay是0.0005.在PASCAL数据集喔~
3.怎么测试
测试就简单啦~对于一张测试image,先运行RPN生成2000个region proposal,然后把这些region proposal投影到conv feature map上进行后续的Fast R-CNN网络的操作就行啦。由于共享了conv feature map,一张图只用计算一次,大的缩短时间。
来一个三个网络的运行时间对比:
: 47s/img
Fast R-CNN:3s/img
Faster R-CNN:0.2s/img
--The End of Faster R-CNN--
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?faster rcnn 如何修改测试配置文件
[问题点数:40分]
faster rcnn 如何修改测试配置文件
[问题点数:40分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
匿名用户不能发表回复!|5061人阅读
Faster Rcnn(26)
最近开始学习,看了下Faster RCNN的代码,在学习的过程中也查阅了很多其他人写的博客,得到了很大的帮助,所以也打算把自己一些粗浅的理解记录下来,一是记录下自己的菜鸟学习之路,方便自己过后查阅,二来可以回馈网络。目前编程能力有限,且是第一次写博客,中间可能会有一些错误。
第一步,准备
从train_faster_rcnn_alt_opt.py入:
初始化参数:args = parse_args() 采用的是Python的argparse
主要有–net_name,–gpu,–cfg等(在cfg中只是修改了几个参数,其他大部分参数在congig.py中,涉及到训练整个网络)。cfg_from_file(args.cfg_file) 这里便是代用config中的函数cfg_from_file来读取前面cfg文件中的参数,同时调用_merge_a_into_b函数把所有的参数整合,其中__C = edict() cfg = __C cfg是一个词典(edict)数据结构。faster rcnn采用的是多进程,mp_queue是进程间用于通讯的数据结构import multiprocessing as mp
mp_queue = mp.Queue()1212同时solvers, max_iters, rpn_test_prototxt = get_solvers(args.net_name)得到solver参数
接下来便进入了训练的各个阶段。
第二步,Stage 1 RPN, init from ImageNet model
cfg.TRAIN.SNAPSHOT_INFIX = 'stage1'
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
init_model=args.pretrained_model,
solver=solvers[0],
max_iters=max_iters[0],
p = mp.Process(target=train_rpn, kwargs=mp_kwargs)
rpn_stage1_out = mp_queue.get()
p.join()123456789101112123456789101112可以看到第一个步骤是用ImageNet的模型M0来Finetuning RPN网络得到模型M1。以训练为例,这里的args参数都在脚本 experiments/scrips/faster_rcnn_alt_opt.sh中找到。主要关注train_rpn函数。
对于train_rpn函数,主要分一下几步:
1.在config参数的基础上改动参数,以适合当前任务,主要有
cfg.TRAIN.HAS_RPN = True
cfg.TRAIN.BBOX_REG = False
cfg.TRAIN.PROPOSAL_METHOD = 'gt'123123这里,关注proposal method 使用的是gt,后面会使用到gt_roidb函数,重要。
2. 初始化化caffe
3. 准备roidb和imdb
主要涉及到的函数get_roidb
在get_roidb函数中调用factory中的get_imdb根据__sets[name]中的key(一个lambda表达式)转到pascol_voc类。class pascal_voc(imdb)在初始化自己的时候,先调用父类的初始化方法,例如:
year:’2007’
image _set:’trainval’
devkit _path:’data/VOCdevkit2007’
data _path:’data /VOCdevkit2007/VOC2007’
classes:(…)_如果想要训练自己的数据,需要修改这里_
class _to _ind:{…} _一个将类名转换成下标的字典 _
建立索引0,1,2....
image _ext:’.jpg’
image _index: [‘000001’,’000003’,……]_根据trainval.txt获取到的image索引_
roidb _handler: &Method gt_roidb &
&Object uuid &
comp _id:’comp4’
config:{…}
}12345678910111213141234567891011121314注意,在这里,并没有读入任何数据,只是建立了图片的索引。
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)11设置proposal方法,接上面,设置为gt,这里只是设置了生成的方法,第一次调用发生在下一句,roidb = get_training_roidb(imdb) –& append_flipped_images()时的这行代码:“boxes = self.roidb[i][‘boxes’].copy()”,其中get_training_roidb位于train.py,主要实现图片的水平翻转,并添加回去。实际是该函数调用了imdb. append_flipped_images也就是在这个函数,调用了pascal_voc中的gt_roidb,转而调用了同一个文件中的_load_pascal_annotation,该函数根据图片的索引,到Annotations这个文件夹下去找相应的xml标注数据,然后加载所有的bounding
box对象,xml的解析到此结束,接下来是roidb中的几个类成员的赋值:
boxes 一个二维数组,每一行存储 xmin ymin xmax ymaxgt _classes存储了每个box所对应的类索引(类数组在初始化函数中声明)gt _overlap是一个二维数组,共有num _classes(即类的个数)行,每一行对应的box的类索引处值为1,其余皆为0,后来被转成了稀疏矩阵seg _areas存储着某个box的面积flipped 为false 代表该图片还未被翻转(后来在train.py里会将翻转的图片加进去,用该变量用于区分最后将这些成员变量组装成roidb返回。
在get_training_roidb函数中还调用了roidb中的prepare_roidb函数,这个函数就是用来准备imdb 的roidb,给roidb中的字典添加一些属性,比如image(图像的索引),width,height,通过前面的gt _overla属性,得到max_classes和max_overlaps.
return roidb,imdb114. 设置输出路径,output_dir = get_output_dir(imdb),函数在config中,用来保存中间生成的caffemodule等
5.正式开始训练
model_paths = train_net(solver, roidb, output_dir,
pretrained_model=init_model,
max_iters=max_iters)123123调用train中的train_net函数,其中,首先filter_roidb,判断roidb中的每个entry是否合理,合理定义为至少有一个前景box或背景box,roidb全是groudtruth时,因为box与对应的类的重合度(overlaps)显然为1,也就是说roidb起码要有一个标记类。如果roidb包含了一些proposal,overlaps在[BG_THRESH_LO, BG_THRESH_HI]之间的都将被认为是背景,大于FG_THRESH才被认为是前景,roidb 至少要有一个前景或背景,否则将被过滤掉。将没用的roidb过滤掉以后,返回的就是filtered_roidb。在train文件中,需要关注的是SolverWrapper类。详细见train.py,在这个类里面,引入了caffe
SGDSlover,最后一句self.solver.layers[0].set_roidb(roidb)将roidb设置进layer(0)(在这里就是ROILayer)调用ayer.py中的set_roidb方法,为layer(0)设置roidb,同时打乱顺序。最后train_model。在这里,就需要去实例化每个层,在这个阶段,首先就会实现ROIlayer,详细参考layer中的setup,在训练时roilayer的forward函数,在第一个层,只需要进行数据拷贝,在不同的阶段根据prototxt文件定义的网络结构拷贝数据,blobs
= self._get_next_minibatch()这个函数读取图片数据(调用get_minibatch函数,这个函数在minibatch中,主要作用是为faster rcnn做实际的数据准备,在读取数据的时候,分出了boxes,gt_boxes,im_info(宽高缩放)等)。
第一个层,对于stage1_rpn_train.pt文件中,该layer只有3个top blob:’data’、’im_info’、’gt_boxes’。
对于stage1_fast_rcnn_train.pt文件中,该layer有6个top blob:top: ‘data’、’rois’、’labels’、’bbox_targets’、’bbox_inside_weights’、’bbox_outside_weights’,这些数据准备都在minibatch中。至此后数据便在caffe中流动了,直到训练结束。 这里只截取了一部分:
值得注意的是在rpn-data层使用的是AnchorTargetLayer,该层使用实现的,往后再介绍。
6.保存最后得到的权重参数
rpn_stage1_out = mp_queue.get()11至此,第一阶段完成,在后面的任务开始时,如果有需要,会在这个输出的地址找这一阶段得到的权重文件。
第三步,Stage 1 RPN, generate proposals
这一步就是调用上一步训练得到的模型M1来生成proposal P1,在这一步只产生proposal,参数:
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
rpn_model_path=str(rpn_stage1_out['model_path']),
rpn_test_prototxt=rpn_test_prototxt)
p = mp.Process(target=rpn_generate, kwargs=mp_kwargs)
rpn_stage1_out['proposal_path'] = mp_queue.get()['proposal_path']
p.join()12345678910123456789101.关注rpn_generate函数
前面和上面讲到的train_rpn基本相同,从rpn_proposals = imdb_proposals(rpn_net, imdb)开始,imdb_proposals函数在rpn.generate.py文件中,rpn_proposals是一个列表的列表,每个子列表。对于imdb_proposals,使用im = cv2.imread(imdb.image_path_at(i))读入图片数据,调用 im_proposals生成单张图片的rpn proposals,以及得分。这里,im_proposals函数会调用网络的forward,从而得到想要的boxes和scores,这里需要好好理解blobs_out
= net.forward(data,im_info)中net forward和layer forward间的调用关系。
在这里,也会有proposal,同样会使用python实现的ProposalLayer,这个函数也在rpn文件夹内,后面再补充。
boxes = blobs_out['rois'][:, 1:].copy() / scale
scores = blobs_out['scores'].copy()
return boxes, scores123123至此,得到imdb proposal
2.保存得到的proposal文件
queue.put({'proposal_path': rpn_proposals_path})
rpn_stage1_out['proposal_path'] = mp_queue.get()['proposal_path']1212至此,Stage 1 RPN, generate proposals结束
第四步,Stage 1 Fast R-CNN using RPN proposals, init from ImageNet model
cfg.TRAIN.SNAPSHOT_INFIX = 'stage1'
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
init_model=args.pretrained_model,
solver=solvers[1],
max_iters=max_iters[1],
rpn_file=rpn_stage1_out['proposal_path'])
p = mp.Process(target=train_fast_rcnn, kwargs=mp_kwargs)
fast_rcnn_stage1_out = mp_queue.get()
p.join()1234567891011121312345678910111213这一步,用上一步生成的proposal,以及imagenet模型M0来训练fast-rcnn模型M2。
关注train_fast_rcnn
同样地,会设置参数,这里注意cfg.TRAIN.PROPOSAL_METHOD = ‘rpn’ 不同于前面,后面调用的将是rpn_roidb。cfg.TRAIN.IMS_PER_BATCH = 2,每个mini-batch包含两张图片,以及它们proposal的roi区域。且在这一步是有rpn_file的(后面和rpn_roidb函数使用有关)。其他的和前面差不多。提一下,这里在train_net的时候,会调用add_bbox_regression_targets位于roidb中,主要是添加bbox回归目标,即添加roidb的‘bbox_targets’属性,同时根据cfg中的参数设定,求取bbox_targets的mean和std,因为需要训练class-specific
regressors在这里就会涉及到bbox_overlaps函数,放在util.bbox中。
要注意的是在这一步get_roidb时,如前所说,使用的是rpn_roidb,会调用imdb. create_roidb_from_box_list该方法功能是从box_list中读取每张图的boxes,而这个box_list就是从上一步保存的proposal文件中读取出来的,然后做一定的处理,详细见代码,重点是在最后会返回roidb,rpn_roidb中的gt_overlaps是rpn_file中的box与gt_roidb中box的gt_overlaps等计算IoU等处理后得到的,而不像gt_roidb()方法生成的gt_roidb中的gt_overlaps全部为1.0。同时使用了imdb.merge_roidb,类imdb的静态方法【这里不太懂,需要再学习下】,把rpn_roidb和gt_roidb归并为一个roidb,在这里,需要具体去了解合并的基本原理。
第五步,Stage 2 RPN, init from stage 1 Fast R-CNN model
cfg.TRAIN.SNAPSHOT_INFIX = 'stage2'
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
init_model=str(fast_rcnn_stage1_out['model_path']),
solver=solvers[2],
max_iters=max_iters[2],
p = mp.Process(target=train_rpn, kwargs=mp_kwargs)
rpn_stage2_out = mp_queue.get()1234567891012345678910这部分就是利用模型M2练rpn网络,这一次与stage1的rpn网络不通,这一次conv层的参数都是不动的,只做前向计算,训练得到模型M3,这属于微调了rpn网络。
第六步,Stage 2 RPN, generate proposals
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
rpn_model_path=str(rpn_stage2_out['model_path']),
rpn_test_prototxt=rpn_test_prototxt)
p = mp.Process(target=rpn_generate, kwargs=mp_kwargs)
rpn_stage2_out['proposal_path'] = mp_queue.get()['proposal_path']
p.join()1234567891012345678910这一步,基于上一步得到的M3模型,产生proposal P2,网络结构和前面产生proposal P1的一样。
第七步,Stage 2 Fast R-CNN, init from stage 2 RPN R-CNN model
cfg.TRAIN.SNAPSHOT_INFIX = 'stage2'
mp_kwargs = dict(
queue=mp_queue,
imdb_name=args.imdb_name,
init_model=str(rpn_stage2_out['model_path']),
solver=solvers[3],
max_iters=max_iters[3],
rpn_file=rpn_stage2_out['proposal_path'])
p = mp.Process(target=train_fast_rcnn, kwargs=mp_kwargs)
fast_rcnn_stage2_out = mp_queue.get()
p.join()1234567891011121312345678910111213这一步基于模型M3和P2训练fast rcnn得到最终模型M4,这一步,conv层和rpn都是参数固定,只是训练了rcnn层(也就是全连接层),与stage1不同,stage1只是固定了rpn层,其他层还是有训练。模型结构与stage1相同:
第八步,输出最后模型
final_path = os.path.join(
os.path.dirname(fast_rcnn_stage2_out['model_path']),
args.net_name + '_faster_rcnn_final.caffemodel')
print 'cp {} -& {}'.format(
fast_rcnn_stage2_out['model_path'], final_path)
shutil.copy(fast_rcnn_stage2_out['model_path'], final_path)
print 'Final model: {}'.format(final_path)12345671234567只是对上一步模型输出的一个拷贝。
至此,整个faster-rcnn的训练过程就结束了。
AnchorTargetLayer和ProposalLayer
前面说过还有这两个层没有说明,一个是anchortarget layer一个是proposal layer,下面逐一简要分析。
class AnchorTargetLayer(caffe.Layer)11首先是读取参数,在prototxt,实际上只读取了param_str: “‘feat_stride’: 16”,这是个很重要的参数,目前我的理解是滑块滑动的大小,对于识别物体的大小很有用,比如小物体的识别,需要把这个参数减小等。
首先 setup部分,
anchor_scales = layer_params.get('scales', (8, 16, 32))
self._anchors = generate_anchors(scales=np.array(anchor_scales))1212调用generate_anchors方法生成最初始的9个anchor该函数位于generate_anchors.py 主要功能是生成多尺度,多宽高比的anchors,8,16,32其实就是scales:[2^3 2^4 2^5],base_size为16,具体是怎么实现的可以查阅源代码。_ratio_enum()部分生成三种宽高比 1:2,1:1,2:1的anchor如下图所示:(以下参考)
_scale_enum()部分,生成三种尺寸的anchor,以_ratio_enum()部分生成的anchor[0 0 15 15]为例,扩展了三种尺度 128*128,256*256,512*512,如下图所示:
另外一个函数就是forward()。
在faster rcnn中会根据不同图的输入,得到不同的feature map,height, width = bottom[0].data.shape[-2:]首先得到conv5的高宽,以及gt box gt_boxes = bottom[1].data,图片信息im_info = bottom[2].data[0, :],然后计算偏移量,shift_x = np.arange(0, width) * self._feat_stride,在这里,你会发现,例如你得到的fm是H=61,W=36,然后你乘以16,得到的图形大概就是,其实这个16大概就是网络的缩放比例。接下来就是生成anchor,以及对anchor做一定的筛选,详见代码。
另外一个需要理解的就是proposal layer,这个只是在的时候用,许多东西和AnchorTargetLayer类似,不详细介绍,可以查看代码。主要看看forward函数,函数介绍在注释部分写的很详细:
12345678910111234567891011在这个函数中会引用NMS方法。
代码文件夹说明
转载出处:
在tools文件夹中,是我们直接调用的最外层的封装文件。其中主要包含的文件为:
_init_paths.py :用来初始化路径的,也就是之后的路径会join(path,*)compress_net.py:用来压缩参数的,使用了SVD来进行压缩,这里可以发现,作者对于fc6层和fc7层进行了压缩,也就是两个全连接层。demo.py :通常,我们会直接调用这个函数,如果要测试自己的模型和数据,这里需要修改。这里调用了fast_rcnn中的test、config、nums_wrapper函数。vis_detections用来做检测,parse_args用来进行参数设置,以及damo和主函数。eval_recall.py:评估函数reval.py:re-evaluate,这里调用了fast_rcnn以及dataset中的函数。其中,from_mats函数和from_dets函数分别loadmat文件和pkl文件。rpn_genetate.py:这个函数调用了rpn中的genetate函数,之后我们会对rpn层做具体的介绍。这里,主要是一个封装调用的过程,我们在这里调用配置的参数、设置rpn的test参数,以及输入输出等操作。test_net.py:测试fast rcnn网络。主要就是一些参数配置。train_faster_rcnn_alt_opt.py:训练faster rcnn网络使用交替的训练,这里就是根据faster rcnn文章中的具体实现。可以在主函数中看到,其包括的步骤为:RPN 1,使用imagenet model进行初始化参数,生成proposal,这里存储在mp_kwargsfast rcnn 1,使用 imagenet model 进行初始化参数,使用刚刚生成的proposal进行fast rcnn的训练RPN 2使用 fast rcnn 中的参数进行初始化(这里要注意哦),并生成proposalfast rcnn 2,使用RPN 2 中的 model进行初始化参数值得注意的是:在我们训练时,我们可以在get_solvers中的max_iters中设置迭代次数,在不确定网络是否可以调通时,减少迭代次数可以减少测试时间。我们在训练faster rcnn网络时,就是调用这个文件训练的train_net.py:使用fast rcnn,训练自己数据集的网络模型train_svms.py:使用最原始的RCNN网络训练post-hoc SVMsRPN
这里我们主要看lib/rpn文件夹下的代码。这里主要介绍了rpn的模型,其中,包含的主要文件如下:
generate_anchors.py: 生成多尺度和多比例的锚点。这里由generate_anthors函数主要完成,可以看到,使用了 3 个尺度( 128, 256, and 512)以及 3 个比例(1:1,1:2,2:1)。一个锚点由w, h, x_ctr, y_ctr固定,也就是宽、高、x center和y center固定。proposal_layer.py:这个函数是用来将RPN的输出转变为object proposals的。作者新增了ProposalLayer类,这个类中,重新了set_up和forward函数,其中forward实现了:生成锚点box、对于每个锚点提供box的参数细节、将预测框切成图像、删除宽、高小于阈值的框、将所有的(proposal, score) 对排序、获取 pre_nms_topN proposals、获取NMS 、获取 after_nms_topN proposals。(注:NMS,nonmaximum
suppression,非极大值抑制)anchor_target_layer.py:生成每个锚点的训练目标和标签,将其分类为1 (object), 0 (not object) , -1 (ignore).当label&0,也就是有object时,将会进行box的回归。其中,forward函数功能:在每一个cell中,生成9个锚点,提供这9个锚点的细节信息,过滤掉超过图像的锚点,测量同GT的overlap。proposal_target_layer.py:对于每一个object proposal 生成训练的目标和标签,分类标签从0-k,对于标签&0的box进行回归。(注意,同anchor_target_layer.py不同,两者一个是生成anchor,一个是生成proposal)generate.py:使用一个rpn生成object proposals。作者就是通过以上这些文件生成rpn的。
lib/nms文件夹下是非极大值抑制,这部分大家应该已经非常熟悉了,其Python版本的核心函数为py_cpu_nms.py,具体实现以及注释如下:
def py_cpu_nms(dets, thresh):
"""Pure Python NMS baseline."""
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
order = scores.argsort()[::-1]
while order.size & 0:
i = order[0]
keep.append(i)
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
ovr = inter / (areas[i] + areas[order[1:]] - inter)
inds = np.where(ovr &= thresh)[0]
order = order[inds + 1]12345678910111213141516171819202122232425262728293031321234567891011121314151617181920212223242526272829303132参考
在这里,没有贴出代码的注释,只是梳理了下Faster RCNN训练的流程,因为代码的注释网络上已经有很多,需要看代码的注释可以参考下面几个博客,我看代码的时候也有参考:
原文地址:
继fasterrcnn后,又一个pva-fasterrcnn的配置教程,希望可以帮助大家。若不能配置成功,请与我联系,邮箱:
注意:有些复制的终端命令如果不能在终端运行,请注意英文全角半角问题,可以将命令输入终端,无须复制粘贴命令
第一部分:下载并编译pvanet1、终端输入:git clone --recursive https://github.com/sanghoon/pva-faster-rcnn.git2、建立Cython模块:这个地方很容易错,缺什么下载什么就能解决啦,出现问题的小伙伴可以来群里讨论哈,很多问题我当时没有记录,所以来群里讨论讨论就行啦,群号你懂得cd $pva-faster-rcnn/libmake –j16(为啥用16相信大家也很清楚啦)3、编译caffe及pycaffecd $pva-faster-rcnn/caffe-fast-rcnncp Makefile.config.example Makefile.config修改Makefile.config文件:去掉cudnn前面#(我用cudnn4.0,仅供参考)Opencv_version不用注释(我用的2.4.10,3.0没有测试过,所以不用注释)BLAS=atlas(我测试的库,mkl没有试过)(sudo apt-get install libatlas-base-dev即可安装)去掉with_python_layer前面的#,注意一定要去掉,不然无法训练数据(测试的时候不需要)
修改后保存退出
make –j16
make pycaffe –j16
第二部分:下载预训练模型(外网真心慢啊)为小伙伴们提供百度网盘下载链接:链接:http://pan.baidu.com/s/1kVRRPDd 密码:1cdt1、打开文件将test.model放入$pva-faster-rcnn/models/pvanet/full/这个目录下2、将test(1).model重命名为test.model放入$pva-faster-rcnn/models/pvanet/comp/目录下其他的模型我就没有去试验啦,后续有时间就会更新这些模型的训练方法的
第三部分:下载voc07数据打开终端(任何目录)输入:wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar解压(严格按照此顺序):tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar将生成的VOCdevkit文件夹更名为VOCdevkit2007移动至$pva-faster-rcnn/data/目录下面
第四部分:voc07测试预训练模型终端输入:cd $pva-faster-rcnn1、full/test.model测试:./tools/test_net.py --gpu 0 --def models/pvanet/full/test.pt --net models/pvanet/full/test.model --cfg models/pvanet/cfgs/submit_160715.yml2、Comp/test.model测试:./tools/test_net.py --gpu 0 --def models/pvanet/comp/test.pt --net models/pvanet/comp/test.model --cfg models/pvanet/cfgs/submit_160715.yml此测试会得到系列类别的AP值
第五部分:预训练model训练并测试voc07数据终端输入:1、训练:cd $pva-faster-rcnn./tools/train_net.py --gpu 0 --solver models/pvanet/example_finetune/solver.prototxt --weights models/pvanet/full/test.model –iters 100000 --cfg models/pvanet/cfgs/train.yml –imdb voc_2007_trainval(其他参数默认)训练结果会在pva根目录生成output文件夹,模型就在里面2、测试:./tools/test_net.py --gpu 0 --def models/pvanet/example_finetune/test.prototxt --net output/faster_rcnn_pavnet/voc_2007_trainval/pvanet_frcnn_iter_100000.caffemodel --cfg models/pvanet/cfgs/submit_160715.yml
(其他参数默认)
第六部分:预训练model训练并测试自己数据1、数据制作:还记得fasterrcnn数据如何制作的吗?参考博客http://blog.csdn.net/samylee/article/details/Tips:参考voc07的数据格式,我们可发现,生成的数据最后只需保留Annotations、ImageSets和JPEGImages三个文件夹即可,ImageSets/Main文件中用到的只有trainval.txt和test.txt这两个文件(数据分布:trainval=train+val,all_data=trainval+test),多类别如果增加负样本或模糊样本可以考虑1、0及-1操作(其中1表示有目标,0表示模糊目标,-1表示没有目标)数据集制作完成后将这三个文件夹复制至一个文件夹(命名为VOC2007)当中,再移动至$pva-faster-rcnn/data/VOCdevkit2007中,替换原来的VOC2007
2、类别设置:(有几类设置几类,类似fasterrcnn,我的数据集为1类行人数据)
1)打开文件/models/pvanet/example_finetune/train.prototxt
num_classes:2(开头处)(我实验时一类)
2)修改lib/datasets/pascal_voc.py
self._classes = ('__background__', # always index 0
'people')(只有这一类)
3)修改lib/datasets/imdb.py
数据整理,在一行代码为 boxes[:, 2] = widths[i] - oldx1 - 1下加入代码: for b in range(len(boxes)):
if boxes[b][2]& boxes[b][0]:
boxes[b][0] = 0
4)修改完pascal_voc.py和imdb.py后进入lib/datasets目录下删除原来的pascal_voc.pyc和imdb.pyc文件,重新生成这两个文件,因为这两个文件是python编译后的文件,系统会直接调用。
终端进入lib/datasets文件目录输入:
python(此处应出现python的版本)
&&&import py_compile
&&&py_compile.compile(r'imdb.py')
&&&py_compile.compile(r'pascal_voc.py')
3、训练数据:cd $pva-faster-rcnn
./tools/train_net.py --gpu 0 --solver models/pvanet/example_finetune/solver.prototxt --weights models/pvanet/full/test.model –iters 100000 --cfg models/pvanet/cfgs/train.yml –imdb voc_2007_trainval(其他参数默认)4、测试模型:./tools/test_net.py --gpu 0 --def models/pvanet/example_finetune/test.prototxt --net output/faster_rcnn_pavnet/voc_2007_trainval/pvanet_frcnn_iter_100000.caffemodel --cfg models/pvanet/cfgs/submit_160715.yml
(其他参数默认)
第七部分:实验结果目前我训练了<span style="color:#左右,loss为<span style="color:#左右,其他四个参数分别在<span style="color:#、0.1、0.01、0.01左右后续工作可做demo演示程序,小伙伴们尽请期待!}

我要回帖

更多关于 驴要怎么训练才能骑 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信