for basic discriminator of GANs
判別器用於感知生成器產生的合成圖片和ground-truth的差異,並旨在實現區分出fake or real;
同時,判別器的輸出也是經過一系列的conv后得到的一個標量值,一般使這個值激活在0~1之間;
但是,這樣的結果存在着一些問題:
1.輸出的結果顯然是一個整體圖片的加權值,無法體現局部圖像的特征,對於精度要求高的的圖像遷移等任務比較困難。
for Patch-based discriminator of GANs
PatchGAN的思路是最后的輸出不是一個標量值,而是一個$N*N$的矩陣$X$,其實$X_{ij}$表示patch $ij$是fake or real.
關鍵點就是:在$X$上的一個神經元$X_{ij}$可以表示一塊輸入patch,這個神經元就對這塊patch的像素敏感,這塊patch 就是 輸出$X_{ij}$的感知域(receptive field).
1.這樣方法 通過每個patch 進行差別的判別, 實現了局部圖像特征的提取和表征, 有利於實現更為高分辨率的圖像生產;同時, 對最后的 分類特征圖進行平均后, 也能夠實現相比
2.單標量輸出的更為精確的整體差異表示,相當於對整體進行加權求和平均,對於某些特征差異大的局部圖像特征, 能夠實現比basic D 更為合理的 損失表示。
3.這種機制,將局部圖像特征和整體圖像特性相融合。
Mathematical:
有個解決辦法就是將圖像裁剪成多個重疊的patches,分別進行判別器的差異識別,並對得到的結果進行平均,但是這樣存在大的運算消耗。
Obviously,卷積神經網絡的強大之處在於,它們能以相同的方式獨立地處理每個圖像塊,所以在最后的實際過程中,得到的輸出矩陣的每一神經元相當於就是在執行每個patch的單獨判斷的結果,這樣的結果具有高效的運算效果。
The size of receptive field:
堆疊不同層的convnets, 最后輸出矩陣的單個神經元的表征的感知域的大小顯然不一樣;感知域越大,這意味着它應該學習距離更遠的對象之間的關系
empirical, 層數越深, 能夠感知的patch的尺寸也越大,但是這樣會付出更多的計算成本和時間消耗,所以需要通過traceback:
function receptive_field_sizes() % compute input size from a given output size f = @(output_size, ksize, stride) (output_size - 1) * stride + ksize; %% n=1 discriminator % fix the output size to 1 and derive the receptive field in the input out = ... f(f(f(1, 4, 1), ... % conv2 -> conv3 4, 1), ... % conv1 -> conv2 4, 2); % input -> conv1 fprintf('n=1 discriminator receptive field size: %d\n', out); %% n=2 discriminator % fix the output size to 1 and derive the receptive field in the input out = ... f(f(f(f(1, 4, 1), ... % conv3 -> conv4 4, 1), ... % conv2 -> conv3 4, 2), ... % conv1 -> conv2 4, 2); % input -> conv1 fprintf('n=2 discriminator receptive field size: %d\n', out); %% n=3 discriminator % fix the output size to 1 and derive the receptive field in the input out = ... f(f(f(f(f(1, 4, 1), ... % conv4 -> conv5 4, 1), ... % conv3 -> conv4 4, 2), ... % conv2 -> conv3 4, 2), ... % conv1 -> conv2 4, 2); % input -> conv1 fprintf('n=3 discriminator receptive field size: %d\n', out); %% n=4 discriminator % fix the output size to 1 and derive the receptive field in the input out = ... f(f(f(f(f(f(1, 4, 1), ... % conv5 -> conv6 4, 1), ... % conv4 -> conv5 4, 2), ... % conv3 -> conv4 4, 2), ... % conv2 -> conv3 4, 2), ... % conv1 -> conv2 4, 2); % input -> conv1 fprintf('n=4 discriminator receptive field size: %d\n', out); %% n=5 discriminator % fix the output size to 1 and derive the receptive field in the input out = ... f(f(f(f(f(f(f(1, 4, 1), ... % conv6 -> conv7 4, 1), ... % conv5 -> conv6 4, 2), ... % conv4 -> conv5 4, 2), ... % conv3 -> conv4 4, 2), ... % conv2 -> conv3 4, 2), ... % conv1 -> conv2 4, 2); % input -> conv1 fprintf('n=5 discriminator receptive field size: %d\n', out);
實際模型搭建
顯然,是需要堆積多個convnets即可實現PatchGAN的判別器, PatchGAN更多的將它理解為一種機制mechanism,其實整個模型就是一個FCN結構。
對於不同的感知域,肯定在D中表征為有不同的convnet層, torch:
function defineD_n_layers(input_nc, output_nc, ndf, n_layers) if n_layers==0 then return defineD_pixelGAN(input_nc, output_nc, ndf) else local netD = nn.Sequential() -- input is (nc) x 256 x 256 netD:add(nn.SpatialConvolution(input_nc+output_nc, ndf, 4, 4, 2, 2, 1, 1)) module = nn.SpatialConvolution(nInputPlane, nOutputPlane, kW, kH, [dW], [dH], [padW], [padH]) netD:add(nn.LeakyReLU(0.2, true)) local nf_mult = 1 local nf_mult_prev = 1 for n = 1, n_layers-1 do nf_mult_prev = nf_mult nf_mult = math.min(2^n,8) netD:add(nn.SpatialConvolution(ndf * nf_mult_prev, ndf * nf_mult, 4, 4, 2, 2, 1, 1)) netD:add(nn.SpatialBatchNormalization(ndf * nf_mult)):add(nn.LeakyReLU(0.2, true)) end -- state size: (ndf*M) x N x N nf_mult_prev = nf_mult nf_mult = math.min(2^n_layers,8) netD:add(nn.SpatialConvolution(ndf * nf_mult_prev, ndf * nf_mult, 4, 4, 1, 1, 1, 1)) netD:add(nn.SpatialBatchNormalization(ndf * nf_mult)):add(nn.LeakyReLU(0.2, true)) -- state size: (ndf*M*2) x (N-1) x (N-1) netD:add(nn.SpatialConvolution(ndf * nf_mult, 1, 4, 4, 1, 1, 1, 1)) -- state size: 1 x (N-2) x (N-2) netD:add(nn.Sigmoid()) -- state size: 1 x (N-2) x (N-2) return netD end end9
一些思考 future works
1.PatchGAN的整個機制的核心在於對 G網絡結果的優化,優化了類似U-net的結構(encoder-decoder的架構),使得低階信息跨越bottleneck,讓更多的低階信息得以交換,
並讓G的訓練有如同 Res-block般的平緩梯度,一定程度上減緩了梯度消失, 我們知道Resnet較為好的解決了多層convnet堆疊后的訓練困難的問題,其類似於放大器的結構,讓訓練
更為的有效。
2.由於patches的重疊性和局部特征性,對於不同的任務, patches之間的局部特征的相關性肯定存在差異, 所以對於感知域的尺寸確定需要有差異性和動態性,才能實現較為好的性能。
3.對於G 來說, 其解碼過程其實使用的是微步幅卷積操作或叫做反卷積操作,但是反卷積操作其實對於圖像的產生是存在着爭議性的,改善和提高這個部分,具有一點的前景, 可以采用
多個的feature map進行重疊作為輸入的操作, 得到一個多層特征圖, 嘗試直接使用一個下采樣卷積作為一個生成器。
4.對於CGANs 機制的引入, 其實是使得 GAN的訓練更加穩定, 進行有約束的執行generative 任務, 進行加 buff的 判別的任務。