1. 程式人生 > 實用技巧 >怎樣通俗易懂地解釋反捲積?

怎樣通俗易懂地解釋反捲積?

通過推導,我們可以得到稀疏矩陣:

反捲積的操作就是要對這個矩陣運算過程進行逆運算,即通過和得到,根據各個矩陣的尺寸大小,我們能很輕易的得到計算的過程,即為反捲積的操作:

-->直接學這個矩陣引數行不行?效果會不會更好?
如何體現更巧妙的 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')


卷積的結果是:


可見,反捲積不能恢復數值,而且,在當時,即便使用完全相同的引數進行轉置卷積,輸入的尺寸也不能恢復。

編輯於 2019-05-27