<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一些目標(biāo)檢測(cè)技巧

          共 31836字,需瀏覽 64分鐘

           ·

          2021-05-19 18:03

          點(diǎn)擊上方機(jī)器學(xué)習(xí)與生成對(duì)抗網(wǎng)絡(luò)”,關(guān)注星標(biāo)

          獲取有趣、好玩的前沿干貨!

          本文轉(zhuǎn)自:視學(xué)算法

          一、數(shù)據(jù)增強(qiáng)


          數(shù)據(jù)增強(qiáng)是增加深度模型魯棒性和泛化性能的常用手段,隨機(jī)翻轉(zhuǎn)、隨機(jī)裁剪、添加噪聲等也被引入到檢測(cè)任務(wù)的訓(xùn)練中來(lái),個(gè)人認(rèn)為數(shù)據(jù)(監(jiān)督信息)的適時(shí)傳入可能是更有潛力的方向。
          個(gè)人觀點(diǎn):

          問(wèn)題:為什么圖像和Bbox需要進(jìn)行數(shù)據(jù)增強(qiáng)呢?
          答:因?yàn)閿?shù)據(jù)多了就可以盡可能多的學(xué)習(xí)到圖像中的不變性,學(xué)習(xí)到的不變性越多那么模型的泛化能力越強(qiáng)。
          但是輸入到CNN中的圖像為什么不具有平移不變性?如何去解決?下面鏈接有專(zhuān)門(mén)的解析:
          https://zhuanlan.zhihu.com/p/103342289
          MMDetection中,數(shù)據(jù)增強(qiáng)包括兩部分:(源碼解析)

          1)圖像增強(qiáng)

          • 源碼在mmdet/datasets/extra_aug.py里面,包括RandomCrop、brightness、contrast、saturation、ExtraAugmentation等等圖像增強(qiáng)方法。


          • 添加位置是train_pipeline或test_pipeline這個(gè)地方(一般train進(jìn)行增強(qiáng)而test不需要),例如數(shù)據(jù)增強(qiáng)RandomFlip,flip_ratio代表隨機(jī)翻轉(zhuǎn)的概率:


          train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), dict(type='RandomFlip', flip_ratio=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),]test_pipeline = [ dict(type='LoadImageFromFile'), dict( type='MultiScaleFlipAug', img_scale=(1333, 800), flip=False, transforms=[ dict(type='Resize', keep_ratio=True), dict(type='RandomFlip'), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']), ])]
           
            2) Bbox增強(qiáng)
          • 源碼在mmdet/datasets/custom.py里面,增強(qiáng)源碼為:


          def pre_pipeline(self, results):        results['img_prefix'] = self.img_prefix        results['seg_prefix'] = self.seg_prefix        results['proposal_file'] = self.proposal_file        results['bbox_fields'] = []        results['mask_fields'] = []



             二、Multi-scale Training/Testing 多尺度訓(xùn)練/測(cè)試


          輸入圖片的尺寸對(duì)檢測(cè)模型的性能影響相當(dāng)明顯,事實(shí)上,多尺度是提升精度最明顯的技巧之一。在基礎(chǔ)網(wǎng)絡(luò)部分常常會(huì)生成比原圖小數(shù)十倍的特征圖,導(dǎo)致小物體的特征描述不容易被檢測(cè)網(wǎng)絡(luò)捕捉。
          通過(guò)輸入更大、更多尺寸的圖片進(jìn)行訓(xùn)練,能夠在一定程度上提高檢測(cè)模型對(duì)物體大小的魯棒性,僅在測(cè)試階段引入多尺度,也可享受大尺寸和多尺寸帶來(lái)的增益。
          multi-scale training/testing最早見(jiàn)于[1],訓(xùn)練時(shí),預(yù)先定義幾個(gè)固定的尺度,每個(gè)epoch隨機(jī)選擇一個(gè)尺度進(jìn)行訓(xùn)練。測(cè)試時(shí),生成幾個(gè)不同尺度的feature map,對(duì)每個(gè)Region Proposal,在不同的feature map上也有不同的尺度,我們選擇最接近某一固定尺寸(即檢測(cè)頭部的輸入尺寸)的Region Proposal作為后續(xù)的輸入。
          在[2]中,選擇單一尺度的方式被Maxout(element-wise max,逐元素取最大)取代:隨機(jī)選兩個(gè)相鄰尺度,經(jīng)過(guò)Pooling后使用Maxout進(jìn)行合并,如下圖所示。
          使用Maxout合并feature vector
          近期的工作如FPN等已經(jīng)嘗試在不同尺度的特征圖上進(jìn)行檢測(cè),但多尺度訓(xùn)練/測(cè)試仍作為一種提升性能的有效技巧被應(yīng)用在MS COCO等比賽中。

          MMDetection中,多尺度訓(xùn)練/測(cè)試:(源碼解析)
          只需要修改train_pipeline 和test_pipeline中的img_scale部分即可(換成[(), ()])。帶來(lái)的影響是:train達(dá)到擬合的時(shí)間增加、test的時(shí)間增加,一旦test的時(shí)間增加一定會(huì)影響比賽的分?jǐn)?shù),因?yàn)楸荣惗紩?huì)將測(cè)試的時(shí)間作為評(píng)分標(biāo)準(zhǔn)之一:
          train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations', with_bbox=True), dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), #這里可以更換多尺度[(),()] dict(type='RandomFlip', flip_ratio=0.5), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),]test_pipeline = [ dict(type='LoadImageFromFile'), dict( type='MultiScaleFlipAug', img_scale=(1333, 800), flip=False, transforms=[ dict(type='Resize', keep_ratio=True), dict(type='RandomFlip'), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size_divisor=32), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']), ])]



            三、Global Context 全局語(yǔ)境



          這一技巧在ResNet的工作[3]中提出,做法是把整張圖片作為一個(gè)RoI,對(duì)其進(jìn)行RoI Pooling并將得到的feature vector拼接于每個(gè)RoI的feature vector上,作為一種輔助信息傳入之后的R-CNN子網(wǎng)絡(luò)。目前,也有把相鄰尺度上的RoI互相作為context共同傳入的做法。
          這一部分暫時(shí)沒(méi)有代碼解析。


           四、Box Refinement/Voting 預(yù)測(cè)框微調(diào)/投票法



          微調(diào)法和投票法由工作[4]提出,前者也被稱(chēng)為Iterative Localization。微調(diào)法最初是在SS算法得到的Region Proposal基礎(chǔ)上用檢測(cè)頭部進(jìn)行多次迭代得到一系列box,在ResNet的工作中,作者將輸入R-CNN子網(wǎng)絡(luò)的Region Proposal和R-CNN子網(wǎng)絡(luò)得到的預(yù)測(cè)框共同進(jìn)行NMS(見(jiàn)下面小節(jié))后處理,
          最后,把跟NMS篩選所得預(yù)測(cè)框的IoU超過(guò)一定閾值的預(yù)測(cè)框進(jìn)行按其分?jǐn)?shù)加權(quán)的平均,得到最后的預(yù)測(cè)結(jié)果。投票法可以理解為以頂尖篩選出一流,再用一流的結(jié)果進(jìn)行加權(quán)投票決策。
          不同的訓(xùn)練策略,不同的 epoch 預(yù)測(cè)的結(jié)果,使用 NMS 來(lái)融合,或者softnms
          需要調(diào)整的參數(shù):
          • box voting 的閾值,

          • 不同的輸入中這個(gè)框至少出現(xiàn)了幾次來(lái)允許它輸出,

          • 得分的閾值,一個(gè)目標(biāo)框的得分低于這個(gè)閾值的時(shí)候,就刪掉這個(gè)目標(biāo)框。

          這一部分暫時(shí)沒(méi)有代碼解析。
          五、隨機(jī)權(quán)值平均(SWA)


          隨機(jī)權(quán)值平均只需快速集合集成的一小部分算力,就可以接近其表現(xiàn)。SWA 可以用在任意架構(gòu)和數(shù)據(jù)集上,都會(huì)有不錯(cuò)的表現(xiàn)。根據(jù)論文中的實(shí)驗(yàn),SWA 可以得到我之前提到過(guò)的更寬的極小值。
          在經(jīng)典認(rèn)知下,SWA 不算集成,因?yàn)樵谟?xùn)練的最終階段你只得到一個(gè)模型,但它的表現(xiàn)超過(guò)了快照集成,接近 FGE(多個(gè)模型取平均)。
          左圖:W1、W2、W3分別代表3個(gè)獨(dú)立訓(xùn)練的網(wǎng)絡(luò),Wswa為其平均值。中圖:WSWA 在測(cè)試集上的表現(xiàn)超越了SGD。右圖:WSWA 在訓(xùn)練時(shí)的損失比SGD要高。
          結(jié)合 WSWA 在測(cè)試集上優(yōu)于 SGD 的表現(xiàn),這意味著盡管 WSWA 訓(xùn)練時(shí)的損失較高,它的泛化性更好。
          SWA 的直覺(jué)來(lái)自以下由經(jīng)驗(yàn)得到的觀察:每個(gè)學(xué)習(xí)率周期得到的局部極小值傾向于堆積在損失平面的低損失值區(qū)域的邊緣(上圖左側(cè)的圖形中,褐色區(qū)域誤差較低,點(diǎn)W1、W2、3分別表示3個(gè)獨(dú)立訓(xùn)練的網(wǎng)絡(luò),位于褐色區(qū)域的邊緣)。
          對(duì)這些點(diǎn)取平均值,可能得到一個(gè)寬闊的泛化解,其損失更低(上圖左側(cè)圖形中的 WSWA)。
          下面是 SWA 的工作原理。它只保存兩個(gè)模型,而不是許多模型的集成:
          1. 第一個(gè)模型保存模型權(quán)值的平均值(WSWA)。在訓(xùn)練結(jié)束后,它將是用于預(yù)測(cè)的最終模型。

          2. 第二個(gè)模型(W)將穿過(guò)權(quán)值空間,基于周期性學(xué)習(xí)率規(guī)劃探索權(quán)重空間。

          SWA權(quán)重更新公式
          在每個(gè)學(xué)習(xí)率周期的末尾,第二個(gè)模型的當(dāng)前權(quán)重將用來(lái)更新第一個(gè)模型的權(quán)重(公式如上)。因此,在訓(xùn)練階段,只需訓(xùn)練一個(gè)模型,并在內(nèi)存中儲(chǔ)存兩個(gè)模型。
          預(yù)測(cè)時(shí)只需要平均模型,基于其進(jìn)行預(yù)測(cè)將比之前描述的集成快很多,因?yàn)樵谀欠N集成中,你需要使用多個(gè)模型進(jìn)行預(yù)測(cè),最后再進(jìn)行平均。
          方法實(shí)現(xiàn):
          論文的作者自己提供了一份 PyTorch 的實(shí)現(xiàn) :
          https://github.com/timgaripov/swa

          此外,基于 fast.ai 庫(kù)的 SWA 可見(jiàn) :

          https://github.com/fastai/fastai/pull/276/commits

          六、OHEM 在線難例挖掘
          OHEM(Online Hard negative Example Mining,在線難例挖掘)見(jiàn)于[5]。兩階段檢測(cè)模型中,提出的RoI Proposal在輸入R-CNN子網(wǎng)絡(luò)前,我們有機(jī)會(huì)對(duì)正負(fù)樣本(背景類(lèi)和前景類(lèi))的比例進(jìn)行調(diào)整。
          通常,背景類(lèi)的RoI Proposal個(gè)數(shù)要遠(yuǎn)遠(yuǎn)多于前景類(lèi),F(xiàn)ast R-CNN的處理方式是隨機(jī)對(duì)兩種樣本進(jìn)行上采樣和下采樣,以使每一batch的正負(fù)樣本比例保持在1:3,這一做法緩解了類(lèi)別比例不均衡的問(wèn)題,是兩階段方法相比單階段方法具有優(yōu)勢(shì)的地方,也被后來(lái)的大多數(shù)工作沿用。
          OHEM圖解
          但在OHEM的工作中,作者提出用R-CNN子網(wǎng)絡(luò)對(duì)RoI Proposal預(yù)測(cè)的分?jǐn)?shù)來(lái)決定每個(gè)batch選用的樣本,這樣,輸入R-CNN子網(wǎng)絡(luò)的RoI Proposal總為其表現(xiàn)不好的樣本,提高了監(jiān)督學(xué)習(xí)的效率。
          實(shí)際操作中,維護(hù)兩個(gè)完全相同的R-CNN子網(wǎng)絡(luò),其中一個(gè)只進(jìn)行前向傳播來(lái)為RoI Proposal的選擇提供指導(dǎo),另一個(gè)則為正常的R-CNN,參與損失的計(jì)算并更新權(quán)重,并且將權(quán)重復(fù)制到前者以使兩個(gè)分支權(quán)重同步。
          OHEM以額外的R-CNN子網(wǎng)絡(luò)的開(kāi)銷(xiāo)來(lái)改善RoI Proposal的質(zhì)量,更有效地利用數(shù)據(jù)的監(jiān)督信息,成為兩階段模型提升性能的常用部件之一。
          MMDetection中,OHEM(online hard example mining):(源碼解析)
          rcnn=[        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.4, # 更換                neg_iou_thr=0.4,                min_pos_iou=0.4,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler',                num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False),        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.5,                neg_iou_thr=0.5,                min_pos_iou=0.5,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler', # 解決難易樣本,也解決了正負(fù)樣本比例問(wèn)題。num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False),        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.6,                neg_iou_thr=0.6,                min_pos_iou=0.6,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler',                num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False)    ],    stage_loss_weights=[1, 0.5, 0.25])
            七、Soft NMS 軟化非極大抑制



          NMS后處理圖示
          NMS(Non-Maximum Suppression,非極大抑制)是檢測(cè)模型的標(biāo)準(zhǔn)后處理操作,用于去除重合度(IoU)較高的預(yù)測(cè)框,只保留預(yù)測(cè)分?jǐn)?shù)最高的預(yù)測(cè)框作為檢測(cè)輸出。Soft NMS由[6]提出。
          在傳統(tǒng)的NMS中,跟最高預(yù)測(cè)分?jǐn)?shù)預(yù)測(cè)框重合度超出一定閾值的預(yù)測(cè)框會(huì)被直接舍棄,作者認(rèn)為這樣不利于相鄰物體的檢測(cè)。提出的改進(jìn)方法是根據(jù)IoU將預(yù)測(cè)框的預(yù)測(cè)分?jǐn)?shù)進(jìn)行懲罰,最后再按分?jǐn)?shù)過(guò)濾。
          配合Deformable Convnets(將在之后的文章介紹),Soft NMS在MS COCO上取得了當(dāng)時(shí)最佳的表現(xiàn)。算法改進(jìn)如下:
          上圖中的即為軟化函數(shù),通常取線性或高斯函數(shù),后者效果稍好一些。當(dāng)然,在享受這一增益的同時(shí),Soft-NMS也引入了一些超參,對(duì)不同的數(shù)據(jù)集需要試探以確定最佳配置。
          MMDetection中,Soft NMS 軟化非極大抑制:(源碼解析)
          test_cfg = dict(    rpn=dict(        nms_across_levels=False,        nms_pre=1000,        nms_post=1000,        max_num=1000,        nms_thr=0.7,        min_bbox_size=0),    rcnn=dict(        score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=20)) # 這里可以換為sof_tnms
          八、RoIAlign RoI對(duì)齊
          RoIAlign是Mask R-CNN([7])的工作中提出的,針對(duì)的問(wèn)題是RoI在進(jìn)行Pooling時(shí)有不同程度的取整,這影響了實(shí)例分割中mask損失的計(jì)算。文章采用雙線性插值的方法將RoI的表示精細(xì)化,并帶來(lái)了較為明顯的性能提升。這一技巧也被后來(lái)的一些工作(如light-head R-CNN)沿用。
          這一部分暫時(shí)沒(méi)有代碼解析。
          九、其他方法
          除去上面所列的技巧外,還有一些做法也值得注意:
          • 更好的先驗(yàn)(YOLOv2):使用聚類(lèi)方法統(tǒng)計(jì)數(shù)據(jù)中box標(biāo)注的大小和長(zhǎng)寬比,以更好的設(shè)置anchor box的生成配置



          • 更好的pre-train模型:檢測(cè)模型的基礎(chǔ)網(wǎng)絡(luò)通常使用ImageNet(通常是ImageNet-1k)上訓(xùn)練好的模型進(jìn)行初始化,使用更大的數(shù)據(jù)集(ImageNet-5k)預(yù)訓(xùn)練基礎(chǔ)網(wǎng)絡(luò)對(duì)精度的提升亦有幫助



          • 超參數(shù)的調(diào)整:部分工作也發(fā)現(xiàn)如NMS中IoU閾值的調(diào)整(從0.3到0.5)也有利于精度的提升,但這一方面尚無(wú)最佳配置參照

          最后,集成(Ensemble)作為通用的手段也被應(yīng)用在比賽中。
           代碼部分

          1.各部分代碼解析

          1.1 faster_rcnn_r50_fpn_1x.py:

          首先介紹一下這個(gè)配置文件所描述的框架,它是基于resnet50的backbone,有著5個(gè)fpn特征層的faster-RCNN目標(biāo)檢測(cè)網(wǎng)絡(luò),訓(xùn)練迭代次數(shù)為標(biāo)準(zhǔn)的12次epoch。
          # model settingsmodel = dict( type='FasterRCNN', # model類(lèi)型 pretrained='modelzoo://resnet50', # 預(yù)訓(xùn)練模型:imagenet-resnet50 backbone=dict( type='ResNet', # backbone類(lèi)型 depth=50, # 網(wǎng)絡(luò)層數(shù) num_stages=4, # resnet的stage數(shù)量 out_indices=(0, 1, 2, 3), # 輸出的stage的序號(hào) frozen_stages=1, # 凍結(jié)的stage數(shù)量,即該stage不更新參數(shù),-1表示所有的stage都更新參數(shù) style='pytorch'), # 網(wǎng)絡(luò)風(fēng)格:如果設(shè)置pytorch,則stride為2的層是conv3x3的卷積層;如果設(shè)置caffe,則stride為2的層是第一個(gè)conv1x1的卷積層 neck=dict( type='FPN', # neck類(lèi)型 in_channels=[256, 512, 1024, 2048], # 輸入的各個(gè)stage的通道數(shù) out_channels=256, # 輸出的特征層的通道數(shù) num_outs=5), # 輸出的特征層的數(shù)量 rpn_head=dict( type='RPNHead', # RPN網(wǎng)絡(luò)類(lèi)型 in_channels=256, # RPN網(wǎng)絡(luò)的輸入通道數(shù) feat_channels=256, # 特征層的通道數(shù) anchor_scales=[8], # 生成的anchor的baselen,baselen = sqrt(w*h),w和h為anchor的寬和高 anchor_ratios=[0.5, 1.0, 2.0], # anchor的寬高比 anchor_strides=[4, 8, 16, 32, 64], # 在每個(gè)特征層上的anchor的步長(zhǎng)(對(duì)應(yīng)于原圖) target_means=[.0, .0, .0, .0], # 均值 target_stds=[1.0, 1.0, 1.0, 1.0], # 方差 use_sigmoid_cls=True), # 是否使用sigmoid來(lái)進(jìn)行分類(lèi),如果False則使用softmax來(lái)分類(lèi) bbox_roi_extractor=dict( type='SingleRoIExtractor', # RoIExtractor類(lèi)型 roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2), # ROI具體參數(shù):ROI類(lèi)型為ROIalign,輸出尺寸為7,sample數(shù)為2 out_channels=256, # 輸出通道數(shù) featmap_strides=[4, 8, 16, 32]), # 特征圖的步長(zhǎng) bbox_head=dict( type='SharedFCBBoxHead', # 全連接層類(lèi)型 num_fcs=2, # 全連接層數(shù)量 in_channels=256, # 輸入通道數(shù) fc_out_channels=1024, # 輸出通道數(shù) roi_feat_size=7, # ROI特征層尺寸 num_classes=81, # 分類(lèi)器的類(lèi)別數(shù)量+1,+1是因?yàn)槎嗔艘粋€(gè)背景的類(lèi)別 target_means=[0., 0., 0., 0.], # 均值 target_stds=[0.1, 0.1, 0.2, 0.2], # 方差 reg_class_agnostic=False)) # 是否采用class_agnostic的方式來(lái)預(yù)測(cè),class_agnostic表示輸出bbox時(shí)只考慮其是否為前景,后續(xù)分類(lèi)的時(shí)候再根據(jù)該bbox在網(wǎng)絡(luò)中的類(lèi)別得分來(lái)分類(lèi),也就是說(shuō)一個(gè)框可以對(duì)應(yīng)多個(gè)類(lèi)別# model training and testing settingstrain_cfg = dict( rpn=dict( assigner=dict( type='MaxIoUAssigner', # RPN網(wǎng)絡(luò)的正負(fù)樣本劃分 pos_iou_thr=0.7, # 正樣本的iou閾值 neg_iou_thr=0.3, # 負(fù)樣本的iou閾值 min_pos_iou=0.3, # 正樣本的iou最小值。如果assign給ground truth的anchors中最大的IOU低于0.3,則忽略所有的anchors,否則保留最大IOU的anchor ignore_iof_thr=-1), # 忽略bbox的閾值,當(dāng)ground truth中包含需要忽略的bbox時(shí)使用,-1表示不忽略 sampler=dict( type='RandomSampler', # 正負(fù)樣本提取器類(lèi)型 num=256, # 需提取的正負(fù)樣本數(shù)量 pos_fraction=0.5, # 正樣本比例 neg_pos_ub=-1, # 最大負(fù)樣本比例,大于該比例的負(fù)樣本忽略,-1表示不忽略 add_gt_as_proposals=False), # 把ground truth加入proposal作為正樣本 allowed_border=0, # 允許在bbox周?chē)鈹U(kuò)一定的像素 pos_weight=-1, # 正樣本權(quán)重,-1表示不改變?cè)嫉臋?quán)重 smoothl1_beta=1 / 9.0, # 平滑L1系數(shù) debug=False), # debug模式 rcnn=dict( assigner=dict( type='MaxIoUAssigner', # RCNN網(wǎng)絡(luò)正負(fù)樣本劃分 pos_iou_thr=0.5, # 正樣本的iou閾值 neg_iou_thr=0.5, # 負(fù)樣本的iou閾值 min_pos_iou=0.5, # 正樣本的iou最小值。如果assign給ground truth的anchors中最大的IOU低于0.3,則忽略所有的anchors,否則保留最大IOU的anchor ignore_iof_thr=-1), # 忽略bbox的閾值,當(dāng)ground truth中包含需要忽略的bbox時(shí)使用,-1表示不忽略 sampler=dict( type='RandomSampler', # 正負(fù)樣本提取器類(lèi)型 num=512, # 需提取的正負(fù)樣本數(shù)量 pos_fraction=0.25, # 正樣本比例 neg_pos_ub=-1, # 最大負(fù)樣本比例,大于該比例的負(fù)樣本忽略,-1表示不忽略 add_gt_as_proposals=True), # 把ground truth加入proposal作為正樣本 pos_weight=-1, # 正樣本權(quán)重,-1表示不改變?cè)嫉臋?quán)重 debug=False)) # debug模式test_cfg = dict( rpn=dict( # 推斷時(shí)的RPN參數(shù) nms_across_levels=False, # 在所有的fpn層內(nèi)做nms nms_pre=2000, # 在nms之前保留的的得分最高的proposal數(shù)量 nms_post=2000, # 在nms之后保留的的得分最高的proposal數(shù)量 max_num=2000, # 在后處理完成之后保留的proposal數(shù)量 nms_thr=0.7, # nms閾值 min_bbox_size=0), # 最小bbox尺寸 rcnn=dict( score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100) # max_per_img表示最終輸出的det bbox數(shù)量 # soft-nms is also supported for rcnn testing # e.g., nms=dict(type='soft_nms', iou_thr=0.5, min_score=0.05) # soft_nms參數(shù))# dataset settingsdataset_type = 'CocoDataset' # 數(shù)據(jù)集類(lèi)型data_root = 'data/coco/' # 數(shù)據(jù)集根目錄img_norm_cfg = dict( mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) # 輸入圖像初始化,減去均值mean并處以方差std,to_rgb表示將bgr轉(zhuǎn)為rgbdata = dict( imgs_per_gpu=2, # 每個(gè)gpu計(jì)算的圖像數(shù)量 workers_per_gpu=2, # 每個(gè)gpu分配的線程數(shù) train=dict( type=dataset_type, # 數(shù)據(jù)集類(lèi)型 ann_file=data_root + 'annotations/instances_train2017.json', # 數(shù)據(jù)集annotation路徑 img_prefix=data_root + 'train2017/', # 數(shù)據(jù)集的圖片路徑 img_scale=(1333, 800), # 輸入圖像尺寸,最大邊1333,最小邊800 img_norm_cfg=img_norm_cfg, # 圖像初始化參數(shù) size_divisor=32, # 對(duì)圖像進(jìn)行resize時(shí)的最小單位,32表示所有的圖像都會(huì)被resize成32的倍數(shù) flip_ratio=0.5, # 圖像的隨機(jī)左右翻轉(zhuǎn)的概率 with_mask=False, # 訓(xùn)練時(shí)附帶mask with_crowd=True, # 訓(xùn)練時(shí)附帶difficult的樣本 with_label=True), # 訓(xùn)練時(shí)附帶label val=dict( type=dataset_type, # 同上 ann_file=data_root + 'annotations/instances_val2017.json', # 同上 img_prefix=data_root + 'val2017/', # 同上 img_scale=(1333, 800), # 同上 img_norm_cfg=img_norm_cfg, # 同上 size_divisor=32, # 同上 flip_ratio=0, # 同上 with_mask=False, # 同上 with_crowd=True, # 同上 with_label=True), # 同上 test=dict( type=dataset_type, # 同上 ann_file=data_root + 'annotations/instances_val2017.json', # 同上 img_prefix=data_root + 'val2017/', # 同上 img_scale=(1333, 800), # 同上 img_norm_cfg=img_norm_cfg, # 同上 size_divisor=32, # 同上 flip_ratio=0, # 同上 with_mask=False, # 同上 with_label=False, # 同上 test_mode=True)) # 同上# optimizeroptimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001) # 優(yōu)化參數(shù),lr為學(xué)習(xí)率,momentum為動(dòng)量因子,weight_decay為權(quán)重衰減因子optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2)) # 梯度均衡參數(shù)# learning policylr_config = dict( policy='step', # 優(yōu)化策略 warmup='linear', # 初始的學(xué)習(xí)率增加的策略,linear為線性增加 warmup_iters=500, # 在初始的500次迭代中學(xué)習(xí)率逐漸增加 warmup_ratio=1.0 / 3, # 起始的學(xué)習(xí)率 step=[8, 11]) # 在第8和11個(gè)epoch時(shí)降低學(xué)習(xí)率checkpoint_config = dict(interval=1) # 每1個(gè)epoch存儲(chǔ)一次模型# yapf:disablelog_config = dict( interval=50, # 每50個(gè)batch輸出一次信息 hooks=[ dict(type='TextLoggerHook'), # 控制臺(tái)輸出信息的風(fēng)格 # dict(type='TensorboardLoggerHook') ])# yapf:enable# runtime settingstotal_epochs = 12 # 最大epoch數(shù)dist_params = dict(backend='nccl') # 分布式參數(shù)log_level = 'INFO' # 輸出信息的完整度級(jí)別work_dir = './work_dirs/faster_rcnn_r50_fpn_1x' # log文件和模型文件存儲(chǔ)路徑load_from = None # 加載模型的路徑,None表示從預(yù)訓(xùn)練模型加載resume_from = None # 恢復(fù)訓(xùn)練模型的路徑workflow = [('train', 1)] # 當(dāng)前工作區(qū)名稱(chēng)

          1.2 cascade_rcnn_r50_fpn_1x.py

          cascade-RCNN是cvpr2018的文章,相比于faster-RCNN的改進(jìn)主要在于其RCNN有三個(gè)stage,這三個(gè)stage逐級(jí)refine檢測(cè)的結(jié)果,使得結(jié)果達(dá)到更高的精度。
          下面逐條解釋其config的含義,與faster-RCNN相同的部分就不再贅述
          # model settingsmodel = dict( type='CascadeRCNN', num_stages=3, # RCNN網(wǎng)絡(luò)的stage數(shù)量,在faster-RCNN中為1 pretrained='modelzoo://resnet50', backbone=dict( type='ResNet', depth=50, num_stages=4, out_indices=(0, 1, 2, 3), frozen_stages=1, style='pytorch'), neck=dict( type='FPN', in_channels=[256, 512, 1024, 2048], out_channels=256, num_outs=5), rpn_head=dict( type='RPNHead', in_channels=256, feat_channels=256, anchor_scales=[8], anchor_ratios=[0.5, 1.0, 2.0], anchor_strides=[4, 8, 16, 32, 64], target_means=[.0, .0, .0, .0], target_stds=[1.0, 1.0, 1.0, 1.0], use_sigmoid_cls=True), bbox_roi_extractor=dict( type='SingleRoIExtractor', roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2), out_channels=256, featmap_strides=[4, 8, 16, 32]), bbox_head=[ dict( type='SharedFCBBoxHead', num_fcs=2, in_channels=256, fc_out_channels=1024, roi_feat_size=7, num_classes=81, target_means=[0., 0., 0., 0.], target_stds=[0.1, 0.1, 0.2, 0.2], reg_class_agnostic=True), dict( type='SharedFCBBoxHead', num_fcs=2, in_channels=256, fc_out_channels=1024, roi_feat_size=7, num_classes=81, target_means=[0., 0., 0., 0.], target_stds=[0.05, 0.05, 0.1, 0.1], reg_class_agnostic=True), dict( type='SharedFCBBoxHead', num_fcs=2, in_channels=256, fc_out_channels=1024, roi_feat_size=7, num_classes=81, target_means=[0., 0., 0., 0.], target_stds=[0.033, 0.033, 0.067, 0.067], reg_class_agnostic=True) ])# model training and testing settingstrain_cfg = dict( rpn=dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=256, pos_fraction=0.5, neg_pos_ub=-1, add_gt_as_proposals=False), allowed_border=0, pos_weight=-1, smoothl1_beta=1 / 9.0, debug=False), rcnn=[ # 注意,這里有3個(gè)RCNN的模塊,對(duì)應(yīng)開(kāi)頭的那個(gè)RCNN的stage數(shù)量 dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.5, min_pos_iou=0.5, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=512, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True), pos_weight=-1, debug=False), dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.6, neg_iou_thr=0.6, min_pos_iou=0.6, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=512, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True), pos_weight=-1, debug=False), dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.7, min_pos_iou=0.7, ignore_iof_thr=-1), sampler=dict( type='RandomSampler', num=512, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True), pos_weight=-1, debug=False) ], stage_loss_weights=[1, 0.5, 0.25]) # 3個(gè)RCNN的stage的loss權(quán)重test_cfg = dict( rpn=dict( nms_across_levels=False, nms_pre=2000, nms_post=2000, max_num=2000, nms_thr=0.7, min_bbox_size=0), rcnn=dict( score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=100), keep_all_stages=False) # 是否保留所有stage的結(jié)果# dataset settingsdataset_type = 'CocoDataset'data_root = 'data/coco/'img_norm_cfg = dict( mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)data = dict( imgs_per_gpu=2, workers_per_gpu=2, train=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_train2017.json', img_prefix=data_root + 'train2017/', img_scale=(1333, 800), img_norm_cfg=img_norm_cfg, size_divisor=32, flip_ratio=0.5, with_mask=False, with_crowd=True, with_label=True), val=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/', img_scale=(1333, 800), img_norm_cfg=img_norm_cfg, size_divisor=32, flip_ratio=0, with_mask=False, with_crowd=True, with_label=True), test=dict( type=dataset_type, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/', img_scale=(1333, 800), img_norm_cfg=img_norm_cfg, size_divisor=32, flip_ratio=0, with_mask=False, with_label=False, test_mode=True))# optimizeroptimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))# learning policylr_config = dict( policy='step', warmup='linear', warmup_iters=500, warmup_ratio=1.0 / 3, step=[8, 11])checkpoint_config = dict(interval=1)# yapf:disablelog_config = dict( interval=50, hooks=[ dict(type='TextLoggerHook'), # dict(type='TensorboardLoggerHook') ])# yapf:enable# runtime settingstotal_epochs = 12dist_params = dict(backend='nccl')log_level = 'INFO'work_dir = './work_dirs/cascade_rcnn_r50_fpn_1x'load_from = Noneresume_from = Noneworkflow = [('train', 1)]


          2.trick部分代碼,cascade_rcnn_r50_fpn_1x.py:

          # fp16 settingsfp16 = dict(loss_scale=512.)# model settingsmodel = dict(    type='CascadeRCNN',    num_stages=3,    pretrained='torchvision://resnet50',    backbone=dict(        type='ResNet',        depth=50,        num_stages=4,        out_indices=(0, 1, 2, 3),        frozen_stages=1,        style='pytorch',        #dcn=dict( #在最后三個(gè)block加入可變形卷積          #   modulated=False, deformable_groups=1, fallback_on_stride=False),          #  stage_with_dcn=(False, True, True, True)        ),    neck=dict(        type='FPN',        in_channels=[256, 512, 1024, 2048],        out_channels=256,        num_outs=5),    rpn_head=dict(        type='RPNHead',        in_channels=256,        feat_channels=256,        anchor_scales=[8],        anchor_ratios=[0.2, 0.5, 1.0, 2.0, 5.0], # 添加了0.2,5,過(guò)兩天發(fā)圖        anchor_strides=[4, 8, 16, 32, 64],        target_means=[.0, .0, .0, .0],        target_stds=[1.0, 1.0, 1.0, 1.0],        loss_cls=dict(            type='FocalLoss', use_sigmoid=True, loss_weight=1.0), # 修改了loss,為了調(diào)控難易樣本與正負(fù)樣本比例        loss_bbox=dict(type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0)),    bbox_roi_extractor=dict(        type='SingleRoIExtractor',        roi_layer=dict(type='RoIAlign', out_size=7, sample_num=2),        out_channels=256,        featmap_strides=[4, 8, 16, 32]),    bbox_head=[        dict(            type='SharedFCBBoxHead',            num_fcs=2,            in_channels=256,            fc_out_channels=1024,            roi_feat_size=7,            num_classes=11,            target_means=[0., 0., 0., 0.],            target_stds=[0.1, 0.1, 0.2, 0.2],            reg_class_agnostic=True,            loss_cls=dict(                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),        dict(            type='SharedFCBBoxHead',            num_fcs=2,            in_channels=256,            fc_out_channels=1024,            roi_feat_size=7,            num_classes=11,            target_means=[0., 0., 0., 0.],            target_stds=[0.05, 0.05, 0.1, 0.1],            reg_class_agnostic=True,            loss_cls=dict(                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0)),        dict(            type='SharedFCBBoxHead',            num_fcs=2,            in_channels=256,            fc_out_channels=1024,            roi_feat_size=7,            num_classes=11,            target_means=[0., 0., 0., 0.],            target_stds=[0.033, 0.033, 0.067, 0.067],            reg_class_agnostic=True,            loss_cls=dict(                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),            loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.0))    ])# model training and testing settingstrain_cfg = dict(    rpn=dict(        assigner=dict(            type='MaxIoUAssigner',            pos_iou_thr=0.7,            neg_iou_thr=0.3,            min_pos_iou=0.3,            ignore_iof_thr=-1),        sampler=dict(            type='RandomSampler',             num=256,            pos_fraction=0.5,            neg_pos_ub=-1,            add_gt_as_proposals=False),        allowed_border=0,        pos_weight=-1,        debug=False),    rpn_proposal=dict(        nms_across_levels=False,        nms_pre=2000,        nms_post=2000,        max_num=2000,        nms_thr=0.7,        min_bbox_size=0),    rcnn=[        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.4, # 更換                neg_iou_thr=0.4,                min_pos_iou=0.4,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler',                num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False),        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.5,                neg_iou_thr=0.5,                min_pos_iou=0.5,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler', # 解決難易樣本,也解決了正負(fù)樣本比例問(wèn)題。num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False),        dict(            assigner=dict(                type='MaxIoUAssigner',                pos_iou_thr=0.6,                neg_iou_thr=0.6,                min_pos_iou=0.6,                ignore_iof_thr=-1),            sampler=dict(                type='OHEMSampler',                num=512,                pos_fraction=0.25,                neg_pos_ub=-1,                add_gt_as_proposals=True),            pos_weight=-1,            debug=False)    ],    stage_loss_weights=[1, 0.5, 0.25])test_cfg = dict(    rpn=dict(        nms_across_levels=False,        nms_pre=1000,        nms_post=1000,        max_num=1000,        nms_thr=0.7,        min_bbox_size=0),    rcnn=dict(        score_thr=0.05, nms=dict(type='nms', iou_thr=0.5), max_per_img=20)) # 這里可以換為sof_tnms# dataset settingsdataset_type = 'CocoDataset'data_root = '../../data/chongqing1_round1_train1_20191223/'img_norm_cfg = dict(    mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)train_pipeline = [    dict(type='LoadImageFromFile'),    dict(type='LoadAnnotations', with_bbox=True),    dict(type='Resize', img_scale=(492,658), keep_ratio=True), #這里可以更換多尺度[(),()]    dict(type='RandomFlip', flip_ratio=0.5),    dict(type='Normalize', **img_norm_cfg),    dict(type='Pad', size_divisor=32),    dict(type='DefaultFormatBundle'),    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),]test_pipeline = [    dict(type='LoadImageFromFile'),    dict(        type='MultiScaleFlipAug',        img_scale=(492,658),        flip=False,        transforms=[            dict(type='Resize', keep_ratio=True),            dict(type='RandomFlip'),            dict(type='Normalize', **img_norm_cfg),            dict(type='Pad', size_divisor=32),            dict(type='ImageToTensor', keys=['img']),            dict(type='Collect', keys=['img']),        ])]data = dict(    imgs_per_gpu=8, # 有的同學(xué)不知道batchsize在哪修改,其實(shí)就是修改這里,每個(gè)gpu同時(shí)處理的images數(shù)目。workers_per_gpu=2,    train=dict(        type=dataset_type,        ann_file=data_root + 'fixed_annotations.json', # 更換自己的json文件        img_prefix=data_root + 'images/', # images目錄        pipeline=train_pipeline),    val=dict(        type=dataset_type,        ann_file=data_root + 'fixed_annotations.json',        img_prefix=data_root + 'images/',        pipeline=test_pipeline),    test=dict(        type=dataset_type,        ann_file=data_root + 'fixed_annotations.json',        img_prefix=data_root + 'images/',        pipeline=test_pipeline))# optimizeroptimizer = dict(type='SGD', lr=0.001, momentum=0.9, weight_decay=0.0001) # lr = 0.00125*batch_size,不能過(guò)大,否則梯度爆炸。optimizer_config = dict(grad_clip=dict(max_norm=35, norm_type=2))# learning policylr_config = dict(    policy='step',    warmup='linear',    warmup_iters=500,    warmup_ratio=1.0 / 3,    step=[6, 12, 19])checkpoint_config = dict(interval=1)# yapf:disablelog_config = dict(    interval=64,    hooks=[        dict(type='TextLoggerHook'), # 控制臺(tái)輸出信息的風(fēng)格        # dict(type='TensorboardLoggerHook') # 需要安裝tensorflow and tensorboard才可以使用    ])# yapf:enable# runtime settingstotal_epochs = 20dist_params = dict(backend='nccl')log_level = 'INFO'work_dir = '../work_dirs/cascade_rcnn_r50_fpn_1x' # 日志目錄load_from = '../work_dirs/cascade_rcnn_r50_fpn_1x/latest.pth' # 模型加載目錄文件#load_from = '../work_dirs/cascade_rcnn_r50_fpn_1x/cascade_rcnn_r50_coco_pretrained_weights_classes_11.pth'resume_from = Noneworkflow = [('train', 1)]


          猜您喜歡:


          超100篇!CVPR 2020最全GAN論文梳理匯總!

          拆解組新的GAN:解耦表征MixNMatch

          StarGAN第2版:多域多樣性圖像生成


          附下載 | 《可解釋的機(jī)器學(xué)習(xí)》中文版

          附下載 |《TensorFlow 2.0 深度學(xué)習(xí)算法實(shí)戰(zhàn)》

          附下載 |《計(jì)算機(jī)視覺(jué)中的數(shù)學(xué)方法》分享


          《基于深度學(xué)習(xí)的表面缺陷檢測(cè)方法綜述》

          《零樣本圖像分類(lèi)綜述: 十年進(jìn)展》

          《基于深度神經(jīng)網(wǎng)絡(luò)的少樣本學(xué)習(xí)綜述》


          瀏覽 155
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  丁香av| 三级视频国产 | 亚洲在线免费观看 | 小电影在线观看黄.999 | 日韩无码免费中文 |