SiameseRPN++分析
SiamRPN++
- 論文來源
- 論文背景
- 什么是目標(biāo)跟蹤
- 什么是孿生網(wǎng)絡(luò)結(jié)構(gòu)
- Siamese的局限
- 解決的問題
- 論文分析
- 創(chuàng)新點一:空間感知策略
- 創(chuàng)新點二:ResNet-50深層網(wǎng)絡(luò)
- 創(chuàng)新點三:多層特征融合
- 創(chuàng)新點四:深層互相關(guān)
- 代碼分析
- 整體代碼簡述
- (1)特征提取網(wǎng)絡(luò)
- (2)逐層的特征融合(Layerwise Aggregation)
- (3)深層互相關(guān)Depthwise Cross Correlation
- 總結(jié)
- 論文翻譯
- Abstract
- 1. Introduction
- 2. Related Work
- 3. Siamese Tracking with Very Deep Networks
- 3.1. Analysis on Siamese Networks for Tracking
- 3.2. ResNet-driven Siamese Tracking
- 3.3. Layer-wise Aggregation
- 3.4. Depthwise Cross Correlation
- 4. Experimental Results
- 4.1. Training Dataset and Evaluation
- 4.2. Implementation Details
- 4.3. Ablation Experiments
- 4.4. Comparison with the state-of-the-art
- 5. Conclusions
論文來源
論文鏈接
代碼鏈接
本文參考:
如何理解SiamRPN++?
SiamRPN++理解
SiamRPN++: 基于深度網(wǎng)絡(luò)的孿生視覺跟蹤的進(jìn)化
【SOT】Siamese RPN++ 論文和代碼解析
SiamRPN++算法詳解
論文背景
什么是目標(biāo)跟蹤
使用視頻序列第一幀的圖像(包括bounding box的位置),來找出目標(biāo)出現(xiàn)在后序幀位置的一種方法。
什么是孿生網(wǎng)絡(luò)結(jié)構(gòu)
在進(jìn)入到正式理解SiamRPN++之前,為了更好的理解這篇論文,我們需要先了解一下孿生網(wǎng)絡(luò)的結(jié)構(gòu)。
孿生網(wǎng)絡(luò)是一種度量學(xué)習(xí)的方法,而度量學(xué)習(xí)又被稱為相似度學(xué)習(xí)。
孿生網(wǎng)絡(luò)結(jié)構(gòu)被較早地利用在人臉識別的領(lǐng)域(《Learning a Similarity Metric Discriminatively, with Application to Face Verification》)。其思想是將一個訓(xùn)練樣本(已知類別)和一個測試樣本(未知類別)輸入到兩個CNN(這兩個CNN往往是權(quán)值共享的)中,從而獲得兩個特征向量,然后通過計算這兩個特征向量的的相似度,相似度越高表明其越可能是同一個類別。在上面這篇論文中,衡量這種相似度的方法是L1距離。
在目標(biāo)領(lǐng)域中,最早利用這種思想的是SiamFC,其網(wǎng)絡(luò)結(jié)構(gòu)如上圖。輸入的z 是第一幀ROI(也就是在手動在第一幀選擇的bounding box),x則是后一幀的圖片。兩者分別通過兩個CNN,得到兩張?zhí)卣鲌D。再通過一次卷積操作(L=(22-6)/1+1=17),獲得最后形狀為17×17×1的特征圖。在特征圖上響應(yīng)值越高的位置,代表其越可能有目標(biāo)存在。其想法就類似于對上面的人臉識別孿生網(wǎng)絡(luò)添加了一次卷積操作。獲得特征圖后,可以獲得相應(yīng)的損失函數(shù)。y={-1,+1}為真實標(biāo)簽,v是特征圖相應(yīng)位置的值。下列第一個式子是特征圖上每一個點的loss,第二個式子是對第一個式子作一個平均,第三個式子就是優(yōu)化目標(biāo)。
However, both Siamese-FC and CFNet are lack of boundingbox regression and need to do multi-scale test which makesit less elegant. The main drawback of these real-time track-ers is their unsatisfying accuracy and robustness comparedto state-of-the-art correlation filter approaches.但是,Siamese-FC和CFNet都沒有邊界框回歸,因此需要進(jìn)行多尺度測試,這使得它不太美觀。這些實時跟蹤器的主要缺點是,與最新的相關(guān)濾波器方法相比,它們的精度和魯棒性不令人滿意。
為了解決SiamFC的這兩個問題,就有了SiamRPN??梢钥吹角鞍氩糠諷iamese Network部分和SiamFC一模一樣(通道數(shù)有變化)。區(qū)別就在于后面的RPN網(wǎng)絡(luò)部分。特征圖會通過一個卷積層進(jìn)入到兩個分支中,在Classification Branch中的4×4×(2k×256)特征圖等價于有2k個4×4×256形狀的卷積核,對20×20×256作卷積操作,于是可以獲得17×17×2k的特征圖,Regression Branch操作同理。而RPN網(wǎng)絡(luò)進(jìn)行的是多任務(wù)的學(xué)習(xí)。17×17×2k做的是區(qū)分目標(biāo)和背景,其會被分為k個groups,每個group會有一層正例,一層負(fù)例。最后會用softmax + cross-entropy loss進(jìn)行損失計算。17×17×4k同樣會被分為k groups,每個group有四層,分別預(yù)測dx,dy,dw,dh。而k的值即為生成的anchors的數(shù)目。而關(guān)于anchor box的運行機(jī)制,可以看下方第二張圖(來自SSD)。
correlation操作詳解(涉及到后續(xù)改進(jìn)):以分類分支為例,在RPN中,分類分支需要輸出一個通道數(shù)為 2k 的特征圖( k 為anchor個數(shù)),SiamFC中使用的correlation只能提供通道數(shù)為1的響應(yīng)圖,無法滿足要求。所以我們換了一個想法,把correlation層當(dāng)成一個卷積層,template分支提取的特征作為卷積核,detection分支提取的特征作為卷積層的input,這樣只需要改變卷積核的形狀就可以達(dá)到輸出2k通道數(shù)的目的。具體做法為使用了兩個不同的卷積層,template分支的卷積層負(fù)責(zé)升維,把通道數(shù)提升到 256*2k ,為了保持對齊,detection分支也增加了一個卷積層,不過保持通道數(shù)不變。之后進(jìn)行correlation操作(卷積),得到最終的分類結(jié)果。
Siamese的局限
作者的實驗發(fā)現(xiàn),較深的網(wǎng)絡(luò),如 ResNet, 無法帶來跟蹤精度提升的原因在于:
更深的網(wǎng)絡(luò)的填充會破壞嚴(yán)格的平移不變性(Strict translation invariance)
padding會破壞這種性質(zhì)
現(xiàn)代化網(wǎng)絡(luò):隨著何鎧明等提出殘差網(wǎng)絡(luò)以后,網(wǎng)絡(luò)的深度得到了巨大的釋放,通常物體檢測和語義分割的baseline backbone都采用ResNet50的結(jié)構(gòu)。為了保證網(wǎng)絡(luò)具有適當(dāng)/整齊的分辨率,幾乎所有的現(xiàn)代網(wǎng)絡(luò)backbone都需要執(zhí)行padding操作。而ResNet網(wǎng)絡(luò)中具有padding操作,即該網(wǎng)絡(luò)肯定不具備嚴(yán)格的平移不變性,padding的引入會使得網(wǎng)絡(luò)輸出的響應(yīng)對不同位置有了不同的認(rèn)知。而我們進(jìn)行進(jìn)一步的訓(xùn)練是希望網(wǎng)絡(luò)學(xué)習(xí)到如何通過物體的表觀特征來分辨回歸物體,這就限制了深網(wǎng)絡(luò)在tracking領(lǐng)域的應(yīng)用。
RPN要求分類和回歸具有不對稱特征
即如果將搜索區(qū)域圖像和模板區(qū)域圖像進(jìn)行互換,輸出的結(jié)果應(yīng)該保持不變。(因為是相似度,所以應(yīng)該有對稱性)。
由于SiamRPN不再是進(jìn)行相似度計算,而是通過計算回歸的偏移量和分類的分?jǐn)?shù)來選擇最終的目標(biāo),這將使得該網(wǎng)絡(luò)不再具有對稱性。因而在SiamRPN的改進(jìn)中需要引入非對稱的部件,如果完全Siamese的話沒法達(dá)到目的,這一點主要會引導(dǎo)后面的correlation設(shè)計。
文中作者引入空間感知策略來克服第一個困難,并對第二個問題進(jìn)行討論。
針對第一個問題作者認(rèn)為Strict translation invariance只存在沒有padding的網(wǎng)絡(luò)中例如Alexnet,并且假設(shè)違反了這種限制將導(dǎo)致空間的傾斜(spatial bias)。
作者發(fā)現(xiàn)如下的幾個參數(shù),對跟蹤結(jié)果的影響,非常巨大:the receptive field size of neurons; network stride; feature padding。
具體來說,感受野決定了用于計算 feature 的圖像區(qū)域。較大的感受野,提供了更好的 image context 信息,而一個較小的感受野可能無法捕獲目標(biāo)的結(jié)構(gòu)信息;
網(wǎng)絡(luò)的步長,影響了定位準(zhǔn)確性的程度,特別是對小目標(biāo)而言;與此同時,它也控制了輸出 feature map 的大小,從而影響了 feature 的判別性和檢測精度。
此外,對于一個全卷積的結(jié)構(gòu)來說,feature padding 對卷積來說,會在模型訓(xùn)練中,引入潛在的位置偏移,從而使得當(dāng)一個目標(biāo)移動到接近搜索范圍邊界的時候,很難做出準(zhǔn)確的預(yù)測。這三個因素,同時造成了 Siamese Tracker 無法很好的從更頂尖的模型中收益。
解決的問題
該論文主要解決的問題是將深層基準(zhǔn)網(wǎng)絡(luò)ResNet、Inception等網(wǎng)絡(luò)應(yīng)用到基于孿生網(wǎng)絡(luò)的跟蹤網(wǎng)絡(luò)中。在SiameseFC算法之后,盡管已經(jīng)有很多的基于孿生網(wǎng)絡(luò)的跟蹤算法,但是大家可能會注意到一個問題是,這些網(wǎng)絡(luò)都使用淺層的類AlexNet做為基準(zhǔn)特征提取器。其實在這之前,也有學(xué)者們嘗試著使用深層的網(wǎng)絡(luò),但是發(fā)現(xiàn)直接使用預(yù)訓(xùn)練好的深層網(wǎng)絡(luò)反而會導(dǎo)致跟蹤算法精度的下降,因此,這成為了一個基于孿生網(wǎng)絡(luò)的跟蹤器需要解決的一個關(guān)鍵問題!
論文分析
創(chuàng)新點一:空間感知策略
1.平移不變性的問題
作者認(rèn)為Strict translation invariance只存在沒有padding的網(wǎng)絡(luò)中例如Alexnet,并且假設(shè)違反了這種限制將導(dǎo)致空間的傾斜(spatial bias)。作者發(fā)現(xiàn)如下的幾個參數(shù),對跟蹤結(jié)果的影響,非常巨大:the receptive field size of neurons; network stride; feature padding。具體來說,感受野決定了用于計算 feature 的圖像區(qū)域。較大的感受野,提供了更好的 image context 信息,而一個較小的感受野可能無法捕獲目標(biāo)的結(jié)構(gòu)信息;網(wǎng)絡(luò)的步長,影響了定位準(zhǔn)確性的程度,特別是對小目標(biāo)而言;與此同時,它也控制了輸出 feature map 的大小,從而影響了 feature 的判別性和檢測精度。此外,對于一個全卷積的結(jié)構(gòu)來說,feature padding 對卷積來說,會在模型訓(xùn)練中,引入潛在的位置偏移,從而使得當(dāng)一個目標(biāo)移動到接近搜索范圍邊界的時候,很難做出準(zhǔn)確的預(yù)測。這三個因素,同時造成了 Siamese Tracker 無法很好的從更頂尖的模型中收益。
2.如果破壞了網(wǎng)絡(luò)的平移不變性,具體會帶來什么問題呢?
如果現(xiàn)代化網(wǎng)絡(luò)的平移不變性被破壞以后,帶來的弊端就是會學(xué)習(xí)到位置偏見:按照SiamFC的訓(xùn)練方法,正樣本都在正中心,網(wǎng)絡(luò)逐漸會學(xué)習(xí)到這種統(tǒng)計特性,學(xué)到樣本中正樣本分布的情況。即簡而言之,網(wǎng)絡(luò)會給圖像的中心位置分配更大的權(quán)重。
3.空間感知策略
要想使用更深的特征提取網(wǎng)絡(luò),就要避免對目標(biāo)產(chǎn)生強(qiáng)烈的中心偏移,我們采用空間感知采樣策略訓(xùn)練了具有ResNet-50骨干網(wǎng)的SiamRPN。在訓(xùn)練過程中,我們不再把正樣本塊放在圖像正中心,而是按照均勻分布的采樣方式讓目標(biāo)在中心點附近進(jìn)行偏移。隨著偏移的范圍增大,深度網(wǎng)絡(luò)可以由剛開始的完全沒有效果逐漸變好。
具體的效果如下圖所示:當(dāng)我們將shift設(shè)置為0時,網(wǎng)絡(luò)只會關(guān)注圖像中心的位置,對應(yīng)到圖中就是只有中心位置具有較大的響應(yīng)值;而當(dāng)我們將shift設(shè)置為16時,網(wǎng)絡(luò)開始關(guān)注更多的圖像范圍,對應(yīng)到圖中就是響應(yīng)的范圍會擴(kuò)大,顏色由深變淺;而當(dāng)我們將shift設(shè)置為32時,網(wǎng)絡(luò)會關(guān)注更大額圖像范圍,對應(yīng)到圖中就是響應(yīng)的范圍變得更大,顏色也更加多樣化。
所以說,通過均勻分布的采樣方式讓目標(biāo)在中心點附近進(jìn)行偏移,可以緩解網(wǎng)絡(luò)因為破壞了嚴(yán)格平移不變性帶來的影響,即消除了位置偏見,讓現(xiàn)代化網(wǎng)絡(luò)可以應(yīng)用于跟蹤算法中。
4.為什么該問題在檢測任務(wù)和語義分割任務(wù)中并不存在?
因為對于物體檢測和語義分割而言,訓(xùn)練過程中,物體本身就是在全圖的每個位置較為均勻的分布。我們可以很容易的驗證,如果在物體檢測網(wǎng)絡(luò)只訓(xùn)練標(biāo)注在圖像中心的樣本,而邊緣的樣本都不進(jìn)行訓(xùn)練,那么顯然,這樣訓(xùn)練的網(wǎng)絡(luò)只會對圖像的中心位置產(chǎn)生高響應(yīng),邊緣位置就隨緣了,不難想象這種時候邊緣位置的性能顯然會大幅衰減。而更為致命的是,按照SiamFC的訓(xùn)練方式,中心位置為正樣本,邊緣位置為負(fù)樣本。那么網(wǎng)絡(luò)只會記錄下邊緣永遠(yuǎn)為負(fù),不管表觀是什么樣子了。這完全背離了我們訓(xùn)練的初衷。
創(chuàng)新點二:ResNet-50深層網(wǎng)絡(luò)
我們主要的實驗實在ResNet-50上做的。現(xiàn)代化網(wǎng)絡(luò)一般都是stride32,但跟蹤為了定位的準(zhǔn)確性,一般stride都比較小(Siamese系列一般都為8),所以我們把ResNet最后兩個block的stride去掉了,同時增加了dilated convolution,一是為了增加感受野,二是為了能利用上預(yù)訓(xùn)練參數(shù)。論文中提到的MobileNet等現(xiàn)代化網(wǎng)絡(luò)也是進(jìn)行了這樣的改動。如上圖所示,改過之后,后面三個block的分辨率就一致了。
在訓(xùn)練過程中采用了新的采樣策略后,我們可以訓(xùn)練ResNet網(wǎng)絡(luò)了,并且能夠正常跟蹤一些視頻了。(之前跟蹤過程中一直聚集在中心,根本無法正常跟蹤目標(biāo))。對backbone進(jìn)行finetune以后,又能夠進(jìn)一步得到一些性能提升。
由于所有層的填充都保持不變,模板特征的空間大小增加到15,這給相關(guān)模塊帶來了沉重的計算負(fù)擔(dān)。因此,作者裁剪中心7×7區(qū)域作為模板特征,其中每個特征單元仍然可以捕獲整個目標(biāo)區(qū)域。
創(chuàng)新點三:多層特征融合
在以前的工作中,僅使用像AlexNet這樣的淺層網(wǎng)絡(luò),多層特性不能提供非常不同的作用。然而,考慮到感受野的變化,ResNet中的不同層更有意義。淺層的特征主要集中在低層次的信息上,如顏色、形狀等,對于定位是必不可少的,而缺乏語義信息;深層的特征具有豐富的語義信息,在某些挑戰(zhàn)場景(如運動模糊、形變等)中是有益的。使用這種豐富的層次信息有助于跟蹤。
在多層使用siamrpn的好處
如創(chuàng)新點2中的圖所示,我們會觀察到作者分別在conv3_3、conv4_6和conv5_3的分支上使用siamrpn網(wǎng)絡(luò),并將前面siamrpn的結(jié)果輸入到后面的siamrpn網(wǎng)絡(luò)中,該思路類似于cvpr2019值的C-RPN算法,通過多級級聯(lián)具有兩個優(yōu)點:
創(chuàng)新點四:深層互相關(guān)
互相關(guān)模塊是嵌入兩個分支信息的核心操作。SiamFC利用互相關(guān)層獲得用于目標(biāo)定位的單信道響應(yīng)圖。在SiamRPN中,通過添加一個巨大的卷積層來縮放信道,擴(kuò)展了互相關(guān)以嵌入更高級別的信息,例如anchors。重上行信道模塊使得參數(shù)分布嚴(yán)重不平衡,使得SiamRPN訓(xùn)練優(yōu)化困難。
??作者提出了一個輕量級的互相關(guān)層,稱為深度互相關(guān),以實現(xiàn)有效的信息關(guān)聯(lián)。深度互相關(guān)層包含的參數(shù)比SiamRPN中使用的互相關(guān)層少10倍,性能與之相當(dāng)。
??為了達(dá)到這個目標(biāo),作者采用一個 conv-bn block 來調(diào)整特征,來適應(yīng)跟蹤任務(wù)。Bounding box prediction 和 基于 anchor 的分類都是非對稱的 (asymmetrical)。為了編碼這種不同,the template branch 和 search branch 傳輸兩個 non-shared convolutional layers。然后,這兩個 feature maps 是有相同個數(shù)的 channels,然后一個 channel 一個 channel 的進(jìn)行 correlation operation。另一個 conv-bn-relu block,用于融合不同 channel 的輸出。最終,最后一個卷積層,用于輸出 classification 和 regression 的結(jié)果。
通過用 Depthwise correlation 替換掉 cross-correlation,我們可以很大程度上降低計算代價和內(nèi)存使用。通過這種方式,template 和 search branch 的參數(shù)數(shù)量就會趨于平衡,導(dǎo)致訓(xùn)練過程更加穩(wěn)定。
如上圖所示,圖中(a)互相關(guān)層預(yù)測方法是取自SiamFC中目標(biāo)模板和搜索圖像之間的單通道相似性映射。模板圖像和搜索圖像在經(jīng)過網(wǎng)絡(luò)后輸出通道數(shù)相同的featuremap,兩者逐通道相互卷積,最后取平均值。
圖中(b)上行信道互相關(guān)層,取自SiamRPN,模板圖像和搜索圖像經(jīng)過特征提取網(wǎng)絡(luò)生成feature map后,輸入RPN網(wǎng)絡(luò),分類分支和回歸分支分別經(jīng)過非權(quán)值共享的卷積層后在相互卷積,參數(shù)量十分巨大。
圖中(c)深度互相關(guān)層預(yù)測模板和搜索圖像之間的多通道相關(guān)性特征,取自SiamRPN++,模板圖像經(jīng)過卷積層后并不像SiamRPN那樣將通道數(shù)增加2k倍(每個grid生成k個anchors),而是保持不變,同時搜索圖像也與模板圖像保持一致,兩者逐通道相互卷積,之后接一個1×1的卷積層,再改變通道數(shù),這樣在保持精度的同時減少了參數(shù)量。如下第一張圖,輸入兩個從ResNet獲得的特征層(channel數(shù)目是一致的),先同樣分別通過一個卷積層(由于需要學(xué)的任務(wù)不同,所以卷積層參數(shù)不共享),再分別進(jìn)行DW卷積操作,然后兩分支再分別通過一層不同的卷積層改變通道數(shù)以獲得想要的分類和回歸結(jié)果。這樣一來,就可以減少計算量,且使得兩個分支更加平衡。
通道數(shù)的研究:
下圖說明了一個有趣的現(xiàn)象。同一類別的對象在同一信道(148信道的car、222信道的person和226信道的face)上具有高響應(yīng),而其余信道的響應(yīng)被抑制。這一特性可以理解為,由深度互相關(guān)產(chǎn)生的信道方向特征幾乎是正交的,每個信道代表一些語義信息。我們還分析了當(dāng)使用上通道互相關(guān)時的熱圖,而響應(yīng)圖的解釋性較差。
上圖為conv4中的深度相關(guān)輸出通道。conv4共有256個通道,但只有少數(shù)信道在跟蹤過程中有較高的響應(yīng)。因此,選擇第148、222、226個通道作為演示,它們是圖中的第2、3、4行。第一行包含來自O(shè)TB數(shù)據(jù)集的六個相應(yīng)的搜索區(qū)域。不同的通道表示不同的語義,第148通道對汽車的響應(yīng)較高,而對人和臉的響應(yīng)較低。第222頻道和第226頻道分別對人和臉有很高的響應(yīng)。
代碼分析
整體代碼簡述
整體代碼主要分成兩個部分,第一個是初始幀標(biāo)記的目標(biāo)box為temple,第二個部分為追蹤過程中的track目標(biāo)。
代碼首先將初始幀進(jìn)行處理成127×127的形式然后進(jìn)入主體網(wǎng)絡(luò)(包括resnet50(經(jīng)過resnet50后輸出三個feature_map大小分別是[1, 512, 15, 15]、[1, 1024, 15, 15]、[1, 2048, 15, 15])和adjustnect)框架中,并將輸出的3個feature_map,其大小分別是[1, 128, 7, 7]、[1, 256, 7, 7]、[1, 512, 7, 7]進(jìn)行保存。
追蹤過程(始終保持上一幀目標(biāo)位置的中心),根據(jù)上一幀目標(biāo)位置的得分判斷是否進(jìn)行長期追蹤(長期追蹤圍繞中心位置搜索的面積較大寫,短期追蹤圍繞中心面積搜索的范圍較小,是否進(jìn)行長期追蹤主要是根據(jù)上上衣目標(biāo)幀的得分決定),按照追蹤形式將上一幀范圍內(nèi)的像素進(jìn)行剪裁填充以及resize成255×255,將剪裁過后的圖片輸入到網(wǎng)絡(luò)框架中(包括resnet50經(jīng)過resnet50后輸出三個feature_map大小分別是[1, 512, 31, 31]、[1, 1024, 31, 31]、[1, 2048, 31, 31])和adjustnect),并輸出三個feature_map大小分別為[1, 128, 31, 31]、[1, 256, 31, 31]、[1, 512, 31, 31]
最后temple和track中分別輸出的feature_map進(jìn)入rpn網(wǎng)絡(luò)中,按照索引一一對應(yīng)進(jìn)行卷積操,之后將templw中的feature展開成[temple.size[0]*temple.size[1], 1,temple.size[2],temple. zise[3]]的形式作為kernel,track同樣改變通道數(shù)作輸入層進(jìn)行卷積操作,之后將三次卷積操作的結(jié)果按照一定權(quán)重(網(wǎng)絡(luò)中訓(xùn)練出來的權(quán)重參數(shù))相加最后輸出。rpn中有兩個分支一個用來預(yù)測是否是目標(biāo)類別cls輸出的tensor大小[1, 10, 25,25](選擇的anchor數(shù)為5,預(yù)測為2分類因此第二個維度上的通道數(shù)為10),另一個分支預(yù)測位置的偏移量loc,輸出的tensor大小為[1, 20, 25, 25](選擇的anchor為5,預(yù)測四個位置上的偏移[x, y, w, h])。
根據(jù)cls何loc的輸出預(yù)測是否是目標(biāo)以及目標(biāo)位置,將cls何loc分別展開成[3125, 2], [3125, 4]的形式,cls經(jīng)過softmax分類器,并取最后一列最為目標(biāo)位置的預(yù)測概率。anchor box結(jié)合回歸結(jié)果得出bounding box。最后使用余弦窗和尺度變化懲罰來對cls中經(jīng)過softmax處理過后的最后一列進(jìn)行排序,選最好的。余弦窗是為了抑制距離過大的,尺度懲罰是為了抑制尺度大的變化
特征提取網(wǎng)絡(luò): 改進(jìn)的殘差網(wǎng)絡(luò)ResNet-50
逐層特征融合(Layerwise Aggregation)
Depthwise Cross Correlation
接下來按照分成的三部分進(jìn)行詳細(xì)說明。
(1)特征提取網(wǎng)絡(luò)
論文中提到
The original ResNet has a large stride of 32 pixels, which is not suitable for dense Siamese network prediction. As shown in Fig.3, we reduce the effective strides at the last two block from 16 pixels and 32 pixels to 8 pixels by modifying the conv4 and conv5 block to have unit spatial stride, and also increase its receptive field by dilated convolutions. An extra 1 x 1 convolution layer is appended to each of block outputs to reduce the channel to 256.
作者的意思就是嫌棄原來ResNet的stride過大,從而在conv4和conv5中將stride=2改動為stride=1。但是同時為了保持之前的感受野,采用了空洞卷積。其代碼定義如下:
class ResNetPP(nn.Module):def __init__(self, block, layers, used_layers):self.inplanes = 64super(ResNetPP, self).__init__()self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=0, # 3bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)self.layer1 = self._make_layer(block, 64, layers[0])self.layer2 = self._make_layer(block, 128, layers[1], stride=2)self.feature_size = 128 * block.expansionself.used_layers = used_layerslayer3 = True if 3 in used_layers else Falselayer4 = True if 4 in used_layers else Falseif layer3:self.layer3 = self._make_layer(block, 256, layers[2],stride=1, dilation=2) # 15x15, 7x7self.feature_size = (256 + 128) * block.expansionelse:self.layer3 = lambda x: x # identityif layer4:self.layer4 = self._make_layer(block, 512, layers[3],stride=1, dilation=4) # 7x7, 3x3self.feature_size = 512 * block.expansionelse:self.layer4 = lambda x: x # identityfor m in self.modules():if isinstance(m, nn.Conv2d):n = m.kernel_size[0] * m.kernel_size[1] * m.out_channelsm.weight.data.normal_(0, math.sqrt(2. / n))elif isinstance(m, nn.BatchNorm2d):m.weight.data.fill_(1)m.bias.data.zero_()def _make_layer(self, block, planes, blocks, stride=1, dilation=1):downsample = Nonedd = dilationif stride != 1 or self.inplanes != planes * block.expansion:if stride == 1 and dilation == 1:downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=1, stride=stride, bias=False),nn.BatchNorm2d(planes * block.expansion),)else:if dilation > 1:dd = dilation // 2padding = ddelse:dd = 1padding = 0downsample = nn.Sequential(nn.Conv2d(self.inplanes, planes * block.expansion,kernel_size=3, stride=stride, bias=False,padding=padding, dilation=dd),nn.BatchNorm2d(planes * block.expansion),)layers = []layers.append(block(self.inplanes, planes, stride,downsample, dilation=dilation))self.inplanes = planes * block.expansionfor i in range(1, blocks):layers.append(block(self.inplanes, planes, dilation=dilation))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x_ = self.relu(x)x = self.maxpool(x_)p1 = self.layer1(x)p2 = self.layer2(p1)p3 = self.layer3(p2)p4 = self.layer4(p3)out = [x_, p1, p2, p3, p4]out = [out[i] for i in self.used_layers]if len(out) == 1:return out[0]else:return out從上述代碼中的這段代碼可以看出
if layer3:self.layer3 = self._make_layer(block, 256, layers[2],stride=1, dilation=2) # 15x15, 7x7self.feature_size = (256 + 128) * block.expansionelse:self.layer3 = lambda x: x # identityif layer4:self.layer4 = self._make_layer(block, 512, layers[3],stride=1, dilation=4) # 7x7, 3x3self.feature_size = 512 * block.expansion作者在原來的ResNet-50的基礎(chǔ)上進(jìn)行了一些修改,包括stride=1與空洞卷積的使用。
(2)逐層的特征融合(Layerwise Aggregation)
熟悉目標(biāo)檢測的FPN網(wǎng)絡(luò)的小伙伴們一定不會對Layerwise Aggregation陌生。一般而言,淺層的網(wǎng)絡(luò)包含的信息更多有關(guān)于物體的顏色、條紋等,深層的網(wǎng)絡(luò)包含的信息更多包含物體的語義特征。正如作者文中提到的那樣:
Features from earlier layers will mainly focus on low level information such as color, shape, are essential for localization, while lacking of semantic information
使用特征融合可以彌補(bǔ)淺層信息和深層信息的不足,更有助于單目標(biāo)追蹤。
本文中的Siamese RPN++利用了ResNet-50在conv3、conv4、conv5的輸出作為輸入。如下圖所示。
也就是這三個輸出分別都有各自的RPN網(wǎng)絡(luò),并不是通過堆疊或者相加進(jìn)行融合。這在代碼中是這樣體現(xiàn)的
先使用改進(jìn)后的resnet50作為特征提取網(wǎng)絡(luò),返回輸出的層 id 為[2,3,4],其實就是conv3、conv4、conv5的輸出。
然后分別對template圖像和需要detection的圖像分別進(jìn)行特征提取。
zf = self.features(template)xf = self.features(detection)事實上,zf 和 xf 并不是單一的特征圖,而是一個列表,每個列表中包含了三個特征圖。
接著,在特征提取結(jié)束后,需要對提取的特征進(jìn)行調(diào)整,代碼中是這樣實現(xiàn)的:
zf = self.neck(zf)xf = self.neck(xf)那么這個neck的定義如下:
AdjustAllLayer(**{'in_channels': [512, 1024, 2048], 'out_channels': [256, 256, 256]})AdjustAllLayer定義如下:
class AdjustLayer(nn.Module):def __init__(self, in_channels, out_channels):super(AdjustLayer, self).__init__()self.downsample = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size=1, bias=False),nn.BatchNorm2d(out_channels),)def forward(self, x):x = self.downsample(x)if x.size(3) < 20:l = 4r = l + 7x = x[:, :, l:r, l:r]return xclass AdjustAllLayer(nn.Module):def __init__(self, in_channels, out_channels):super(AdjustAllLayer, self).__init__()self.num = len(out_channels)if self.num == 1:self.downsample = AdjustLayer(in_channels[0], out_channels[0])else:for i in range(self.num):self.add_module('downsample'+str(i+2),AdjustLayer(in_channels[i], out_channels[i]))def forward(self, features):if self.num == 1:return self.downsample(features)else:out = []for i in range(self.num):adj_layer = getattr(self, 'downsample'+str(i+2))out.append(adj_layer(features[i]))return out可見上面的AdjustAllLayer的作用就是對特征提取網(wǎng)絡(luò)輸出的三個特征圖分別做1x1卷積,調(diào)整所有特征圖的通道數(shù)為256。論文中也有提及:
An extra 1 x 1 convolution layer is appended to each of block outputs to reduce the channel to 256
上述代碼中有個很有趣的forward,即
def forward(self, x):x = self.downsample(x)if x.size(3) < 20:l = 4r = l + 7x = x[:, :, l:r, l:r]return x這么做是為了什么呢?我們發(fā)現(xiàn)原文中提到:
Since the paddings of all layers are kept, the spatial size of the template feature increases to 15, which imposes a heavy computational burden on the correlation module. Thus we crop the center 7 x 7 regions as the template feature where each feature cell can still capture the entire target region.
原來是因為降低運算量所以對template的特征圖進(jìn)行了裁剪,恍然大悟呀!原來原文中的細(xì)節(jié)都在代碼中有所描述,所以我十分推薦大家結(jié)合代碼看論文,這是非常容易進(jìn)行理解的。
特征提取以及所有通道都壓縮至256后,緊接著代碼實現(xiàn)如下:
cls, loc = self.head(zf, xf)其中head定義如下:
self.head = MultiRPN(**{'anchor_num': 5, 'in_channels': [256, 256, 256], 'weighted': True})其中MultiRPN定義如下:
class MultiRPN(RPN):def __init__(self, anchor_num, in_channels, weighted=False):super(MultiRPN, self).__init__()self.weighted = weightedfor i in range(len(in_channels)):self.add_module('rpn'+str(i+2),DepthwiseRPN(anchor_num, in_channels[i], in_channels[i]))if self.weighted:self.cls_weight = nn.Parameter(torch.ones(len(in_channels)))self.loc_weight = nn.Parameter(torch.ones(len(in_channels)))def forward(self, z_fs, x_fs):cls = []loc = []for idx, (z_f, x_f) in enumerate(zip(z_fs, x_fs), start=2):rpn = getattr(self, 'rpn'+str(idx))c, l = rpn(z_f, x_f)cls.append(c)loc.append(l)if self.weighted:cls_weight = F.softmax(self.cls_weight, 0)loc_weight = F.softmax(self.loc_weight, 0)def avg(lst):return sum(lst) / len(lst)def weighted_avg(lst, weight):s = 0for i in range(len(weight)):s += lst[i] * weight[i]return sif self.weighted:return weighted_avg(cls, cls_weight), weighted_avg(loc, loc_weight)else:return avg(cls), avg(loc)(3)深層互相關(guān)Depthwise Cross Correlation
Siamese RPN++中選用了Depth-wise Cross Correlation Layer對Template和Search Region進(jìn)行卷積運算。這么做是為了降低計算量。具體實現(xiàn)過程如下
class DepthwiseXCorr(nn.Module):def __init__(self, in_channels, hidden, out_channels, kernel_size=3, hidden_kernel_size=5):super(DepthwiseXCorr, self).__init__()self.conv_kernel = nn.Sequential(nn.Conv2d(in_channels, hidden, kernel_size=kernel_size, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),)self.conv_search = nn.Sequential(nn.Conv2d(in_channels, hidden, kernel_size=kernel_size, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),)self.head = nn.Sequential(nn.Conv2d(hidden, hidden, kernel_size=1, bias=False),nn.BatchNorm2d(hidden),nn.ReLU(inplace=True),nn.Conv2d(hidden, out_channels, kernel_size=1))def forward(self, kernel, search):kernel = self.conv_kernel(kernel)search = self.conv_search(search)feature = xcorr_depthwise(search, kernel)out = self.head(feature) #維度提升return outclass DepthwiseRPN(RPN):def __init__(self, anchor_num=5, in_channels=256, out_channels=256):super(DepthwiseRPN, self).__init__()self.cls = DepthwiseXCorr(in_channels, out_channels, 2 * anchor_num)self.loc = DepthwiseXCorr(in_channels, out_channels, 4 * anchor_num)def forward(self, z_f, x_f):cls = self.cls(z_f, x_f)loc = self.loc(z_f, x_f)return cls, loc其中xcorr_depthwise定義如下
def xcorr_depthwise(x, kernel):"""depthwise cross correlation"""batch = kernel.size(0)channel = kernel.size(1)x = x.view(1, batch*channel, x.size(2), x.size(3))kernel = kernel.view(batch*channel, 1, kernel.size(2), kernel.size(3))out = F.conv2d(x, kernel, groups=batch*channel)out = out.view(batch, channel, out.size(2), out.size(3))return out實質(zhì)上Depthwise Cross Correlation采用的就是分組卷積的思想,分組卷積可以帶來運算量的大幅度降低,被廣泛用于MobileNet系列網(wǎng)絡(luò)中。
通過上述代碼可以看出,與Siamese RPN網(wǎng)絡(luò)不同,Siamese RPN++提升網(wǎng)絡(luò)通道數(shù)為2k或者4k的操作是在卷積操作( Cross Correlation)之后,而Siamese RPN網(wǎng)絡(luò)是在卷積操作之前,這樣就減少了大量的計算量了。這在DepthwiseXCorr類中的forward中定義出來了,如下:
def forward(self, kernel, search):kernel = self.conv_kernel(kernel)search = self.conv_search(search)feature = xcorr_depthwise(search, kernel)out = self.head(feature) #維度提升return out上面的self.head運算就是升維運算(到2k或者4k),可以看出,其發(fā)生在xcorr_depthwise之后。
最后的最后,網(wǎng)絡(luò)最后輸出的3個cls和loc分支進(jìn)行了按權(quán)重融合。這在MultiRPN的forward定義了,如下:
def forward(self, z_fs, x_fs):cls = []loc = []for idx, (z_f, x_f) in enumerate(zip(z_fs, x_fs), start=2):rpn = getattr(self, 'rpn'+str(idx))c, l = rpn(z_f, x_f)cls.append(c)loc.append(l)if self.weighted:cls_weight = F.softmax(self.cls_weight, 0)loc_weight = F.softmax(self.loc_weight, 0)def avg(lst):return sum(lst) / len(lst)def weighted_avg(lst, weight):s = 0for i in range(len(weight)):s += lst[i] * weight[i]return sif self.weighted:return weighted_avg(cls, cls_weight), weighted_avg(loc, loc_weight)else:return avg(cls), avg(loc)總結(jié)
至此,Siamese RPN++的網(wǎng)絡(luò)結(jié)構(gòu)就講解結(jié)束了,代碼總結(jié)如下:
def forward(self, template, detection):zf = self.features(template) #ResNet-50特征提取xf = self.features(detection)zf = self.neck(zf) #降低維度為256xf = self.neck(xf)cls, loc = self.head(zf, xf) #RPNreturn cls, loc總體的結(jié)構(gòu)圖如下:
圖中右側(cè)的支路中
至此,Siamese RPN++的結(jié)構(gòu)解析也結(jié)束了。
論文翻譯
Abstract
1. Introduction
2. Related Work
3. Siamese Tracking with Very Deep Networks
3.1. Analysis on Siamese Networks for Tracking
3.2. ResNet-driven Siamese Tracking
3.3. Layer-wise Aggregation
3.4. Depthwise Cross Correlation
4. Experimental Results
4.1. Training Dataset and Evaluation
4.2. Implementation Details
4.3. Ablation Experiments
4.4. Comparison with the state-of-the-art
5. Conclusions
總結(jié)
以上是生活随笔為你收集整理的SiameseRPN++分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到一盆屎是什么原因
- 下一篇: SiamBAN论文学习