怎樣通俗易懂地解釋反捲積?
通過推導,我們可以得到稀疏矩陣:
反捲積的操作就是要對這個矩陣運算過程進行逆運算,即通過和得到,根據各個矩陣的尺寸大小,我們能很輕易的得到計算的過程,即為反捲積的操作:
-->直接學這個矩陣引數行不行?效果會不會更好?
如何體現更巧妙的 weight sharing? deformable conv?
怎樣通俗易懂地解釋反捲積?
定義:反捲積(deconvolution)是指通過 計算 輸出和已知輸入 ,求 未知輸入的過程。 應用1:影象識別。 應用2:可以從一組模糊的光切影象… 被瀏覽 77,868 檢視全部 13 個回答 孫小也 阿里巴巴 產品經理 Frank Tian 、 醒了麼 等閱讀本文的基礎,是預設已經理解了影象處理中正向卷積的過程(卷積特徵提取 - UFLDL)。
什麼是反捲積?
- 上取樣(Upsample)
在應用在計算機視覺的深度學習領域,由於輸入影象通過卷積神經網路(CNN)提取特徵後,輸出的尺寸往往會變小,而有時我們需要將影象恢復到原來的尺寸以便進行進一步的計算(e.g.:影象的語義分割),這個採用擴大影象尺寸,實現影象由小解析度到大解析度的對映的操作,叫做上取樣(Upsample)。
- 反捲積(Transposed Convolution)
上取樣有3種常見的方法:雙線性插值(bilinear),反捲積(Transposed Convolution),反池化(Unpooling),我們這裡只討論反捲積。這裡指的反捲積,也叫轉置卷積,它並不是正向卷積的完全逆過程,用一句話來解釋:
反捲積是一種特殊的正向卷積,先按照一定的比例通過補來擴大輸入影象的尺寸,接著旋轉卷積核,再進行正向卷積。
反捲積的數學推導
- 正向卷積的實現過程
假設輸入影象尺寸為,元素矩陣為:
卷積核尺寸為,元素矩陣為:
步長,填充,即,
則按照卷積計算公式,輸出影象的尺寸為。
- 用矩陣乘法描述卷積
把的元素矩陣展開成一個列向量:
把輸出影象的元素矩陣展開成一個列向量:
對於輸入的元素矩陣和 輸出的元素矩陣,用矩陣運算描述這個過程:
通過推導,我們可以得到稀疏矩陣:
反捲積的操作就是要對這個矩陣運算過程進行逆運算,即通過和得到,根據各個矩陣的尺寸大小,我們能很輕易的得到計算的過程,即為反捲積的操作:
但是,如果你代入數字計算會發現,反捲積的操作只是恢復了矩陣的尺寸大小,並不能恢復的每個元素值,本文最後會在 tensorflow 平臺進行這個實驗。
在此之前,我們先給出反捲積影象尺寸變化的公式。
- 反捲積的輸入輸出尺寸關係
在進行反捲積時,簡單來說,大體上可分為以下兩種情況:
Relationship 1:
此時反捲積的輸入輸出尺寸關係為:
如上圖所示,我們選擇一個輸入尺寸為,卷積核尺寸為,步長,填充,即,則輸出的尺寸為。
Relationship 2:
此時反捲積的輸入輸出尺寸關係為:
如上圖所示,我們選擇一個輸入的尺寸為,卷積核的尺寸為,步長,填充,即,則輸出的尺寸為。
- 反捲積在 FCN 中的應用
在影象語義分割網路 FCN-32s 中,上取樣反捲積操作的輸入每張影象的尺寸是,我們希望進行一次上取樣後能恢復成原始影象的尺寸,代入公式:
根據上式,我們可以得到一個關於三者之間關係的等式:
通過實驗,最終找出了最合適的一組資料:
在 tensorflow 中實現反捲積
- 反捲積的具體計算步驟
下面我們用一組實驗更直觀的解釋一下在 tensorflow 中反捲積的過程:
我們令輸入影象為:
卷積核為:
case 1
如果要使輸出的尺寸是,步數,tensorflow 中的命令為:
transpose_conv = tf.nn.conv2d_transpose(value=input,
filter=kernel,
output_shape=[1,5,5,1],
strides=2,
padding='SAME')
當執行 transpose_conv 命令時,tensorflow 會先計算卷積型別、輸入尺寸、步數和輸出尺寸之間的關係是否成立,如果不成立,會直接提示錯誤,如果成立,執行如下操作:
1. 現根據步數對輸入的內部進行填充,這裡可以理解成輸入放大的倍數,即在的每個元素之間填充,的個數與的關係為:
例如這裡舉例的,即在的每個元素之間填個:
因為卷積型別為 same,所以此時,。
2. 接下來,用卷積核對填充後的輸入進行步長的正向卷積,根據正向卷積輸出尺寸公式:得到輸出尺寸是,反捲積公式中我們給出的輸出尺寸引數也是為,兩者相同,所以可以進行計算,結果為:
與 tensorflow 的執行結果相同。
case 2
我們將 case 1 中的輸出尺寸改成,其他引數均不變,tensorflow 中的命令為:
transpose_conv = tf.nn.conv2d_transpose(value=input,
filter=kernel,
output_shape=[1,6,6,1],
strides=2,
padding='SAME')
卷積型別是 same,我們首先在外圍填充一圈:
這時發現,填充後的輸入尺寸與的卷積核卷積後的輸出尺寸是,沒有達到的,這就需要繼續填充,tensorflow 的計算規則是優先在左側和上側填充一排,填充後的輸入變為:
接下來,再對這個填充後的輸入與的卷積核卷積,結果為:
與 tensorflow 的執行結果相同。
- 反捲積只能恢復尺寸,不能恢復數值
最後,我們要驗證一下前文中提到的“如果你代入數字計算會發現,反捲積的操作只是恢復了矩陣的尺寸大小,並不能恢復的每個元素值”。
1. 正向卷積:
value = tf.reshape(tf.constant([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.]]),
[1, 5, 5, 1])
filter = tf.reshape(tf.constant([[1., 0.],
[0., 1.]]),
[2, 2, 1, 1])
output = tf.nn.conv2d(value, filter, [1, 2, 2, 1], 'SAME')
卷積的結果是:
2. 我們用和正向卷積完全相同的引數對這個結果進行反捲積:
input = tf.reshape(tf.constant([[6., 8., 3.],
[12., 14., 6.],
[7., 8., 9.]]),
[1, 3, 3, 1])
kernel = tf.reshape(tf.constant([[1., 0.],
[0., 1.]]),
[2, 2, 1, 1])
output = tf.nn.conv2d_transpose(value=input,
filter=kernel,
output_shape=[1, 3, 3, 1],
strides=[1, 2, 2, 1],
padding='SAME')
卷積的結果是:
可見,反捲積不能恢復數值,而且,在當時,即便使用完全相同的引數進行轉置卷積,輸入的尺寸也不能恢復。