經典論文復現 | PyraNet:基於特徵金字塔網路的人體姿態估計
大咖揭祕Java人都栽在了哪?點選免費領取《大廠面試清單》,攻克面試難關~>>>
過去幾年發表於各大 AI 頂會論文提出的 400 多種演算法中,公開演算法程式碼的僅佔 6%,其中三分之一的論文作者分享了測試資料,約 54% 的分享包含“虛擬碼”。這是今年 AAAI 會議上一個嚴峻的報告。人工智慧這個蓬勃發展的領域正面臨著實驗重現的危機,就像實驗重現問題過去十年來一直困擾著心理學、醫學以及其他領域一樣。最根本的問題是研究人員通常不共享他們的原始碼。
可驗證的知識是科學的基礎,它事關理解。隨著人工智慧領域的發展,打破不可復現性將是必要的。為此,PaperWeekly 聯手百度 PaddlePaddle 共同發起了本次論文有獎復現,我們希望和來自學界、工業界的研究者一起接力,為 AI 行業帶來良性迴圈。
作者丨黃澤宇
學校丨深圳大學
研究方向丨計算機圖形學、深度學習
Learning Feature Pyramids for Human Pose Estimation是發表在 ICCV 2017 的一篇有關人體姿態估計的論文,提出利用特徵金字塔來進行人體姿勢預測。作者是 Wei Yang,香港中文大學博士生。
論文復現程式碼:
http://aistudio.baidu.com/aistudio/#/projectdetail/24019
人體姿態估計介紹
人體姿態估計是計算機視覺領域一個較有挑戰性的任務,問題的輸入是一張圖片,輸出是圖片中的人體各個關節點的位置 ,如下圖所示。人體姿態任務可以是單人姿態估計,或者是多人姿態估計,而本文給出的方法是單姿態估計,即一張圖片只預測一個人的姿態。
在本文之前,在人體姿態估計效果較好的工作是 2016 年 Alejandro Newell 等人的Stacked Hourglass Networks for Human Pose Estimation[1],而本文的網路結構是在此之上的改進, 因此 Hourglass Network 的相關設計對理解本文網路非常重要。
重要工作介紹
Stacked Hourglass Network
Stacked Hourglass Network 是一種堆疊沙漏型的全卷積網路,能夠很好地捕捉圖片的多尺度特徵,並由粗到細地預測關節點位置的熱力圖 Heatmap,即關節點出現在各個位置的概率。最終的關節點的位置預測結果取 Heatmap 中概率最大的索引。
網路的基本結構如下圖所示,可以看到網路後面都是由一個個沙漏型的結構堆疊而成的。
Hourglass Module
沙漏模組則是一種編碼器-解碼器加短接層的設計,其動機是捕獲多尺度資訊。因為對於人體的各個不同部位的大小尺度是不一樣的,通過短接層將不同尺度下的特徵圖加入到解碼階段可以獲得更尺度的資訊,從而得到更精準的預測。
Hourglass 模組和 Networks 中的白色方塊表示的都是類似於 ResNet 中的殘差模組[2],其作用是在保留原特徵資訊的同時進一步提取更深層次的特徵,同時也能使得網路變得更深又不至於梯度消失。
像堆疊殘差模組一樣堆疊沙漏模組就得到了堆疊沙漏網路。值得注意的是,沙漏模組的輸入和輸出大小可以是一樣的,也就是說在每個沙漏模組之後都可以進行最終結果的預測並計算損失,起到中間監督作用。
另外,上層模組的預測結果也可以作為下層模組的輸入,從而更好的幫助下層模組進行預測,因此預測結果也可以通過 1*1 的卷積重新加入到原來的特徵中,進行由粗糙到細緻的估計。
改進方向
為了捕捉不同尺度的,除了使用短接層,還可以使用不同的卷積核同時進行卷積,再將得到的特徵進行疊加,比如Inception 模組[3]。Inception 模組通過使用不同大小的卷積核以及 1*1 的卷積使得網路能夠捕捉不同解析度的特徵,並減少引數數量。
而在減少引數數量方面,ResNeXt又在 ResNet 更進一步[4],將初始的輸入分裂成多條分支進行卷積,其中每條分支的卷積核大小都是一樣的。
另外,使用空洞卷積也可以獲得多尺度的特徵[5],空洞卷積是通過使用具有間隔的卷積核在特徵圖上進行卷積從而避免對原特徵圖進行下采樣的步驟。
本文方法
Pyramid Residual Modules (PRMs)
可能是受到上述三種模組的啟示,本文作者設計出了四種特徵金字塔模組如下圖所示。
PRM-A 是在原先的殘差模組的分支基礎上,直接增加多個解析度的分支,其解析度的不同主要是通過下采樣實現的,而由於殘差模組的結果需要將不同分支的結果相加,因此下采樣後的特徵要通過上取樣恢復原來解析度。
PRM-B 則是將 PRM-A 中不同解析度的分支開始的 1*1 卷積進行引數共享,從而減少引數數量。
PRM-C 則是將 PRM-B 中多解析度特徵的相加改為了串聯,由於串聯後的特徵通道數與原來不同,因此可能需要再進行一個 1*1 的卷積對齊特徵通道後再與原特徵相加。
PRM-D 則是使用空洞卷積代,替下采樣和上取樣得到多尺度的特徵。
根據後面的實驗結果可以看到在準確率、引數數量和複雜度的權衡之下,PRM-B 模組是較好的選擇。
Output Variance Accumulation
除了上述的改進,本文作者還提到原始的殘差模組有輸出方差積累的問題,當堆疊多個殘差塊時,將原始特徵直接與卷積後的特徵相加時會有較大的方差,通過對原始特徵新增一個 Bn-ReLu-Conv 操作可以較好的控制這個問題。
PyraNet
本文網路框架使用 Stacked Hourglass Network 的基本框架,但將其中的殘差模組都替換成了上述特徵金字塔模組 PRMs,網路結構圖如下。
再談初始化
網路引數的初始化對網路的訓練以及結果會有一定影響,為了使得網路更順利的開始訓練,有許多不同的初始化方案,其中較常見的即是Xavier[6]。
Xavier
Xavier 的提出者指出,第 i 層的引數方差從正向和反向傳播的角度考慮,應分別滿足如下式子。其中的 n_i 和 n_(i+1) 分別是該層輸入的元素個數以及輸出的元素個數。
折衷考慮,Xavier 初始化的引數方差同時考慮輸入和輸出元素個數,即將上述兩式相加後得到的結果。
Initialization Multi-Branch Networks
本文作者考慮到提出 Xavier 時的大部分網路並沒有多條分支,因此對多分支網路的初始化方案重新考量,得出瞭如下的更泛化的結果。其中 l 表示網路層數,C_i 和 C_o 分別表示輸入和輸出分支數,n_i 和 n_o 分別表示各輸入和輸出分支的元素個數,α 根據啟用函式有不同取值,ReLu 取 0.5。即從前向和反向傳播的角度考慮,各層引數初始化時的方差應與各輸入分支合併前的總元素個數、各輸出分支分離後的總元素個數有關。
折衷考慮,多分支引數初始化的方差在文中應為滿足如下式子。注意到 α 帶有平方,特殊情況下,若 α 取 0.5,輸入輸出均只有 1 條分支,結果與 Xavier 不一致,因此筆者認為 α 不應取平方,這樣在上述情況下仍能 Xavier 保持一致,作為 Xavier 的泛化。
實驗結果與分析
人體姿態估計準確性
本文在 MPII 和 LSP、LSPEt 資料集上進行訓練,使用 PCK (Percentage of Correct Keypoints) 和 PCKh 進行評估,PCK 計算估計的關鍵點與真實值間的歸一化距離小於設定閾值的比例,PCKh 則以頭部長度為參考的歸一化。實驗結果如下,可以看到使用 PRM-B 的 PyraNet 在所有對比的方法中都取得了最好的準確率。
控制變數比較
在網路結構的對比實驗中可以看到,相比於 Baseline 即普通的 Stacked Hourglass Network,PyraNet 使用的特徵金字塔和多分支引數初始化方案都有提高結果的準確性。
其他實驗
本文作者使 PRM 替代相應網路的殘差模組在 CIFAR-10 上進行訓練,得到最低的 Top-1 測試誤差,但網路的大小和運算量稍有增加。
總結
本文的主題雖然是人體姿態估計,但提出的改進和創新較為普適,在其他任務上也可以進嘗試。主要思想有如下:
1. 本提出了特徵金字塔殘差模組,增強了深度神經網路的尺度不變性;
2. 本文提出了多分支引數初始化方案,使得網路訓練更順利;
3. 本文提出了通過在短接層增加一次卷積來減少殘差模組輸出方差積累的問題。
PaddleFluid模型復現
注:程式碼中的 bn_relu_convn*n 是對依次使用 PaddleFluid 的 batch norm、relu 和卷積核為 n 的 conv2d 的封裝。
1. 定義特徵金字塔模組:特徵金字塔首先將輸入進行不夠規模的下采樣,再進行特徵提取,然後將下采樣後提取的特徵上取樣回輸入大小。原文使用了 Fraction pool 進行下采樣,使得下采樣更加平滑,而 PaddleFluid 並沒有實現 Fraction pool,故只能使用簡單的二線性插值 Resize bilinear 進行代替。
defpyramid(input,out_ch,ngroup):output_res=input.shape[-1]scale_base=pow(2.0,1.0/ngroup)#extractfeaturesindifferentresolutionfeatures=[]foriinrange(1,ngroup+1):#subsamplescale=round(1.0/pow(scale_base,i),4)feature=resize_bilinear(input,scale=scale)#extractthefeaturefeature=bn_relu_conv3x3(feature,out_ch)#upsamplefeature=resize_bilinear(feature,out_shape=[output_res,output_res])features.append(feature)#sumupfeaturesoutput=features[0]foriinrange(1,ngroup):output=elementwise_add(output,features[i])returnoutput
output_res=input.shape[-1]
scale_base=pow(2.0,1.0/ngroup)
#extractfeaturesindifferentresolution
features=[]
foriinrange(1,ngroup+1):
#subsample
scale=round(1.0/pow(scale_base,i),4)
feature=resize_bilinear(input,scale=scale)
#extractthefeature
feature=bn_relu_conv3x3(feature,out_ch)
#upsample
feature=resize_bilinear(feature,out_shape=[output_res,output_res])
features.append(feature)
#sumupfeatures
output=features[0]
foriinrange(1,ngroup):
output=elementwise_add(output,features[i])
returnoutput
2. 定義 PRM 特徵金字塔殘差塊:在一般的 ResNet 殘差模組的基礎上進行擴充套件,在進行完 3*3 的卷積後再加入一個特徵金字塔,這裡實現了上述的 PRM-B,即所有特徵金字塔分支使同一個輸入。
defconv_block(input,out_ch,type='prm-b',base_width=6,cardinality=30):#1*1convconv_out=bn_relu_conv1x1(input,out_ch//2)#3*3convconv_out=bn_relu_conv3x3(conv_out,out_ch//2)iftype=='res':output=bn_relu_conv1x1(conv_out,out_ch)returnoutputeliftype=='prm-b':pyra_depth=out_ch//base_widthngroup=cardinality#extractfeaturepyramid#1branchin,ngroupbranchesoutpyra_out=bn_relu_conv1x1(input,pyra_depth,in_branches=1,out_branches=ngroup)pyra_out=pyramid(pyra_out,pyra_depth,ngroup)#ngroupbrachesin,1branchoutpyra_out=bn_relu_conv1x1(pyra_out,out_ch//2,in_branches=ngroup,out_branches=1)#2branchesin,1branchoutoutput=elementwise_add(conv_out,pyra_out)output=bn_relu_conv1x1(output,out_ch,in_branches=2,out_branches=1)returnoutput#TODO:PRM-A/PRM-C/PRM-Dreturnoutput
#1*1conv
conv_out=bn_relu_conv1x1(input,out_ch//2)
#3*3conv
conv_out=bn_relu_conv3x3(conv_out,out_ch//2)
iftype=='res':
output=bn_relu_conv1x1(conv_out,out_ch)
returnoutput
eliftype=='prm-b':
pyra_depth=out_ch//base_width
ngroup=cardinality
#extractfeaturepyramid
#1branchin,ngroupbranchesout
pyra_out=bn_relu_conv1x1(input,pyra_depth,in_branches=1,out_branches=ngroup)
pyra_out=pyramid(pyra_out,pyra_depth,ngroup)
#ngroupbrachesin,1branchout
pyra_out=bn_relu_conv1x1(pyra_out,out_ch//2,in_branches=ngroup,out_branches=1)
#2branchesin,1branchout
output=elementwise_add(conv_out,pyra_out)
output=bn_relu_conv1x1(output,out_ch,in_branches=2,out_branches=1)
returnoutput
#TODO:PRM-A/PRM-C/PRM-D
returnoutput
3. 按照 Stacked Hourglass Network 的方式定義沙漏模組和堆疊沙漏模組(程式碼略)。值得注意的是 Hourglass 是一個遞迴的結構,因此可以使用遞迴函式來建立網路結構。
4. 定義初始化方案 Branch initializer,筆者使用 Xavier 進行泛化,加入了輸入輸出分支數。
defbranch_initializer(in_units=1,out_units=1,in_branches=1,out_branches=1,act='relu',uniform=False,seed=0):#itmightbealphainsteadofalpha**2informula.15#inthiscase,whenin_branches=out_branches=1,itdegenratestoXavieralphax2=0.5*2ifact=='relu'else1.0*2fan_in=in_units*in_branches*alphax2fan_out=out_units*out_branches*alphax2returnXavier(uniform,fan_in,fan_out)
#itmightbealphainsteadofalpha**2informula.15
#inthiscase,whenin_branches=out_branches=1,itdegenratestoXavier
alphax2=0.5*2ifact=='relu'else1.0*2
fan_in=in_units*in_branches*alphax2
fan_out=out_units*out_branches*alphax2
returnXavier(uniform,fan_in,fan_out)
5. 網路訓練:實驗使用 PaddleFluid v0.14 環境,Titan Xp 單 GPU,在 MPII 資料集上進行訓練,訓練圖片 20k 張,測試圖片 2k 張,訓練時進行了資料增強。PyraNet 堆疊沙漏數 nstack=2,殘差模組使用PRM-B結構,特徵金字塔分支數 cardinality=4,通道基數 base_width=9,批大小 batch_size=8,訓練輪述 epoch=150,使用 Adam 優化器,學習率 2.5*10^-4 且每 10 輪衰減至 90%,初始化使用 Xavier 泛化後的多分支初始化。對照組除了殘差模組為普通 res 模組其他引數均相同。
6. 實驗結果:本次復現結果使用 PRM-B 模組的 PyraNet 並沒有比使用 Res 模組的堆疊沙漏網路效果要好。準確率使用 [email protected] 進行評估。
準確率曲線如下:使用 PRM-B 由於發生了過擬合,在 Epoch=110 處進行了早停,而使用 Res 則在 Epoch=110 時接近收斂。
7. 結果對比分析:復現結果本應是使用 PRM-B 模組的 PyraNet 要好於使用 Res 模組的堆疊沙漏網路,但結果卻相反。
在訓練時發現一個問題,即 PyraNet 很容易過擬合,調整多次都沒有得到很好的結果,而普通的堆疊沙漏網路訓練則非常穩定。推測是由於加入了特徵金字塔結構,分支數太多,網路變得複雜,所以難以訓練。由於時間關係,也沒有將網路除錯到最好狀態。
8. 結果視覺化:下面是幾個使用 Res 模組的堆疊沙漏網路實驗結果的視覺化,可以看到預測出了基本的人體姿勢。
關於PaddlePaddle
這是筆者第一次接觸並復現有關人體姿態預測的論文,也是首次嘗試使用 PaddlePaddle,並沒有取得很好的結果。
人體姿態檢測相比於簡單的圖片識別、生成,資料處理過程更復雜,計算量更大,網路結構一旦變得複雜,就會變得難以訓練。同時網路變得更大引數數量急劇增加,只能用很小的批大小進行訓練,也容易使得網路陷入區域性最小值。
而 PaddlePaddle 則是極具潛力的深度學習框架,很容易上手,目前還只是實現了最基本、最常見的一些操作,對於實現純卷積網路來說非常便利,期待未來版本有更強大的功能和更好的使用體驗。
參考文獻
[1].Newell A, Yang K, Deng J. Stacked Hourglass Networks for Human Pose Estimation[J]. 2016:483-499.
[2]. He K, Zhang X, Ren S, et al. Deep Residual Learning for Image Recognition[C]// IEEE Conference on Computer Vision and Pattern Recognition. IEEE Computer Society, 2016:770-778.
[3]. Szegedy C, Liu W, Jia Y, et al. Going deeper with convolutions[J]. 2014:1-9.
[4]. Xie S, Girshick R, Dollar P, et al. Aggregated Residual Transformations for Deep Neural Networks[J]. 2016:5987-5995.
[5]. Chen L C, Papandreou G, Kokkinos I, et al. DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs.[J]. IEEE Transactions on Pattern Analysis & Machine Intelligence, 2018, 40(4):834-848.
[6]. Glorot X, Bengio Y. Understanding the difficulty of training deep feedforward neural networks[J]. Journal of Machine Learning Research, 2010, 9:249-256.
來源:PaperWeekly
本文分享 CSDN - 飛槳PaddlePaddle。
如有侵權,請聯絡 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。