SAGAN——Self-Attention Generative Adversarial Networks

原論文下載地址:Self-Attention Generative Adversarial Networks

該文章作者爲:Han Zhang

GitHub代碼實現:pytorch實現

摘要部分:

本文提出了Self-Attention Generative Adversarial Networks,在注意力機制,遠距離依賴(long-range dependency)下來實現了圖片生成任務。(1)傳統的卷積GAN網絡,是通過低分辨率圖像中的空間局部點來生成高分辨率細節特徵。 而在SAGAN中,可以使用根據所有位置的提示來生成詳細信息。(2)因爲判別器可以檢查圖像的遠端部分中的高度詳細的特徵是否彼此一致。而最近的研究表明,對生成器進行有效的調節可以影響GAN網絡的性能,所以我們在GAN網絡的generator中加入了光譜正則化(spectral normalization)。最終達到了比較好的效果。

提出問題:

convolutional GANs have much more difficulty modeling some image classes than others when trained on multi-class datasets . For example, while the state-of-the-art ImageNet GAN model  excels at synthesizing image classes with few structural constraints (e.g. ocean, sky and landscape classes, which are distinguished more by texture than by geometry), it fails to capture geometric or structural patterns that occur consistently in some classes (for example, dogs are often drawn with realistic fur texture but without clearly defined separate feet)。

在多種類別的數據集上訓練時,卷積GAN網絡比其他圖像類更難以建模,也就是說GAN網絡很容易合成具有少量結構約束的圖像(像星空,海洋...),

在目前的圖像生成模型中,一般很難處理好細節和整體的權衡

可能原因:

對此的一種可能解釋是先前的模型嚴重依賴於卷積來模擬不同圖像區域之間的依賴性。由於卷積運算符具有局部感受域,因此只能在經過多個卷積層之後處理長距離依賴性(long-range dependency)。這可能會因各種原因阻止學習長期依賴性:

(1)小型模型可能無法找到他們之間的依賴關係;

(2)優化算法可能無法發現仔細協調多個層以捕獲這些依賴性的參數值;

(3)增加捲積核的大小可以增加網絡的表示能力,但是又會喪失卷積網絡的參數和計算效率。

解決辦法-即SAGAN的優點:

self-attention 在模擬遠程依賴性的能力、計算效率和統計效率之間展現出更好的平衡。自我關注模塊將所有位置處的特徵的加權和作爲該位置的響應,其中權重 - 或注意向量 - 僅以較小的計算成本來計算。

我們提出了自我注意生成對抗網絡(SAGAN),它將self-attention機制引入卷積GAN。

(1)可以很好的處理長範圍、多層次的依賴(可以很好的發現圖像中的依賴關係)

(2)生成圖像時每一個位置的細節和遠端的細節協調好

(3)判別器還可以更準確地對全局圖像結構實施複雜的幾何約束。

SAGAN:(參考了 https://blog.csdn.net/mx54039q/article/details/80896054)

文中提到大多數GAN用的都是卷積層,而卷積層只能夠處理局部的信息,所以本文中採用了一種non-local model,是的生成器和判別器能夠有效地構建各個區域之間的關係。

                                             self-attention 機制

(1)f(x),g(x)和h(x)都是普通的1x1卷積,差別只在於輸出通道大小不同;

(2)將f(x)的輸出轉置,並和g(x)的輸出相乘,再經過softmax歸一化得到一個Attention Map;

(3)將得到的Attention Map和h(x)逐像素點相乘,得到自適應的注意力feature maps.

       tensorflow code

    def attention(self, x, ch):
      f = conv(x, ch // 8, kernel=1, stride=1, sn=self.sn, scope='f_conv') # [bs, h, w, c']
      g = conv(x, ch // 8, kernel=1, stride=1, sn=self.sn, scope='g_conv') # [bs, h, w, c']
      h = conv(x, ch, kernel=1, stride=1, sn=self.sn, scope='h_conv') # [bs, h, w, c]

      # N = h * w
      s = tf.matmul(hw_flatten(g), hw_flatten(f), transpose_b=True) # # [bs, N, N]

      beta = tf.nn.softmax(s, axis=-1)  # attention map

      o = tf.matmul(beta, hw_flatten(h)) # [bs, N, C]
      gamma = tf.get_variable("gamma", [1], initializer=tf.constant_initializer(0.0))

      o = tf.reshape(o, shape=x.shape) # [bs, h, w, C]
      x = gamma * o + x

      return x

                                                  

  參數的含義

(1)f(x)的輸出[C/8, W, H], g(x)的輸出[C/8, W, H],爲了適應矩陣乘法,文中將一個feature map的長和寬flat成一個N維的向量          (N = W x H),即f(x)和g(x)的輸出爲[C/8, N];

(2)將f(x)的轉置和g(x)矩陣乘,得到的輸出S爲一個矩陣[N, N],S矩陣可以看做一個相關性矩陣,即長H寬W的feature map上          各個像素點之間的相關性;

(3)將S矩陣逐行用Softmax歸一化得到\beta矩陣,每一行(長度爲N的向量)代表了一種Attention的方式;

(4)將這N種Attention的方式應用到h(x)上,即每一個像素點都與整個feature map相關,相關性來自於\beta矩陣,得到N個新的像素點作爲輸出O;

最終的輸出爲:

                                                   

其中\gamma初始化爲0,然後逐漸的給 non-local分配更多的權重,

而這樣做的原因是因爲:我們想一開始學習一些簡單的任務,然後再不斷地增加複雜的任務。在SAGAN中,我們提出的注意力模型用在了generator模型和discriminator模型中,最後使用交替訓練的方式來最小化adversarial loss。

穩定訓練GAN的一些技巧:

(1)Spectral normalization for both generator and discriminator
         有效地降低了訓練的計算量,使得訓練更加穩定

(2)Imbalanced learning rate for generator and discriminator updates
         two-timescale update rule (TTUR)
         在訓練過程中,給予G和D不同的學習速率,以平衡兩者的訓練速度

實驗結果:

(1)用來評估所使用的兩個tricks

(2)評估 Self-attention 機制

spectral_normalization code (tensorflow)

w = tf.get_variable("kernel", shape=[kernel, kernel, channels, x.get_shape()[-1]], initializer=weight_init, regularizer=weight_regularizer)
x = tf.nn.conv2d_transpose(x, filter=spectral_norm(w), output_shape=output_shape, strides=[1, stride, stride, 1], padding=padding)
def spectral_norm(w, iteration=1):
    w_shape = w.shape.as_list()
    w = tf.reshape(w, [-1, w_shape[-1]])

    u = tf.get_variable("u", [1, w_shape[-1]], initializer=tf.truncated_normal_initializer(), trainable=False)

    u_hat = u
    v_hat = None
    for i in range(iteration):
        """
        power iteration
        Usually iteration = 1 will be enough
        """
        v_ = tf.matmul(u_hat, tf.transpose(w))
        v_hat = l2_norm(v_)

        u_ = tf.matmul(v_hat, w)
        u_hat = l2_norm(u_)

    sigma = tf.matmul(tf.matmul(v_hat, w), tf.transpose(u_hat))
    w_norm = w / sigma

    with tf.control_dependencies([u.assign(u_hat)]):
        w_norm = tf.reshape(w_norm, w_shape)

return w_norm

摘自:https://github.com/taki0112/Self-Attention-GAN-Tensorflow/blob/master/ops.py

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章