圖像數(shù)據(jù)格式定義了一批圖片數(shù)據(jù)的存儲順序呛牲。在調(diào)用 TensorFlow API 時會經(jīng)常看到 data_format 參數(shù):
data_format 默認(rèn)值為 "NHWC",也可以手動設(shè)置為 "NCHW"茬末。這個參數(shù)規(guī)定了 input Tensor 和 output Tensor 的排列方式银亲。
data_format 設(shè)置為 "NHWC" 時慢叨,排列順序?yàn)?[batch, height, width, channels];
設(shè)置為 "NCHW" 時务蝠,排列順序?yàn)?[batch, channels, height, width]拍谐。
其中 N 表示這批圖像有幾張,H 表示圖像在豎直方向有多少像素馏段,W 表示水平方向像素數(shù)轩拨,C 表示通道數(shù)(例如黑白圖像的通道數(shù) C = 1,而 RGB 彩色圖像的通道數(shù) C = 3)毅弧。為了便于演示气嫁,我們后面作圖均使用 RGB 三通道圖像。
兩種格式的區(qū)別如下圖所示:
NCHW 中够坐,C 排列在外層寸宵,每個通道內(nèi)像素緊挨在一起,即 'RRRRRRGGGGGGBBBBBB' 這種形式元咙。
NHWC 格式梯影,C 排列在最內(nèi)層,多個通道對應(yīng)空間位置的像素緊挨在一起庶香,即 'RGBRGBRGBRGBRGBRGB' 這種形式甲棍。
如果我們需要對圖像做彩色轉(zhuǎn)灰度計(jì)算,NCHW 計(jì)算過程如下:
即 R 通道所有像素值乘以 0.299赶掖,G 通道所有像素值乘以 0.587感猛,B 通道所有像素值乘以 0.114,最后將三個通道結(jié)果相加得到灰度值奢赂。
相應(yīng)地陪白,NHWC 數(shù)據(jù)格式的彩色轉(zhuǎn)灰度計(jì)算過程如下:
輸入數(shù)據(jù)分成多個(R, G, B) 像素組,每個像素組中 R 通道像素值乘以 0.299膳灶,G 通道像素值乘以 0.587咱士,B 通道像素值乘以 0.114 后相加得到一個灰度輸出像素。將多組結(jié)果拼接起來得到所有灰度輸出像素轧钓。
以上使用兩種數(shù)據(jù)格式進(jìn)行 RGB -> 灰度計(jì)算的復(fù)雜度是相同的序厉,區(qū)別在于訪存特性。通過兩張圖對比可以發(fā)現(xiàn)毕箍,NHWC 的訪存局部性更好(每三個輸入像素即可得到一個輸出像素)弛房,NCHW?則必須等所有通道輸入準(zhǔn)備好才能得到最終輸出結(jié)果,需要占用較大的臨時空間霉晕。
在 CNN 中常常見到 1x1 卷積(例如:用于移動和嵌入式視覺應(yīng)用的 MobileNets)庭再,也是每個輸入 channel 乘一個權(quán)值捞奕,然后將所有 channel 結(jié)果累加得到一個輸出 channel。如果使用 NHWC 數(shù)據(jù)格式拄轻,可以將卷積計(jì)算簡化為矩陣乘計(jì)算颅围,即?1x1 卷積核實(shí)現(xiàn)了每個輸入像素組到每個輸出像素組的線性變換。
TensorFlow 為什么選擇 NHWC 格式作為默認(rèn)格式恨搓?因?yàn)樵缙陂_發(fā)都是基于 CPU院促,使用 NHWC 比 NCHW 稍快一些(不難理解,NHWC 局部性更好斧抱,cache 利用率高)常拓。
NCHW 則是 Nvidia cuDNN 默認(rèn)格式,使用 GPU 加速時用 NCHW 格式速度會更快(也有個別情況例外)辉浦。
最佳實(shí)踐:設(shè)計(jì)網(wǎng)絡(luò)時充分考慮兩種格式弄抬,最好能靈活切換,在 GPU 上訓(xùn)練時使用 NCHW 格式宪郊,在 CPU 上做預(yù)測時使用 NHWC 格式掂恕。
參考:
【1】 https://www.tensorflow.org/performance/performance_guide