你是一個解放者 你要有一顆勇敢的心 你要跨上戰馬 掛上榴彈 重新奪回兒時的沙丘

                               ---《復活》野外合作社

損失函數:

minGmaxDV(D,G)=??x~pdata(x)[logD(x)]+??z~pz(z)[log(1?D(G(x)))]

判別器由CNN,BN和LeakeyRelu層組成,最後一層激活層是digmoid,輸入是3x64x64 RGB image,輸出是一個表示input來源於真實數據分布的概率。生成器由反卷積,BN層和Relu層組成,最後一層激活層使用Tanh,輸出是3x64x64 RGB image。損失函數BCELoss()二值交叉熵。

我們在這裡主要記錄的是DCGAN的訓練過程以及對反卷積的思考。

根據[3]裡面的一些Tricks設置,我們構建不同的mini-batches for real and fake,調整G的目標函數由min[1-logD(G(z))]為max logD(G(z)),因為前者容易出現梯度消失的問題。

step 1:

從數據集中構建一個batch的real_data送到D中,這裡給real_data的標籤都為1。計算損失[log(D(x))]並求梯度。

step 2:

將一個batch的100維高斯分布向量送到G中生成fake_data(label都為0),送到D中,計算損失[log(1?D(G(z)))]並求梯度。將前兩步的梯度相加一起回傳更新D的參數。注意這裡雖然求過G的前向,但是這裡通過截斷反向傳播梯度流不更新G的參數。

step 3:

將step2中生成的fake_data(注意這裡由於我們需要maximize log(D(G(z))),我們將label置為1)送入到D中,求損失反向傳播更新G的參數。

這裡總結一下Some Tips and Tricks to make GANs work.[3]

(1)、Normalize the images between -1 and 1; use Tanh activation layer in the last of Generator

(2)、Use maximize (log(D(z))) as the loss function to optimize G.

(3)、Sample from a Gaussion Distribution.

(4)、Construct different mini-batches for real and fake images respectively.

(5)、Use BN and Adam

(6)、Avoid use Sparse Gradients like Relu and Max pooling.Use Average pooling or PixelShuffle instead.

(7)、Use soft and Noisy Labels,just like set real_datas label in [0.7, 1.2] and fake [0.0, 0.3]


卷積的輸出尺寸:

(n+2p-f)/s+1

tensorflow官方是這麼寫的,

out=  left{egin{matrix} left lceil frac{n-f+1}{s} 
ight 
ceil, quad if quad VALID \  left lceil frac{n}{s} 
ight 
ceil, quad if quad SAME end{matrix}
ight.

其中,VALID時的padding數為:

p = (out-1)*s+f-in

如果p為奇數就是左奇右偶填充。

反卷積判斷輸出尺寸是否正確也可以根據以上卷積的公式進行計算,只不過輸入輸出要互換。

另一點需要注意的點反卷積的filter尺寸輸入輸出要互換。即卷積[h,w,in,out]反卷積[h,w,out,in]

要想我們按照這種方法求得的結果和輸入tf.nn.conv2d_transpose()函數的結果是一樣的,需要對卷積核翻轉180。

圖片來源[4]

問題:反卷積的時候padding方式不同,具體是如何實現的?以及如何crop的問題

因為網上大多數是針對padding=SAME的情況,而padding=VALID的情況沒有找到很好的解釋。

經過一天的實驗,總結以下

在input之間補s-1個0,再在最外圈補f-1圈0.

SAME時,從output裁剪處output大小的矩陣來,而VALID時,如果輸出的矩陣比要求的小,需要在最後一列和最後一行補0。

(一般情況下VALID的輸出矩陣會比SAME的要大)

而以上的這些煩惱在pytorch中就不復存在了。pytorch大法好!

nn.ConvTranspose2d(self, in_channels, out_channels, kernel_size, stride=1,
padding=0, outputpadding=0, groups=1, bias=True, dilation=1)

輸出直接可以根據公式求得,還不會出現tensorflow里那種輸出尺寸可能會不確定所以必須得指定output_shape。

output = (input-1)*stride+output\_padding-2*padding + kernel\_size

[1]、PyTorch Tutorials 1.0.0.dev20181002 documentation

[2]、arxiv.org/pdf/1511.0643

[3]、github.com/soumith/ganh

[4]、blog.csdn.net/huachao10


推薦閱讀:
相关文章