反卷積
- 反卷積計(jì)算
假設(shè)有一個(gè)輸入為4x4的矩陣X,和一個(gè)3x3的矩陣kernel
當(dāng)卷積參數(shù)為步長(zhǎng)為1,填充為0時(shí),輸出為Y=2x2
此時(shí)我們將X展開(kāi)為16x1的列向量,Y展開(kāi)為4x1的列向量,則存在矩陣C,有Y = CX,
C的shape為4x16。稀疏矩陣可以推導(dǎo)出來(lái),從而根據(jù)C和Y我們可以求的X。但是這個(gè)操作只能恢復(fù)X的shape,而不能恢復(fù)
它的每個(gè)元素的值。
- 反卷積輸出的shape
首先對(duì)于正向卷積,輸出shape計(jì)算公式output = (input - kernelsize + 2padding) / strides + 1,舉例,input=6x6,kernel=3x3,
stride=2,padding=1,則它的輸出shape=3x3
對(duì)于反卷積,第一種情況,(output + 2padding - kernel) % s = 0(注意這里的output是卷積的輸出),此時(shí)的反卷積輸出為o = strides(input - 1) - 2padding + kernel,即
此時(shí)反卷積輸出為5x5.
第二種情況,(output + 2padding - kernel) % s != 0
此時(shí)反卷積輸出尺寸為o = strides(input - 1) - 2padding + kernel + (output + 2padding - kernel) % s,即對(duì)于上述的正向卷積,
做反向卷積是輸出為6x6。
- tensorflow實(shí)驗(yàn)
反卷積
第一種情況,輸出的shape為5x5
import tensorflow as tf
img = tf.Variable(tf.constant([[1.,2,3],[4,5,6],[7,8,9]], shape=[1,3,3,1]))
kernel = tf.Variable(tf.constant([[1.0,0.,0.],[0,1.0,0],[0,0,1.0]],shape=[3,3,1,1]))
conts = tf.nn.conv2d_transpose(img,kernel,[1,5,5,1],strides=[1,2,2,1],padding='SAME')
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print('conts:\n', sess.run(conts))
'''
輸出為5x5
1 0 2 0 3
0 6 0 8 0
4 0 5 0 6
0 12 0 14 0
7 0 8 0 9
'''
第二種情況,輸出shape為6x6
# 代碼同上,conts = tf.nn.conv2d_transpose(img,kernel,[1,5,5,1],strides=[1,2,2,1],padding='SAME')中【1,5,5,1】改為【1,6,6,1】
'''
輸出為
1 0 2 0 3 0
0 1 0 2 0 3
4 0 6 0 8 0
0 4 0 5 0 6
7 0 12 0 14 0
0 7 0 8 0 9
'''
- tensorflow計(jì)算規(guī)則
tensorflow執(zhí)行反卷積時(shí),會(huì)首先根據(jù)輸入的參數(shù)計(jì)算卷積結(jié)果是否成立,也即shape是否合法。
對(duì)于第一種情況,計(jì)算時(shí)先對(duì)輸入的矩陣中間補(bǔ)0,每?jī)蓚€(gè)元素之間補(bǔ)0的個(gè)數(shù)由strides確定,即補(bǔ)strides-1個(gè)0,對(duì)于3x3矩陣,補(bǔ)零之后變?yōu)?x5
1 0 2 0 3 1 0 2 0 3
1 2 3 0 0 0 0 0 0 6 0 8 0
4 5 6 -> 4 0 5 0 6 -> 卷積核轉(zhuǎn)置 -> 4 0 5 0 6
7 8 9 0 0 0 0 0 0 12 0 14 0
7 0 8 0 9 7 0 8 0 9
第二種情況,計(jì)算時(shí)除了對(duì)矩陣元素中間補(bǔ)零之外,還在外圍填充0(也就是same填充),此時(shí)input從3x3變?yōu)榱?x5,padding=1,但此時(shí)通過(guò)卷積公式計(jì)算
output = (input - kernelsize + 2padding) / strides + 1 = (5 - 3 + 2)/ 1 + 1 = 5,不等于6,所以繼續(xù)在外圍填充0,
tensorflow優(yōu)先在左側(cè)和上側(cè)填充,此時(shí)輸出的shape就變?yōu)?x6了。
注:這一步有的分析上也說(shuō)是上下左右都補(bǔ)零,但是輸出結(jié)果對(duì)下方和右方的最后一列進(jìn)行裁剪操作,但實(shí)際上效果是一樣的。