CNN中卷積層的計算細節

前幾天在看CS231n中的CNN經典模型講解時,花了一些時間才搞清楚卷積層輸入輸出的尺寸關係到底是什麼樣的,現總結如下。(可以參照我畫的題圖理解卷積層的運算)

卷積層尺寸的計算原理

  • 輸入矩陣格式:四個維度,依次為:樣本數、圖像高度、圖像寬度、圖像通道數
  • 輸出矩陣格式:與輸出矩陣的維度順序和含義相同,但是後三個維度(圖像高度、圖像寬度、圖像通道數)的尺寸發生變化。
  • 權重矩陣(卷積核)格式:同樣是四個維度,但維度的含義與上面兩者都不同,為:卷積核高度、卷積核寬度、輸入通道數、輸出通道數(卷積核個數)
  • 輸入矩陣、權重矩陣、輸出矩陣這三者之間的相互決定關係
    • 卷積核的輸入通道數(in depth)由輸入矩陣的通道數所決定。(紅色標註)
    • 輸出矩陣的通道數(out depth)由卷積核的輸出通道數所決定。(綠色標註)
    • 輸出矩陣的高度和寬度(height, width)這兩個維度的尺寸由輸入矩陣、卷積核、掃描方式所共同決定。計算公式如下。(藍色標註)

 begin{cases} height_{out} &= (height_{in} - height_{kernel} + 2 * padding) ~ / ~ stride + 1[2ex] width_{out} &= (width_{in} - width_{kernel} + 2 * padding) ~ / ~ stride + 1 end{cases}

* 註:以下計算演示均省略掉了 Bias ,嚴格來說其實每個卷積核都還有一個 Bias 參數。

標準卷積計算舉例

以 AlexNet 模型的第一個卷積層為例,

- 輸入圖片的尺寸統一為 227 x 227 x 3 (高度 x 寬度 x 顏色通道數),

- 本層一共具有96個卷積核,

- 每個卷積核的尺寸都是 11 x 11 x 3。

- 已知 stride = 4, padding = 0,

- 假設 batch_size = 256,

- 則輸出矩陣的高度/寬度為 (227 - 11) / 4 + 1 = 55

 begin{matrix} & mathbf{Batch} & mathbf{Height} && mathbf{Width} && mathbf{In~Depth} && mathbf{Out~Depth}[2ex] mathbf{Input} & quadquad 256 quadquad times & color{blue}{227} & times & color{blue}{227} & times & color{red}{3} [2ex] mathbf{Kernel} &quadquadquadquadquad & color{blue}{11} & times & color{blue}{11} & times & color{red}{3} & times & color{green}{96} [2ex] mathbf{Output} & quadquad 256 quadquad times & color{blue}{55} & times & color{blue}{55} &&& times & color{green}{96} end{matrix}

1 x 1 卷積計算舉例

後期 GoogLeNet、ResNet 等經典模型中普遍使用一個像素大小的卷積核作為降低參數複雜度的手段。

從下面的運算可以看到,其實 1 x 1 卷積沒有什麼神秘的,其作用就是將輸入矩陣的通道數量縮減後輸出(512 降為 32),並保持它在寬度和高度維度上的尺寸(227 x 227)。

 begin{matrix} & mathbf{Batch} & mathbf{Height} && mathbf{Width} && mathbf{In~Depth} && mathbf{Out~Depth}[2ex] mathbf{Input} & quadquad 256 quadquad times & color{blue}{227} & times & color{blue}{227} & times & color{red}{512} [2ex] mathbf{Kernel} &quadquadquadquadquad & color{blue}{1} & times & color{blue}{1} & times & color{red}{512} & times & color{green}{32} [2ex] mathbf{Output} & quadquad 256 quadquad times & color{blue}{227} & times & color{blue}{227} &&& times & color{green}{32} end{matrix}

全連接層計算舉例

實際上,全連接層也可以被視為是一種極端情況的卷積層,其卷積核尺寸就是輸入矩陣尺寸,因此輸出矩陣的高度和寬度尺寸都是1。

 begin{matrix} & mathbf{Batch} & mathbf{Height} && mathbf{Width} && mathbf{In~Depth} && mathbf{Out~Depth}[2ex] mathbf{Input} & quad quad 256 quad quad times & color{blue}{32} & times & color{blue}{32} & times & color{red}{512} [2ex] mathbf{Kernel} &quadquadquadquadquad & color{blue}{32} & times & color{blue}{32} & times & color{red}{512} & times & color{green}{4096} [2ex] mathbf{Output} & quad quad 256 quad quad times & color{blue}{1} & times & color{blue}{1} &&& times & color{green}{4096} end{matrix}

總結下來,其實只需要認識到,雖然輸入的每一張圖像本身具有三個維度,但是對於卷積核來講依然只是一個一維向量。卷積核做的,其實就是與感受野範圍內的像素點進行點積(而不是矩陣乘法)。

附:TensorFlow 中卷積層的簡單實現

def conv_layer(x, out_channel, k_size, stride, padding):n in_channel = x.shape[3].valuen w = tf.Variable(tf.truncated_normal([k_size, k_size, in_channel, out_channel], mean=0, stddev=stddev))n b = tf.Variable(tf.zeros(out_channel))n y = tf.nn.conv2d(x, filter=w, strides=[1, stride, stride, 1], padding=padding)n y = tf.nn.bias_add(y, b)n y = tf.nn.relu(y)n return xn

  • 輸入 x:[batch, height, width, in_channel]
  • 權重 w:[height, width, in_channel, out_channel]
  • 輸出 y:[batch, height, width, out_channel]

推薦閱讀:

tensorflow讀取數據-tfrecord格式
如何使用最流行框架Tensorflow進行時序預測和時間序列分析
乾脆面君,你給我站住!你已經被TensorFlow盯上了

TAG:卷积神经网络CNN | TensorFlow | 深度学习DeepLearning |