最近因為項目需要看了一些語義分割(如FCN、U-Net、SegNet等)的論文,然後在github上找了相關的實現代碼。在看代碼的時候發現,訓練階段,代碼作者都將圖片的輸入尺寸固定了,但是按論文裡面的說法,全卷積的目的就是為了能夠接受任意尺寸的輸入,既然這樣,為什麼很多代碼是將輸入尺寸固定的?


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

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

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框架因為設計限制無法實現這樣的功能)。


全卷積架構確實可以任意輸入,但固定輸入大小喂入batch數據更方便。另外,有可能輸入圖片的解析度很大,直接輸入佔用內存,且速度慢。


  1. 沒有全鏈接層的情況下,無論訓練還是測試,輸入尺寸可以是任意的;
  2. 為了提高訓練效率,節省顯存空間,訓練是通常採用固定輸入(變長數據結構浪費空間);
  3. 固定尺寸好做數據shuffle。


  1. 卷積運算中,其輸入就是不限制輸入尺寸的
  2. 代碼實現固定尺寸是因為目前都是基於mini-batch去訓練網路的,在單卡上若batch_size &> 1, 這個mini-batch中的所有輸入必須同尺寸(不然無法構成4-D 張量,僅僅是一個list of 3-D tensor, 這樣是無法GPU並行的)


可能你需要在仔細看一下代碼,理論上尺寸都是不固定的。但從實現角度方便,會按最大長度把比較短的進行補齊,補齊的過程可以用填0等方法。另外,如果想純動態,可以考慮看看tensoflow裏動態rnn的實現


為了並行,一卡內的並行,多卡之間的並行(有時候可以不需要輸入尺寸一樣).語義分割只需要注意輸入尺寸最好,但是目標檢測很多地方都需要保持一樣,所以很麻煩,大多數的實現版本都是一卡一圖,這裡是實現的一個一卡多圖的tensorflow版本https://github.com/kuku-sichuan/FPN_Faster_RCNN


螞蟻跟大象誰的速度快?如果不把兩者縮放到同一個尺度,是沒法判斷的。圖片間的像素對等位置要對齊,不然神經網路沒法對比從而得出規律總結


推薦閱讀:
相關文章