關於輸入圖像Size不固定的討論


關於輸入圖像Size不固定的討論

【轉】對於大小可變的輸入,深度學習模型如何處理?

轉自知乎一個小問題:深度學習模型如何處理大小可變的輸入

前幾天在學習花書的時候,和小伙伴們討論了“CNN如何處理可變大小的輸入”這個問題。進一步引申到“對於大小可變的輸入,深度學習模型如何處理?”這個更大的問題。因為這里面涉及到一些概念,我們經常搞混淆,比如RNN單元明明可以接受不同長度的輸入,但我們卻在實際訓練時習慣於使用padding來補齊;再比如CNN無法直接處理大小不同的輸入,但是去掉全連接層之后又可以。因此,這里我想總結一下這個問題:

  1. 究竟什么樣的模型結構可以處理可變大小的輸入?
  2. 若模型可處理,那該如何訓練/預測?
  3. 若模型不可處理,那該如何訓練/預測?

一、什么樣的網絡結構可以處理可變大小的輸入?

直接上結論(我個人總結的,不一定對/全面,歡迎指正):

當某個網絡(層或者單元)是以下三種情況之一時:
只處理局部的信息
② 網絡是無參數化的;
參數矩陣跟輸入大小無關
這個網絡就可以處理大小可變的輸入。

下面我分別從幾個經典的網絡結構來回應上面的結論:

CNN

首先講講CNN。CNN中的卷積層通過若干個kernel來獲取輸入的特征,每個kernel只通過一個小窗口在整體的輸入上滑動,所以不管輸入大小怎么變化,對於卷積層來說都是一樣的。那為什么CNN不能直接處理大小不同的圖片呢?是因為一般的CNN里都會有Dense層,Dense層連接的是全部的輸入,一張圖片,經過卷積層、池化層的處理后,要把全部的單元都“壓扁(flatten)”然后輸入給Dense層,所以圖片的大小,是影響到輸入給Dense層的維數的,因此CNN不能直接處理。但是,有一種網絡叫FCNN,即Fully Convolutional Neural Network,是一種沒有Dense層的卷積網絡,那么它就可以處理大小變化的輸入了。

SSP

CNN處理大小可變的輸入的另一種方案是使用特殊的池化層——SSP(Spatial Pyramid Pooling),即“空間金字塔池化”,最初由何愷明團隊提出。這種池化層,不使用固定大小的窗口,而是有固定大小的輸出。比方不管你輸入的網格是多大,一個固定輸出2×2的SSP池化,都將這個輸入網絡分成2×2的區域,然后執行average或者max的操作,得到2×2的輸出。

SSP和FCNN在《花書》中都有展示:

img

圖中,SSP通過一個固定輸出大小的pooling,擁有了處理可變大小輸入的能力。

FCNN

FCNN,則是去掉了Dense層,使用kernel的數量來對應類別的數量(如圖中例子使用了1000個kernel來對應1000個類),最后使用一個全局池化——GAP(Global Average Pooling),出自Inception-V3,其將每個kernel對應的feature map都轉化成一個值,就形成了一個1000維的向量,就可以直接使用softmax來分類了,不必使用Dense層了。通過這連個特殊的卷積層和池化層,FCNN也擁有了處理可變大小輸入的能力。

Transformer

Transformer也可以處理長度可變的輸入,這個問題在知乎上有討論,可惜我都沒太看明白。比如邱錫鵬老師講的,是因為“self-attention的權重是是動態生成的”,我不懂權重怎么個動態法?再例如許同學講“Transformer是通過計算長度相關的self-attention得分矩陣來處理可變長數據”,這個直接從字面上也不太好理解。

在我看來,這跟self-attention壓根沒關系。Transformer中的self-attention是無參數化的,從attention層輸入,到輸出加權后的向量表示,不需要任何的參數/權重,因此self-attention自然可以處理長度變化的輸入。Transformer中的參數都來源於Dense層,包括一些純線性映射層(projection layer)和position-wise FFN(feed-forward layer)。搞清楚這些Dense層的操作,才能理解為何Transformer可以處理變長輸入。

我們先看看Transformer的結構:

img

這里我們重點關注encoder部分,即左半部分。但是看這個圖,並不能很好的理解為什么可以處理長度變化的輸入。為此,我花了一個簡陋的草圖(省略了多頭,省略了Add&Norm,簡化了論文中的FFN),來更細致地查看encoder部分:

img

我們不必展開看self-attention的部分,因為它就是讓所有的向量,兩兩之間都計算attention權重然后再分別加權求和得到新的一組向量,中間沒有任何的參數,向量的維度、數量都沒有任何的變化。

整個encoder,涉及到可學習參數的只有projection layer和point-wise feed-forward layer,其中前者只是為了把每個輸入token的向量的維度改變一下(圖中,從d變為p),后者則是對每一個token,都使用同一個Dense層進行處理,把每個向量的p維轉化為m維。所以,所有的參數,都跟序列的長度n沒有任何關系,只要模型參數學好了,我們改變序列長度n也照樣可以跑通

這里唯一值得展開看看的,就是這里的point-wise feed-forward layer,這其實就是普普通通的Dense層,但是處理輸入的方式是point-wise的,即對於序列的每個step,都執行相同的操作:

img

一開始我不理解,為什么明明有一個Dense層接在attention層后面還能處理可變長的輸入。后來發現這不是普通的Dense,而是point-wise的,相當於一個recurrent的Dense層,所以自然可以處理變化的長度。

二、若模型可處理大小變化的輸入,那如何訓練和預測?

通過了第一部分的討論,我們知道了,什么網絡結構可以處理大小變化的輸入。

訓練

但是我們在訓練時,為了加速訓練,往往會將一批數據同時輸入到模型中進行計算、求導。那同一批數據,要喂給網絡,我們必須把它組織成矩陣的形式,那矩陣的每一行/列自然維度需要相同。所以我們必須讓同一個batch中的各個樣本長度/大小一致

最常用的方法,就是padding,我們通過padding補零,把同一個batch中的所有樣本都變成同一個長度,這樣就可以方便我們進行批量計算了。對於那些padded values,也就是補的零,我們可以使用masking機制來避免模型對這些值進行訓練。

實際上,有研究指出,我們可以對一批樣本(以NLP為例),做一個長度的排序,然后分組,每一組使用不同的max length超參數,這樣可以節省padding的使用次數,從而提高訓練效率(論文我不知道是哪個,聽別人說的,知道的同學可以告訴我),文后的連接里,我找到了一個keras的示例代碼,可供參考。

當然,如果我們設置batch size=1,那就不需要padding了,就可以開心的把各種不同長度的數據都丟進去訓練了。

預測

在預測時,如果我們想進行批量預測,那也是必須通過padding來補齊,而如果是單條的預測,我們則可以使用各種長度。

三、若模型不可處理大小變化的輸入,那如何訓練與預測?

訓練

不可接受,那我們就只能老老實實地把所有輸入都規范成同一大小,比如經典的CNN網絡,我們會吧所有的圖片都進行resize,或者padding。

這里需要提一下transfer learning的場景,我們經常需要直接拿來別人在ImageNet上訓練好的牛逼網絡來進行finetune,那問題來了,比人訓練CNN的時候,肯定有自己固定好的輸入大小,跟我們要用的場景往往不一致,那怎么辦?只要做過CNN的transfer learning的同學應該都有經驗:我們需要把別人的網絡的最后面的Dense層都去掉!因為前面分析過了,Dense層才是讓CNN無法處理可變大小輸入的罪魁禍首,Dense一拿掉,剩下的卷積層啊池化層啊都可以快樂地遷移到各種不同大小的輸入上了。

其他的辦法,就是改造模型結構了,例如SSP,FCNN都是對經典CNN的改造。

預測

預測時,在這種情況下,我們也只能使用統一的輸入大小,不管是單條還是批量預測。

參考鏈接:

  1. https://ai.stackexchange.com/questions/15524/why-would-you-implement-the-position-wise-feed-forward-network-of-the-transforme
  2. https://stackoverflow.com/questions/44611006/timedistributeddense-vs-dense-in-keras-same-number-of-parameters/44616780#44616780

全卷積FCN

全卷積的目的就是為了能夠接受任意尺寸的輸入

全連接層要求固定的輸入維度。而不同大小的圖像,卷積模塊(卷積+非線性激活+池化)輸出的特征映射維度是不一樣的。而你提到的FCN、U-Net、SegNet,都是全卷積神經網絡(fully convolutional neural network)。實際上,FCN的全稱就是Full Convolutional Networks(全卷積網絡)。這些網絡用卷積層替換掉了全連接層,這就支持了任意大小的輸入圖像。

imgimg SegNet架構

比如,上圖為SegNet架構,可以看到,其中有卷積層、池化層、上采樣層、Softmax層,就是沒有FC(全連接)層。

順便提下,要支持任意尺寸輸入圖像,全卷積神經網絡不是唯一的選擇。比如,可以用全局平均池化(Global Average Pooling)層替換全連接層(Inception-V3),或者在卷積模塊和全連接層之間加一個空間金字塔池化(Spatial Pyramid Pooling)層,整理一下卷積模塊的輸出,再傳給全連接層。

訓練階段,代碼作者都將圖片的輸入尺寸固定了

這個並不是模型架構本身的限制,而是工程上的一些因素(比如,為了訓練效率,同一mini-batch中的圖像大小必須一樣),或者說,是實現上的簡單性。

通常情況下,你並不需要操心這個問題,因為這只是訓練階段。很多圖像數據集中的圖像都是統一的,即便不統一,你在傳給網絡前預處理一下也不是什么難事。這些模型架構確實具有支持任意尺寸圖像的能力,但在訓練階段你不一定要利用這個能力。可以到測試階段再發揮它支持任意尺寸圖像的優勢。

還有就是把batch大小改到1,也就是每次訓練一張圖像。比如,MXNet上的FCN實現FCN-xs就是這么干的,訓練階段的batch_size = 1。PyTorch上的FCN實現pytorch-fcn 和TensorFlow上的FCN實現tensor_fcn都可以將batch_size設為1,從而支持使用不同大小的圖像進行訓練。

理論上說,既然只是限制同一mini-batch大小都是一樣,那么可以根據訓練圖像的不同大小進行分組,將相同大小的圖像分到同一個mini-batch中進行訓練。但是這比較復雜,因為據我所知主流框架的數據加載默認不支持這樣的功能,可能需要自行實現(當然前提是defined-by-run框架,defined-and-run框架因為設計限制無法實現這樣的功能)。

為何pytorch預訓練的resnet模型對輸入圖片的大小無要求?

AdaptiveAvgPool2d

答:實際上就是當前的resnet實現已經使用了一個自適應池化層。

img

CNN中如果圖片的長寬差異太大會有什么影響呢?如果有怎么解決呢?

  • answer1:

    僅就代碼而言,沒什么問題,總是能跑的。

    不要padding ,差距50倍,padding 完了等於就是一個大黑方塊中間一條細線,除了浪費算力什么也得不到。

    這種情況最大的問題在於感受野會非常受限,一般圖片通過多次下采樣來增大感受野,一般是下采樣三到四次。這樣的話窄邊的信息可能直接就采沒了,經不起幾次下采樣。

    但同時長邊那么長,感受野只能覆蓋一小截,太局限了,上下文信息不足,最終效果也不會好。要增大長邊的感受野就得瘋狂下采樣,來個五六層比如,但窄邊又不允許……所以確實是一個很尷尬的局面。

    稍微聯想一下,你這個問題和車道線檢測其實非常類似,都是長長的帶狀分布,所以可以直接使用車道線檢測的思路解決,也就是scnn:

    imgimg

    這篇文章解決的就是你這個問題,大概思路是從各個方向把信息融合在一起,充分的感受上下文信息,文章如下:

    Spatial As Deep: Spatial CNN for Traffic Scene Understanding

    Transformer是如何處理可變長度數據的?

占個坑吧,Transformer的知識點還是有點模糊不清。

在目標檢測中如何解決小目標的問題?

在深度學習目標檢測中,特別是人臉檢測中,由於分辨率低、圖像模糊、信息少、噪聲多,小目標和小人臉的檢測一直是一個實用和常見的難點問題。然而,在過去幾年的發展中,也出現了一些提高小目標檢測性能的解決方案。本文將對這些方法進行分析、整理和總結。

解決方案一:圖像金字塔和多尺度滑動窗口檢測

一開始,在深學習方法成為流行之前,對於不同尺度的目標,通常是從原始圖像開始,使用不同的分辨率構建圖像金字塔,然后使用分類器對金字塔的每一層進行滑動窗口的目標檢測。

圖片

在著名的人臉檢測器MTCNN中,使用圖像金字塔法檢測不同分辨率的人臉目標。然而,這種方法通常是緩慢的,雖然構建圖像金字塔可以使用卷積核分離加速或簡單粗暴地縮放,但仍需要做多個特征提取,后來有人借其想法想出一個特征金字塔網絡FPN,在不同層融合特征,只需要一次正向計算,不需要縮放圖片。

解決方案二:簡單,粗暴和可靠的數據增強

通過增加訓練集中小目標樣本的種類和數量,也可以提高小目標檢測的性能。有兩種簡單而粗糙的方法:

  • 針對COCO數據集中含有小目標的圖片數量較少的問題,使用過采樣策略,即Oversampling;
  • 針對同一張圖片中小目標數量少的問題,使用分割mask切出小目標圖像,然后使用復制和粘貼方法(當然,再加一些旋轉和縮放)。

在Anchor策略方法中,如果同一幅圖中有更多的小目標,則會匹配更多的正樣本。與ground truth物體相匹配的不同尺度anchor示意圖,小的目標匹配到更少的anchor。為了克服這一問題,我們提出通過復制粘貼小目標來人工增強圖像,使訓練過程中有更多的anchor與小目標匹配。

解決方案三:特征融合FPN

不同階段的特征圖對應不同的感受野,其所表達的信息抽象程度也不同。

淺層特征圖感受野小,更適合檢測小目標,深層特征圖較大,更適合檢測大目標。因此,有人提出將不同階段的特征映射整合在一起來提高目標檢測性能,稱之為特征金字塔網絡FPN。

圖片

  • (a) 利用圖像金字塔建立特征金字塔。特征的計算是在每個圖像的尺度上獨立進行的,這是很緩慢的。
  • (b) 最近的檢測系統選擇只使用單一尺度的特征以更快地檢測。
  • (c) 另一種選擇是重用由ConvNet計算出的金字塔特征層次結構,就好像它是一個特征圖金字塔。
  • (d)特征金字塔網絡(FPN)如圖所示,特征圖用藍色輪廓線表示,較粗的輪廓線表示語義上較強的特征。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM