成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

DCGAN(深度卷積對抗網絡)案例

derek_334892 / 3137人閱讀

摘要:深度卷積對抗生成網絡是的變體,是一種將卷積引入模型的網絡。特點是判別器使用來替代空間池化,生成器使用反卷積使用穩(wěn)定學習,有助于處理初始化不良導致的訓練問題生成器輸出層使用激活函數,其它層使用激活函數。

介紹

如圖所示,GAN網絡會同時訓練兩個模型。生成器:負責生成數據(比如:照片);判別器:判別所生成照片的真假。訓練過程中,生成器生成的照片會越來越接近真實照片,直到判別器無法區(qū)分照片真假。

DCGAN(深度卷積對抗生成網絡)是GAN的變體,是一種將卷積引入模型的網絡。特點是:

判別器使用strided convolutions來替代空間池化,生成器使用反卷積

使用BN穩(wěn)定學習,有助于處理初始化不良導致的訓練問題

生成器輸出層使用Tanh激活函數,其它層使用Relu激活函數。判別器上使用Leaky Relu激活函數。

本次案例我們將使用mnist作為數據集訓練DCGAN網絡,程序最后將使用GIF的方式展示訓練效果。

數據導入
import tensorflow as tf
import glob
import imageio
import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow.contrib as tcon
import PIL
import time
from IPython import display

# shape:(60000,28,28)
(train_images,train_labels),(_,_)=tf.keras.datasets.mnist.load_data()
# shape:[batch_size,height,width,channel]
train_images_reshape=tf.reshape(train_images,shape=(train_images.shape[0],28,28,1)).astype(tf.float32)
# 縮放圖片[-1,1]
train_images_nor=(train_images-127.5)/127.5

dataset加載數據

BUFFER_SIZE=60000
BATCH_SIZE=256

# 優(yōu)化輸入管道需要從:讀取,轉換,加載三方面考慮。
train_dataset=tf.data.Dataset.from_tensor_slices(train_images).shuffle(buffer_size=BUFFER_SIZE).batch(BATCH_SIZE)
生成模型

該生成模型將使用反卷積層,我們首先創(chuàng)建全連接層然后通過兩次上采樣將圖片分辨率擴充至28x28x1。我們將逐步提升分辨率降低depth,除最后一層使用tanh激活函數,其它層都使用Leaky Relu激活函數。

def make_generator_model():
    # 反卷積,從后往前
    model=tf.keras.Sequential()
    model.add(
        tf.keras.layers.Dense(
            input_dim=7*7*256,
            
            # 不使用bias的原因是我們使用了BN,BN會抵消掉bias的作用。
            # bias的作用:
            # 提升網絡擬合能力,而且計算簡單(只要一次加法)。
            # 能力的提升源于調整輸出的整體分布
            use_bias=False,
            # noise dim
            input_shape=(100,)
        )
    )
    """
    隨著神經網絡的訓練,網絡層的輸入分布會發(fā)生變動,逐漸向激活函數取值兩端靠攏,如:sigmoid激活函數,
    此時會進入飽和狀態(tài),梯度更新緩慢,對輸入變動不敏感,甚至梯度消失導致模型難以訓練。
    BN,在網絡層輸入激活函數輸入值之前加入,可以將分布拉到均值為0,標準差為1的正態(tài)分布,從而
    使激活函數處于對輸入值敏感的區(qū)域,從而加快模型訓練。此外,BN還能起到類似dropout的正則化作用,由于我們會有
    ‘強拉’操作,所以對初始化要求沒有那么高,可以使用較大的學習率。
    """
    model.add(tf.keras.layers.BatchNormalization())
    """
    relu 激活函數在輸入為負值的時候,激活值為0,此時神經元無法學習
    leakyrelu 激活函數在輸入為負值的時候,激活值不為0(但值很?。?,神經元可以繼續(xù)學習
    """
    model.add(tf.keras.layers.LeakyReLU())

    model.add(tf.keras.layers.Reshape(input_shape=(7,7,256)))
    assert model.output_shape == (None,7,7,256)

    model.add(tf.keras.layers.Conv2DTranspose(
        filters=128,
        kernel_size=5,
        strides=1,
        padding="same",
        use_bias="False"
    ))
    assert model.output_shape == (None,7,7,128)
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.LeakyReLU())

    # 卷積核為奇數:圖像兩邊可以對稱padding 00xxxx00
    model.add(tf.keras.layers.Conv2DTranspose(
        filters=64,
        kernel_size=5,
        strides=2,
        padding="same",
        use_bias="False"
    ))
    assert model.output_shape == (None,14,14,64)
    model.add(tf.keras.layers.BatchNormalization())
    model.add(tf.keras.layers.LeakyReLU())

    model.add(tf.keras.layers.Conv2DTranspose(
        filters=1,
        kernel_size=5,
        strides=2,
        padding="same",
        use_bias="False",
        
        # tanh激活函數值區(qū)間[-1,1],均值為0關于原點中心對稱。、
        # sigmoid激活函數梯度在反向傳播過程中會出全正數或全負數,導致權重更新出現Z型下降。
        activation="tanh"
    ))
    assert model.output_shape == (None,28,28,1)

    return model
判別模型

判別器使用strided convolutions來替代空間池化,比如這里strided=2。卷積層使用LeakyReLU替代Relu,并使用Dropout為全連接層提供加噪聲的輸入。

def make_discriminator_model():
    # 常規(guī)卷積操作
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(64, (5, 5), strides=(2, 2), padding="same"))
    model.add(tf.keras.layers.LeakyReLU())
    
    # dropout常見于全連接層,其實卷積層也是可以使用的。
    # 這里簡單翻譯下dropout論文觀點:
    """
    可能很多人認為因為卷積層參數較少,過擬合發(fā)生概率較低,所以dropout作用并不大。
    但是,dropout在前面幾層依然有幫助,因為它為后面的全連接層提供了加噪聲的輸入,從而防止過擬合。
    """
    model.add(tf.keras.layers.Dropout(0.3))
      
    model.add(tf.keras.layers.Conv2D(128, (5, 5), strides=(2, 2), padding="same"))
    model.add(tf.keras.layers.LeakyReLU())
    model.add(tf.keras.layers.Dropout(0.3))
       
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(1))
     
    return model
損失函數

獲取模型:

generator = make_generator_model()
discriminator = make_discriminator_model()

生成器損失函數:

損失函數使用sigmoid cross entropy,labels使用值全為1的數組。

def generator_loss(generator_output):
    return tf.losses.sigmoid_cross_entropy(
        multi_class_labels=tf.ones_like(generator_output),
        logits=generator_output
    )

判別器損失函數

判別器損失函數接受兩種輸入,生成器生成的圖像和數據集中的真實圖像,損失函數計算方法如下:

使用sigmoid cross entropy損失函數計算數據集中真實圖像的損失,labels使用值全為1的數組。

使用sigmoid cross entropy損失函數計算生成器圖像的損失,labels使用值全為0的數組。

將以上損失相加得到判別器損失。

def discriminator_loss(real_output, generated_output):
    # real:[1,1,...,1] 
    real_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.ones_like(real_output), logits=real_output)
    #:generated:[0,0,...,0] 
    generated_loss = tf.losses.sigmoid_cross_entropy(multi_class_labels=tf.zeros_like(generated_output), logits=generated_output)
    
    # 總損失為兩者相加
    total_loss = real_loss + generated_loss
    return total_loss

模型保存:

# 兩種模型同時訓練,自然需要使用兩種優(yōu)化器,學習率為:0.0001
generator_optimizer = tf.train.AdamOptimizer(1e-4)
discriminator_optimizer = tf.train.AdamOptimizer(1e-4)
checkpoint_dir = "./training_checkpoints"
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")

# checkpoint配置
checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,
                                 discriminator_optimizer=discriminator_optimizer,
                                 generator=generator,
                                 discriminator=discriminator)
模型訓練

訓練參數配置:

# 數據集迭代次數
EPOCHS = 50
# 生成器噪聲維度
noise_dim = 100

# 可視化效果數量設置
num_examples_to_generate = 16
random_vector_for_generation = tf.random_normal([num_examples_to_generate,
                                                 noise_dim])

生成器將我們設定的正態(tài)分布的噪聲向量作為輸入,用來生成圖像。判別器將同時顯示數據集真實圖像和生成器生成的圖像用于判別。隨后,我們計算生成器和判斷器損失函數對參數的梯度,然后使用梯度下降進行更新。

def train_step(images):
      # 正態(tài)分布噪聲作為生成器輸入
      noise = tf.random_normal([BATCH_SIZE, noise_dim])
      
      # tf.GradientTape進行記錄
      with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
        generated_images = generator(noise, training=True)
        
        # 判別器中真實圖像和生成器的假圖像
        real_output = discriminator(images, training=True)
        generated_output = discriminator(generated_images, training=True)
        
        gen_loss = generator_loss(generated_output)
        disc_loss = discriminator_loss(real_output, generated_output)
        
      gradients_of_generator = gen_tape.gradient(gen_loss, generator.variables)
      gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.variables)
      
      generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.variables))
      discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.variables))

開始訓練:

加速計算節(jié)約內存,但是不可以使用"pdb","print"。

train_step = tf.contrib.eager.defun(train_step)
def train(dataset, epochs):  
  for epoch in range(epochs):
    start = time.time()
    
    # 迭代數據集
    for images in dataset:
      train_step(images)

    display.clear_output(wait=True)
    
    # 保存圖像用于后面的可視化
    generate_and_save_images(generator,
                               epoch + 1,
                               random_vector_for_generation)
    
    # 每迭代15次數據集保存一次模型
    # 如需部署至tensorflow serving需要使用savemodel
    if (epoch + 1) % 15 == 0:
      checkpoint.save(file_prefix = checkpoint_prefix)
    
    print ("Time taken for epoch {} is {} sec".format(epoch + 1,
                                                      time.time()-start))
  display.clear_output(wait=True)
  generate_and_save_images(generator,
                           epochs,
                           random_vector_for_generation)

可視化生成器圖像:

def generate_and_save_images(model, epoch, test_input):
  # training:False 不訓練BN
  predictions = model(test_input, training=False)

  fig = plt.figure(figsize=(4,4))
  
  for i in range(predictions.shape[0]):
      plt.subplot(4, 4, i+1)
      plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap="gray")
      plt.axis("off")
        
  plt.savefig("image_at_epoch_{:04d}.png".format(epoch))
  plt.show()

train(train_dataset, EPOCHS)
可視化模型訓練結果

展示照片:

def display_image(epoch_no):
  return PIL.Image.open("image_at_epoch_{:04d}.png".format(epoch_no))

動畫展示訓練結果:

with imageio.get_writer("dcgan.gif", mode="I") as writer:
  filenames = glob.glob("image*.png")
  filenames = sorted(filenames)
  last = -1
  for i,filename in enumerate(filenames):
    frame = 2*(i**0.5)
    if round(frame) > round(last):
      last = frame
    else:
      continue
    image = imageio.imread(filename)
    writer.append_data(image)
  image = imageio.imread(filename)
  writer.append_data(image)
    
os.system("cp dcgan.gif dcgan.gif.png")
display.Image(filename="dcgan.gif.png")
總結

DCGAN中生成器判別器都使用卷積網絡來提升生成和判別能力,其中生成器利用反卷積,判別器利用常規(guī)卷積。生成器用隨機噪聲向量作為輸入來生成假圖像,判別器通過對真實樣本的學習判斷生成器圖像真?zhèn)?,如果判斷為假,生成器重新調校訓練,直到判別器無法區(qū)分真實樣本圖像和生成器的圖像。

本文代碼部分參考Yash Katariya,在此表示感謝。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/42754.html

相關文章

  • 到底什么是生成式對抗網絡GAN?

    摘要:很多人可能會問這個故事和生成式對抗網絡有什么關系其實,只要你能理解這段故事,就可以了解生成式對抗網絡的工作原理。 男:哎,你看我給你拍的好不好?女:這是什么鬼,你不能學學XXX的構圖嗎?男:哦……男:這次你看我拍的行不行?女:你看看你的后期,再看看YYY的后期吧,呵呵男:哦……男:這次好點了吧?女:呵呵,我看你這輩子是學不會攝影了……男:這次呢?女:嗯,我拿去當頭像了上面這段對話講述了一位男...

    GitCafe 評論0 收藏0
  • 生成式對抗網絡(GAN)如何快速理解?

    摘要:目前,生成對抗網絡的大部分應用都是在計算機視覺領域。生成對抗網絡生成對抗網絡框架是由等人于年設計的生成模型。在設置中,兩個由神經網絡進行表示的可微函數被鎖定在一個游戲中。我們提出了深度卷積生成對抗網絡的實現。 讓我們假設這樣一種情景:你的鄰居正在舉辦一場非??岬木蹠惴浅O肴⒓?。但有要參加聚會的話,你需要一張?zhí)貎r票,而這個票早就已經賣完了。而對于這次聚會的組織者來說,為了讓聚會能夠成功舉...

    Leo_chen 評論0 收藏0
  • 火熱的生成對抗網絡(GAN),你究竟好在哪里

    摘要:自年提出生成對抗網絡的概念后,生成對抗網絡變成為了學術界的一個火熱的研究熱點,更是稱之為過去十年間機器學習領域最讓人激動的點子。 自2014年Ian Goodfellow提出生成對抗網絡(GAN)的概念后,生成對抗網絡變成為了學術界的一個火熱的研究熱點,Yann LeCun更是稱之為過去十年間機器學習領域最讓人激動的點子。生成對抗網絡的簡單介紹如下,訓練一個生成器(Generator,簡稱G...

    mist14 評論0 收藏0
  • 谷歌大腦發(fā)布GAN全景圖:看百家爭鳴的生成對抗網絡

    摘要:近日,谷歌大腦發(fā)布了一篇全面梳理的論文,該研究從損失函數對抗架構正則化歸一化和度量方法等幾大方向整理生成對抗網絡的特性與變體。他們首先定義了全景圖損失函數歸一化和正則化方案,以及最常用架構的集合。 近日,谷歌大腦發(fā)布了一篇全面梳理 GAN 的論文,該研究從損失函數、對抗架構、正則化、歸一化和度量方法等幾大方向整理生成對抗網絡的特性與變體。作者們復現了當前較佳的模型并公平地對比與探索 GAN ...

    asoren 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<