Faster RCNN代码理解(Python) ---训练过程
最近開始學習深度學習,看了下Faster RCNN的代碼,在學習的過程中也查閱了很多其他人寫的博客,得到了很大的幫助,所以也打算把自己一些粗淺的理解記錄下來,一是記錄下自己的菜鳥學習之路,方便自己過后查閱,二來可以回饋網(wǎng)絡。目前編程能力有限,且是第一次寫博客,中間可能會有一些錯誤。
目錄
- 目錄
-
- 第一步準備
- 第二步Stage 1 RPN init from ImageNet model
- 在config參數(shù)的基礎上改動參數(shù)以適合當前任務主要有
- 初始化化caffe
- 準備roidb和imdb
- 設置輸出路徑output_dir get_output_dirimdb函數(shù)在config中用來保存中間生成的caffemodule等
- 正式開始訓練
- 保存最后得到的權重參數(shù)
- 第三步Stage 1 RPN generate proposals
- 關注rpn_generate函數(shù)
- 保存得到的proposal文件
- 第四步Stage 1 Fast R-CNN using RPN proposals init from ImageNet model
- 第五步Stage 2 RPN init from stage 1 Fast R-CNN model
- 第六步Stage 2 RPN generate proposals
- 第七步Stage 2 Fast R-CNN init from stage 2 RPN R-CNN model
- 第八步輸出最后模型
- AnchorTargetLayer和ProposalLayer
- 代碼文件夾說明
- tools
- RPN
- nms
- 參考
- 原文地址
-
第一步,準備
從train_faster_rcnn_alt_opt.py入:
主要有–net_name,–gpu,–cfg等(在cfg中只是修改了幾個參數(shù),其他大部分參數(shù)在congig.py中,涉及到訓練整個網(wǎng)絡)。
- 1
- 2
- 1
- 2
同時solvers, max_iters, rpn_test_prototxt = get_solvers(args.net_name)得到solver參數(shù)
接下來便進入了訓練的各個階段。
第二步,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],cfg=cfg) p = mp.Process(target=train_rpn, kwargs=mp_kwargs) p.start() rpn_stage1_out = mp_queue.get() p.join()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
可以看到第一個步驟是用ImageNet的模型M0來Finetuning RPN網(wǎng)絡得到模型M1。以訓練為例,這里的args參數(shù)都在腳本 experiments/scrips/faster_rcnn_alt_opt.sh中找到。主要關注train_rpn函數(shù)。
對于train_rpn函數(shù),主要分一下幾步:
1.在config參數(shù)的基礎上改動參數(shù),以適合當前任務,主要有
cfg.TRAIN.HAS_RPN = True cfg.TRAIN.BBOX_REG = False # applies only to Fast R-CNN bbox regression cfg.TRAIN.PROPOSAL_METHOD = 'gt'- 1
- 2
- 3
- 1
- 2
- 3
這里,關注proposal method 使用的是gt,后面會使用到gt_roidb函數(shù),重要。
2. 初始化化caffe
3. 準備roidb和imdb
主要涉及到的函數(shù)get_roidb?
在get_roidb函數(shù)中調用factory中的get_imdb根據(jù)__sets[name]中的key(一個lambda表達式)轉到pascol_voc類。class pascal_voc(imdb)在初始化自己的時候,先調用父類的初始化方法,例如:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
注意,在這里,并沒有讀入任何數(shù)據(jù),只是建立了圖片的索引。
imdb.set_proposal_method(cfg.TRAIN.PROPOSAL_METHOD)- 1
- 1
設置proposal方法,接上面,設置為gt,這里只是設置了生成的方法,第一次調用發(fā)生在下一句,roidb = get_training_roidb(imdb) –> append_flipped_images()時的這行代碼:“boxes = self.roidb[i][‘boxes’].copy()”,其中get_training_roidb位于train.py,主要實現(xiàn)圖片的水平翻轉,并添加回去。實際是該函數(shù)調用了imdb. append_flipped_images也就是在這個函數(shù),調用了pascal_voc中的gt_roidb,轉而調用了同一個文件中的_load_pascal_annotation,該函數(shù)根據(jù)圖片的索引,到Annotations這個文件夾下去找相應的xml標注數(shù)據(jù),然后加載所有的bounding box對象,xml的解析到此結束,接下來是roidb中的幾個類成員的賦值:
- boxes 一個二維數(shù)組,每一行存儲 xmin ymin xmax ymax
- gt _classes存儲了每個box所對應的類索引(類數(shù)組在初始化函數(shù)中聲明)
- gt _overlap是一個二維數(shù)組,共有num _classes(即類的個數(shù))行,每一行對應的box的類索引處值為1,其余皆為0,后來被轉成了稀疏矩陣
- seg _areas存儲著某個box的面積
- flipped 為false 代表該圖片還未被翻轉(后來在train.py里會將翻轉的圖片加進去,用該變量用于區(qū)分
最后將這些成員變量組裝成roidb返回。?
在get_training_roidb函數(shù)中還調用了roidb中的prepare_roidb函數(shù),這個函數(shù)就是用來準備imdb 的roidb,給roidb中的字典添加一些屬性,比如image(圖像的索引),width,height,通過前面的gt _overla屬性,得到max_classes和max_overlaps.
至此,
- 1
- 1
4. 設置輸出路徑,output_dir = get_output_dir(imdb),函數(shù)在config中,用來保存中間生成的caffemodule等
5.正式開始訓練
model_paths = train_net(solver, roidb, output_dir,pretrained_model=init_model,max_iters=max_iters)- 1
- 2
- 3
- 1
- 2
- 3
調用train中的train_net函數(shù),其中,首先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.NET.layers[0].set_roidb(roidb)將roidb設置進layer(0)(在這里就是ROILayer)調用ayer.py中的set_roidb方法,為layer(0)設置roidb,同時打亂順序。最后train_model。在這里,就需要去實例化每個層,在這個階段,首先就會實現(xiàn)ROIlayer,詳細參考layer中的setup,在訓練時roilayer的forward函數(shù),在第一個層,只需要進行數(shù)據(jù)拷貝,在不同的階段根據(jù)prototxt文件定義的網(wǎng)絡結構拷貝數(shù)據(jù),blobs = self._get_next_minibatch()這個函數(shù)讀取圖片數(shù)據(jù)(調用get_minibatch函數(shù),這個函數(shù)在minibatch中,主要作用是為faster rcnn做實際的數(shù)據(jù)準備,在讀取數(shù)據(jù)的時候,分出了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’,這些數(shù)據(jù)準備都在minibatch中。至此后數(shù)據(jù)便在caffe中流動了,直到訓練結束。
畫出網(wǎng)絡的結構?這里只截取了一部分:
?
值得注意的是在rpn-data層使用的是AnchorTargetLayer,該層使用Python實現(xiàn)的,往后再介紹。
6.保存最后得到的權重參數(shù)
rpn_stage1_out = mp_queue.get()- 1
- 1
至此,第一階段完成,在后面的任務開始時,如果有需要,會在這個輸出的地址找這一階段得到的權重文件。
第三步,Stage 1 RPN, generate proposals
這一步就是調用上一步訓練得到的模型M1來生成proposal P1,在這一步只產生proposal,參數(shù):
mp_kwargs = dict(queue=mp_queue,imdb_name=args.imdb_name,rpn_model_path=str(rpn_stage1_out['model_path']),cfg=cfg,rpn_test_prototxt=rpn_test_prototxt) p = mp.Process(target=rpn_generate, kwargs=mp_kwargs) p.start() rpn_stage1_out['proposal_path'] = mp_queue.get()['proposal_path'] p.join()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
1.關注rpn_generate函數(shù)
前面和上面講到的train_rpn基本相同,從rpn_proposals = imdb_proposals(rpn_net, imdb)開始,imdb_proposals函數(shù)在rpn.generate.py文件中,rpn_proposals是一個列表的列表,每個子列表。對于imdb_proposals,使用im = cv2.imread(imdb.image_path_at(i))讀入圖片數(shù)據(jù),調用 im_proposals生成單張圖片的rpn proposals,以及得分。這里,im_proposals函數(shù)會調用網(wǎng)絡的forward,從而得到想要的boxes和scores,這里需要好好理解blobs_out = net.forward(data,im_info)中net forward和layer forward間的調用關系。?
?
在這里,也會有proposal,同樣會使用Python實現(xiàn)的ProposalLayer,這個函數(shù)也在rpn文件夾內,后面再補充。
- 1
- 2
- 3
- 1
- 2
- 3
至此,得到imdb proposal
2.保存得到的proposal文件
queue.put({'proposal_path': rpn_proposals_path}) rpn_stage1_out['proposal_path'] = mp_queue.get()['proposal_path']- 1
- 2
- 1
- 2
至此,Stage 1 RPN, generate proposals結束
第四步,Stage 1 Fast R-CNN using RPN proposals, init from ImageNet model
參數(shù):
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],cfg=cfg,rpn_file=rpn_stage1_out['proposal_path']) p = mp.Process(target=train_fast_rcnn, kwargs=mp_kwargs) p.start() fast_rcnn_stage1_out = mp_queue.get() p.join()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
這一步,用上一步生成的proposal,以及imagenet模型M0來訓練fast-rcnn模型M2。?
關注train_fast_rcnn?
同樣地,會設置參數(shù),這里注意cfg.TRAIN.PROPOSAL_METHOD = ‘rpn’ 不同于前面,后面調用的將是rpn_roidb。cfg.TRAIN.IMS_PER_BATCH = 2,每個mini-batch包含兩張圖片,以及它們proposal的roi區(qū)域。且在這一步是有rpn_file的(后面和rpn_roidb函數(shù)使用有關)。其他的和前面差不多。提一下,這里在train_net的時候,會調用add_bbox_regression_targets位于roidb中,主要是添加bbox回歸目標,即添加roidb的‘bbox_targets’屬性,同時根據(jù)cfg中的參數(shù)設定,求取bbox_targets的mean和std,因為需要訓練class-specific regressors在這里就會涉及到bbox_overlaps函數(shù),放在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的靜態(tài)方法【這里不太懂,需要再學習下】,把rpn_roidb和gt_roidb歸并為一個roidb,在這里,需要具體去了解合并的基本原理。
第五步,Stage 2 RPN, init from stage 1 Fast R-CNN model
參數(shù):
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],cfg=cfg) p = mp.Process(target=train_rpn, kwargs=mp_kwargs) rpn_stage2_out = mp_queue.get()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
這部分就是利用模型M2練rpn網(wǎng)絡,這一次與stage1的rpn網(wǎng)絡不通,這一次conv層的參數(shù)都是不動的,只做前向計算,訓練得到模型M3,這屬于微調了rpn網(wǎng)絡。
第六步,Stage 2 RPN, generate proposals
參數(shù):
mp_kwargs = dict(queue=mp_queue,imdb_name=args.imdb_name,rpn_model_path=str(rpn_stage2_out['model_path']),cfg=cfg,rpn_test_prototxt=rpn_test_prototxt) p = mp.Process(target=rpn_generate, kwargs=mp_kwargs) p.start() rpn_stage2_out['proposal_path'] = mp_queue.get()['proposal_path'] p.join()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
這一步,基于上一步得到的M3模型,產生proposal P2,網(wǎng)絡結構和前面產生proposal P1的一樣。?
第七步,Stage 2 Fast R-CNN, init from stage 2 RPN R-CNN model
參數(shù):
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],cfg=cfg,rpn_file=rpn_stage2_out['proposal_path']) p = mp.Process(target=train_fast_rcnn, kwargs=mp_kwargs) p.start() fast_rcnn_stage2_out = mp_queue.get() p.join()- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
這一步基于模型M3和P2訓練fast rcnn得到最終模型M4,這一步,conv層和rpn都是參數(shù)固定,只是訓練了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)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
只是對上一步模型輸出的一個拷貝。?
至此,整個faster-rcnn的訓練過程就結束了。
AnchorTargetLayer和ProposalLayer
前面說過還有這兩個層沒有說明,一個是anchortarget layer一個是proposal layer,下面逐一簡要分析。
class AnchorTargetLayer(caffe.Layer)- 1
- 1
首先是讀取參數(shù),在prototxt,實際上只讀取了param_str: “‘feat_stride’: 16”,這是個很重要的參數(shù),目前我的理解是滑塊滑動的大小,對于識別物體的大小很有用,比如小物體的識別,需要把這個參數(shù)減小等。
首先 setup部分,
- 1
- 2
- 1
- 2
調用generate_anchors方法生成最初始的9個anchor該函數(shù)位于generate_anchors.py 主要功能是生成多尺度,多寬高比的anchors,8,16,32其實就是scales:[2^3 2^4 2^5],base_size為16,具體是怎么實現(xiàn)的可以查閱源代碼。_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,如下圖所示:
?
另外一個函數(shù)就是forward()。?
在faster rcnn中會根據(jù)不同圖的輸入,得到不同的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,在這里,你會發(fā)現(xiàn),例如你得到的fm是H=61,W=36,然后你乘以16,得到的圖形大概就是1000*600,其實這個16大概就是網(wǎng)絡的縮放比例。接下來就是生成anchor,以及對anchor做一定的篩選,詳見代碼。
另外一個需要理解的就是proposal layer,這個只是在測試的時候用,許多東西和AnchorTargetLayer類似,不詳細介紹,可以查看代碼。主要看看forward函數(shù),函數(shù)算法介紹在注釋部分寫的很詳細:
# Algorithm: # for each (H, W) location i # generate A anchor boxes centered on cell i # apply predicted bbox deltas at cell i to each of the A anchors # clip predicted boxes to image # remove predicted boxes with either height or width < threshold # sort all (proposal, score) pairs by score from highest to lowest # take top pre_nms_topN proposals before NMS # apply NMS with threshold 0.7 to remaining proposals # take after_nms_topN proposals after NMS # return the top proposals (-> RoIs top, scores top)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
在這個函數(shù)中會引用NMS方法。
代碼文件夾說明
轉載出處:另外一篇博客
tools
在tools文件夾中,是我們直接調用的最外層的封裝文件。其中主要包含的文件為:
- _init_paths.py?:用來初始化路徑的,也就是之后的路徑會join(path,*)
- compress_net.py:用來壓縮參數(shù)的,使用了SVD來進行壓縮,這里可以發(fā)現(xiàn),作者對于fc6層和fc7層進行了壓縮,也就是兩個全連接層。
- demo.py?:通常,我們會直接調用這個函數(shù),如果要測試自己的模型和數(shù)據(jù),這里需要修改。這里調用了fast_rcnn中的test、config、nums_wrapper函數(shù)。vis_detections用來做檢測,parse_args用來進行參數(shù)設置,以及damo和主函數(shù)。
- eval_recall.py:評估函數(shù)
- reval.py:re-evaluate,這里調用了fast_rcnn以及dataset中的函數(shù)。其中,from_mats函數(shù)和from_dets函數(shù)分別loadmat文件和pkl文件。
- rpn_genetate.py:這個函數(shù)調用了rpn中的genetate函數(shù),之后我們會對rpn層做具體的介紹。這里,主要是一個封裝調用的過程,我們在這里調用配置的參數(shù)、設置rpn的test參數(shù),以及輸入輸出等操作。
- test_net.py:測試fast rcnn網(wǎng)絡。主要就是一些參數(shù)配置。
- train_faster_rcnn_alt_opt.py:訓練faster rcnn網(wǎng)絡使用交替的訓練,這里就是根據(jù)faster rcnn文章中的具體實現(xiàn)。可以在主函數(shù)中看到,其包括的步驟為:
- RPN 1,使用imagenet model進行初始化參數(shù),生成proposal,這里存儲在mp_kwargs
- fast rcnn 1,使用 imagenet model 進行初始化參數(shù),使用剛剛生成的proposal進行fast rcnn的訓練
- RPN 2使用 fast rcnn 中的參數(shù)進行初始化(這里要注意哦),并生成proposal
- fast rcnn 2,使用RPN 2 中的 model進行初始化參數(shù)
- 值得注意的是:在我們訓練時,我們可以在get_solvers中的max_iters中設置迭代次數(shù),在不確定網(wǎng)絡是否可以調通時,減少迭代次數(shù)可以減少測試時間。
- 我們在訓練faster rcnn網(wǎng)絡時,就是調用這個文件訓練的
- train_net.py:使用fast rcnn,訓練自己數(shù)據(jù)集的網(wǎng)絡模型
- train_svms.py:使用最原始的RCNN網(wǎng)絡訓練post-hoc SVMs
RPN
這里我們主要看lib/rpn文件夾下的代碼。這里主要介紹了rpn的模型,其中,包含的主要文件如下:
- generate_anchors.py: 生成多尺度和多比例的錨點。這里由generate_anthors函數(shù)主要完成,可以看到,使用了 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:這個函數(shù)是用來將RPN的輸出轉變?yōu)閛bject proposals的。作者新增了ProposalLayer類,這個類中,重新了set_up和forward函數(shù),其中forward實現(xiàn)了:生成錨點box、對于每個錨點提供box的參數(shù)細節(jié)、將預測框切成圖像、刪除寬、高小于閾值的框、將所有的(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函數(shù)功能:在每一個cell中,生成9個錨點,提供這9個錨點的細節(jié)信息,過濾掉超過圖像的錨點,測量同GT的overlap。
- proposal_target_layer.py:對于每一個object proposal 生成訓練的目標和標簽,分類標簽從0-k,對于標簽>0的box進行回歸。(注意,同anchor_target_layer.py不同,兩者一個是生成anchor,一個是生成proposal)
- generate.py:使用一個rpn生成object proposals。
作者就是通過以上這些文件生成rpn的。
nms
lib/nms文件夾下是非極大值抑制,這部分大家應該已經非常熟悉了,其python版本的核心函數(shù)為py_cpu_nms.py,具體實現(xiàn)以及注釋如下:
def py_cpu_nms(dets, thresh):"""Pure Python NMS baseline."""#x1、y1、x2、y2、以及score賦值x1 = dets[:, 0]y1 = dets[:, 1]x2 = dets[:, 2]y2 = dets[:, 3]scores = dets[:, 4]#每一個op的面積areas = (x2 - x1 + 1) * (y2 - y1 + 1)#order是按照score排序的order = scores.argsort()[::-1]keep = []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#計算:重疊面積/(面積1+面積2-重疊面積)ovr = inter / (areas[i] + areas[order[1:]] - inter)inds = np.where(ovr <= thresh)[0]order = order[inds + 1]- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
參考
在這里,沒有貼出代碼的注釋,只是梳理了下Faster RCNN訓練的流程,因為代碼的注釋網(wǎng)絡上已經有很多,需要看代碼的注釋可以參考下面幾個博客,我看代碼的時候也有參考:
[1]?http://www.cnblogs.com/CarryPotMan/p/5390336.html
[2]?http://blog.csdn.net/u010668907/article/category/6237110?
[3]?http://blog.csdn.net/sunyiyou9/article/category/6269359?
[4]?http://blog.csdn.net/bailufeiyan/article/details/50749694
原文地址:
http://blog.csdn.net/u011956147/article/details/53053381
繼fasterrcnn后,又一個pva-fasterrcnn的配置教程,希望可以幫助大家。若不能配置成功,請與我聯(lián)系,郵箱:ahuljx@126.com
注意:有些復制的終端命令如果不能在終端運行,請注意英文全角半角問題,可以將命令輸入終端,無須復制粘貼命令
第一部分:下載并編譯pvanet
1、終端輸入:
Git?clone --recursive https://github.com/sanghoon/pva-faster-rcnn.git
2、建立Cython模塊:
這個地方很容易錯,缺什么下載什么就能解決啦,出現(xiàn)問題的小伙伴可以來群里討論哈,很多問題我當時沒有記錄,所以來群里討論討論就行啦,群號你懂得
cd $pva-faster-rcnn/lib
make –j16(為啥用16相信大家也很清楚啦)
3、編譯caffe及pycaffe
cd $pva-faster-rcnn/caffe-fast-rcnn
cp 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前面的#,注意一定要去掉,不然無法訓練數(shù)據(jù)(測試的時候不需要)
修改后保存退出
make –j16
make pycaffe –j16
第二部分:下載預訓練模型(外網(wǎng)真心慢啊)
為小伙伴們提供百度網(wǎng)盤下載鏈接:
鏈接:http://pan.baidu.com/s/1kVRRPDd 密碼:1cdt
1、打開文件將test.model放入$pva-faster-rcnn/models/pvanet/full/這個目錄下
2、將test(1).model重命名為test.model放入$pva-faster-rcnn/models/pvanet/comp/目錄下
其他的模型我就沒有去試驗啦,后續(xù)有時間就會更新這些模型的訓練方法的
第三部分:下載voc07數(shù)據(jù)
打開終端(任何目錄)輸入:
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-rcnn
1、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.yml
2、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數(shù)據(jù)
終端輸入:
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(其他參數(shù)默認)
訓練結果會在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?(其他參數(shù)默認)
第六部分:預訓練model訓練并測試自己數(shù)據(jù)
1、數(shù)據(jù)制作:
還記得fasterrcnn數(shù)據(jù)如何制作的嗎?參考博客http://blog.csdn.NET/samylee/article/details/51201744
Tips:參考voc07的數(shù)據(jù)格式,我們可發(fā)現(xiàn),生成的數(shù)據(jù)最后只需保留Annotations、ImageSets和JPEGImages三個文件夾即可,ImageSets/Main文件中用到的只有trainval.txt和test.txt這兩個文件(數(shù)據(jù)分布:trainval=train+val,all_data=trainval+test),多類別如果增加負樣本或模糊樣本可以考慮1、0及-1操作(其中1表示有目標,0表示模糊目標,-1表示沒有目標)
數(shù)據(jù)集制作完成后將這三個文件夾復制至一個文件夾(命名為VOC2007)當中,再移動至$pva-faster-rcnn/data/VOCdevkit2007中,替換原來的VOC2007
2、類別設置:(有幾類設置幾類,類似fasterrcnn,我的數(shù)據(jù)集為1類行人數(shù)據(jù))
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
數(shù)據(jù)整理,在一行代碼為 ?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編譯后的文件,系統(tǒng)會直接調用。
終端進入lib/datasets文件目錄輸入:
python(此處應出現(xiàn)python的版本)
>>>import py_compile
>>>py_compile.compile(r'imdb.py')
>>>py_compile.compile(r'pascal_voc.py')
3、訓練數(shù)據(jù):
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(其他參數(shù)默認)
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?(其他參數(shù)默認)
第七部分:實驗結果
目前我訓練了10000左右,loss為0.1左右,其他四個參數(shù)分別在0.2、0.1、0.01、0.01左右
后續(xù)工作可做demo演示程序,小伙伴們盡請期待!
總結
以上是生活随笔為你收集整理的Faster RCNN代码理解(Python) ---训练过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows下VS2013 C++编译
- 下一篇: windows下实现c++版faster