從零開始學keras之生成對抗網絡GAN

      網友投稿 920 2025-03-31

      生成對抗網絡主要分為生成器網絡和判別器網絡。

      生成器網絡:他以一個隨機向量(潛在空間的一個隨機點)作為輸入,并將其解碼成一張合成圖像。

      判別器網絡:以一張圖像(真實的或合成的均可)作為輸入,并預測該圖像是來自訓練集還是生成器網絡創建。

      本節將會介紹如何用 Keras 來實現形式最簡單的 GAN。GAN 屬于高級應用,所以本書不會深入介紹其技術細節。我們具體實現的是一個深度卷積生成式對抗網絡(DCGAN,deep convolutional GAN),即生成器和判別器都是深度卷積神經網絡的 GAN。特別地,它在生成器中使用 Conv2DTranspose 層進行圖像上采樣。 我們將在 CIFAR10 數據集的圖像上訓練 GAN,這個數據集包含 50 000 張 32×32 的 RGB圖像,這些圖像屬于 10 個類別(每個類別 5000 張圖像)。為了簡化,我們只使用屬于“frog”(青蛙)類別的圖像。

      GAN 的簡要實現流程如下所示。

      (1) generator 網絡將形狀為 (latent_dim,) 的向量映射到形狀為 (32, 32, 3) 的圖像。

      (2) discriminator 網絡將形狀為 (32, 32, 3) 的圖像映射到一個二進制分數,用于評估圖像為真的概率。

      (3) gan 網絡將 generator 網絡和 discriminator 網絡連接在一起:gan(x) = discriminator (generator(x))。生成器將潛在空間向量解碼為圖像,判別器對這些圖像的真實性進 行評估,因此這個 gan 網絡是將這些潛在向量映射到判別器的評估結果。

      (4) 我們使用帶有“真”/“假”標簽的真假圖像樣本來訓練判別器,就和訓練普通的圖像 分類模型一樣。

      (5) 為了訓練生成器,我們要使用 gan 模型的損失相對于生成器權重的梯度。這意味著,在每一步都要移動生成器的權重,其移動方向是讓判別器更有可能將生成器解碼的圖像劃分為“真”。換句話說,我們訓練生成器來欺騙判別器。

      訓練gan的技巧

      訓練 GAN 和調節 GAN 實現的過程非常困難。你應該記住一些公認的技巧。與深度學習中的大部分內容一樣,這些技巧更像是煉金術而不是科學,它們是啟發式的指南,并沒有理論 的支持。這些技巧得到了一定程度的來自對現象的直觀理解的支持,經驗告訴我們,它們的效果都很好,但不一定適用于所有情況。

      下面是本節實現 GAN 生成器和判別器時用到的一些技巧。這里并沒有列出與 GAN 相關的 全部技巧,更多技巧可查閱關于 GAN 的文獻。

      我們使用 tanh 作為生成器最后一層的激活,而不用 sigmoid,后者在其他類型的模型中更加常見。

      我們使用正態分布(高斯分布)對潛在空間中的點進行采樣,而不用均勻分布。

      隨機性能夠提高穩健性。訓練 GAN 得到的是一個動態平衡,所以 GAN 可能以各種方式“卡住”。在訓練過程中引入隨機性有助于防止出現這種情況。我們通過兩種方式引入隨機性: 一種是在判別器中使用 dropout,另一種是向判別器的標簽添加隨機噪聲。

      稀疏的梯度會妨礙 GAN 的訓練。在深度學習中,稀疏性通常是我們需要的屬性,但在GAN 中并非如此。有兩件事情可能導致梯度稀疏:最大池化運算和 ReLU 激活。我們推薦使用步進卷積代替最大池化來進行下采樣,還推薦使用 LeakyReLU 層來代替 ReLU 激活。LeakyReLU 和 ReLU 類似,但它允許較小的負數激活值,從而放寬了稀疏性限制。

      在生成的圖像中,經常會見到棋盤狀偽影,這是由生成器中像素空間的不均勻覆蓋導致的。為了解決這個問題,每當在生成器和判別器中都使用步進的 Conv2DTranpose 或 Conv2D 時,使用的內核大小要能夠被步幅大小整除。

      生成器

      首先,我們來開發 generator 模型,它將一個向量(來自潛在空間,訓練過程中對其隨機采樣)轉換為一張候選圖像。GAN 常見的諸多問題之一,就是生成器“卡在”看似噪聲的生成圖像上。一種可行的解決方案是在判別器和生成器中都使用 dropout。

      import Keras

      from keras import layers

      import numpy as np

      latent_dim = 32

      height = 32

      width = 32

      channels = 3

      generator_input = keras.Input(shape=(latent_dim,))

      # First, transform the input into a 16x16 128-channels feature map

      # 將輸入轉換為大小為 16×16 的128 個通道的特征圖

      x = layers.Dense(128 * 16 * 16)(generator_input)

      x = layers.LeakyReLU()(x)

      x = layers.Reshape((16, 16, 128))(x)

      # Then, add a convolution layer(添加一個卷積層)

      x = layers.Conv2D(256, 5, padding='same')(x)

      x = layers.LeakyReLU()(x)

      # Upsample to 32x32(上采樣為 32×32)

      x = layers.Conv2DTranspose(256, 4, strides=2, padding='same')(x)

      x = layers.LeakyReLU()(x)

      從零開始學keras之生成對抗網絡GAN

      # Few more conv layers

      x = layers.Conv2D(256, 5, padding='same')(x)

      x = layers.LeakyReLU()(x)

      x = layers.Conv2D(256, 5, padding='same')(x)

      x = layers.LeakyReLU()(x)

      # Produce a 32x32 1-channel feature map(生成一個大小為 32×32 的單通道特征圖(即 CIFAR10 圖像的形狀))

      x = layers.Conv2D(channels, 7, activation='tanh', padding='same')(x)

      generator = keras.models.Model(generator_input, x)

      #將生成器模型實例化,它將形狀為 (latent_dim,)的輸入映射到形狀為 (32, 32, 3) 的圖像

      generator.summary()

      判別器

      接下來,我們來開發 discriminator 模型,它接收一張候選圖像(真實的或合成的)作為輸入,并將其劃分到這兩個類別之一:“生成圖像”或“來自訓練集的真實圖像”

      discriminator_input = layers.Input(shape=(height, width, channels))

      x = layers.Conv2D(128, 3)(discriminator_input)

      x = layers.LeakyReLU()(x)

      x = layers.Conv2D(128, 4, strides=2)(x)

      x = layers.LeakyReLU()(x)

      x = layers.Conv2D(128, 4, strides=2)(x)

      x = layers.LeakyReLU()(x)

      x = layers.Conv2D(128, 4, strides=2)(x)

      x = layers.LeakyReLU()(x)

      x = layers.Flatten()(x)

      # One dropout layer - important trick!

      # 一個 dropout 層:這是很重要的技巧

      x = layers.Dropout(0.4)(x)

      # Classification layer(判別層)

      x = layers.Dense(1, activation='sigmoid')(x)

      discriminator = keras.models.Model(discriminator_input, x)

      discriminator.summary()

      # To stabilize training, we use learning rate decay

      # and gradient clipping (by value) in the optimizer.

      # 將判別器模型實例化,它將形狀為 (32, 32, 3)的輸入轉換為一個二進制分類決策(真 / 假)

      discriminator_optimizer = keras.optimizers.RMSprop(lr=0.0008, clipvalue=1.0, decay=1e-8)

      # clipvalue=1.0:在優化器中使用梯度裁剪(限制梯度值的范圍)

      # decay=1e-8:為了穩定訓練過程,使用學習率衰減

      discriminator.compile(optimizer=discriminator_optimizer, loss='binary_crossentropy')

      對抗網絡

      最后,我們要設置 GAN,將生成器和判別器連接在一起。訓練時,這個模型將讓生成器向某個方向移動,從而提高它欺騙判別器的能力。這個模型將潛在空間的點轉換為一個分類決策(即 “真”或“假”),它訓練的標簽都是“真實圖像”。因此,訓練 gan 將會更新 generator 的權重, 使得 discriminator 在觀察假圖像時更有可能預測為“真”。請注意,有一點很重要,就是在訓練過程中需要將判別器設置為凍結(即不可訓練),這樣在訓練 gan 時它的權重才不會更新。 如果在此過程中可以對判別器的權重進行更新,那么我們就是在訓練判別器始終預測“真”,但這并不是我們想要的!

      # 將判別器權重設置為不可訓練(僅應用于 gan 模型)

      discriminator.trainable = False

      gan_input = keras.Input(shape=(latent_dim,))

      gan_output = discriminator(generator(gan_input))

      gan = keras.models.Model(gan_input, gan_output)

      gan_optimizer = keras.optimizers.RMSprop(lr=0.0004, clipvalue=1.0, decay=1e-8)

      gan.compile(optimizer=gan_optimizer, loss='binary_crossentropy')

      如何訓練DCGAN

      現在開始訓練。再次強調一下,訓練循環的大致流程如下所示。每輪都進行以下操作。

      (1) 從潛在空間中抽取隨機的點(隨機噪聲)。

      (2) 利用這個隨機噪聲用 generator 生成圖像。

      (3) 將生成圖像與真實圖像混合。

      (4) 使用這些混合后的圖像以及相應的標簽(真實圖像為“真”,生成圖像為“假”)來訓練discriminator。

      (5) 在潛在空間中隨機抽取新的點。

      (6) 使用這些隨機向量以及全部是“真實圖像”的標簽來訓練 gan。這會更新生成器的權重(只更新生成器的權重,因為判別器在 gan 中被凍結),其更新方向是使得判別器能夠將生成圖像預測為“真實圖像”。這個過程是訓練生成器去欺騙判別器。

      import os

      from keras.preprocessing import image

      # Load CIFAR10 data(加載 CIFAR10數據)

      (x_train, y_train), (_, _) = keras.datasets.cifar10.load_data()

      # Select frog images (class 6)(選擇青蛙圖像(類別編號為 6))

      x_train = x_train[y_train.flatten() == 6]

      # Normalize data(數據標準化)

      x_train = x_train.reshape(

      (x_train.shape[0],) + (height, width, channels)).astype('float32') / 255.

      iterations = 10000

      batch_size = 20

      save_dir = 'data/gan_images/'

      # 指定保存生成 圖像的目錄

      # Start training loop(開始循環)

      start = 0

      for step in range(iterations):

      # Sample random points in the latent space(在潛在空間中采樣隨機點)

      random_latent_vectors = np.random.normal(size=(batch_size, latent_dim))

      # Decode them to fake images(將這些點解碼為虛假圖像)

      generated_images = generator.predict(random_latent_vectors)

      # Combine them with real images(將這些虛假圖像與真實圖像合在一起)

      stop = start + batch_size

      real_images = x_train[start: stop]

      combined_images = np.concatenate([generated_images, real_images])

      # Assemble labels discriminating real from fake images

      #合并標簽,區分真實和虛假的圖像

      labels = np.concatenate([np.ones((batch_size, 1)),

      np.zeros((batch_size, 1))])

      # Add random noise to the labels - important trick!

      #向標簽中添加隨機噪聲,這是一個很重要的技巧

      labels += 0.05 * np.random.random(labels.shape)

      # Train the discriminator(訓練判別器)

      d_loss = discriminator.train_on_batch(combined_images, labels)

      # sample random points in the latent space(在潛在空間中采樣隨機點)

      random_latent_vectors = np.random.normal(size=(batch_size, latent_dim))

      # Assemble labels that say "all real images"(合并標簽,全部是“真實圖像”(這是在撒謊,通過 gan 模型)

      misleading_targets = np.zeros((batch_size, 1))

      # Train the generator (via the gan model,

      # where the discriminator weights are frozen)

      #來訓練生成器(此時凍結判別器權重)

      a_loss = gan.train_on_batch(random_latent_vectors, misleading_targets)

      start += batch_size

      if start > len(x_train) - batch_size:

      start = 0

      # Occasionally save / plot

      if step % 100 == 0:

      # Save model weights(保存模型權重)

      gan.save_weights('gan.h5')

      # Print metrics(將指標打印出來)

      print('discriminator loss at step %s: %s' % (step, d_loss))

      print('adversarial loss at step %s: %s' % (step, a_loss))

      # Save one generated image(保存一張生成圖像)

      img = image.array_to_img(generated_images[0] * 255., scale=False)

      img.save(os.path.join(save_dir, 'generated_frog' + str(step) + '.png'))

      # Save one real image, for comparison(保存一張真實圖像,用于對比)

      img = image.array_to_img(real_images[0] * 255., scale=False)

      img.save(os.path.join(save_dir, 'real_frog' + str(step) + '.png'))

      下面展示生成的圖像

      import matplotlib.pyplot as plt

      # sample random points in the latent space(在潛在空間中采樣隨機點)

      random_latent_vectors = np.random.normal(size=(10, latent_dim))

      # Decode them to fake images(將這些點解碼為虛假圖像)

      generated_images = generator.predict(random_latent_vectors)

      for i in range(generated_images.shape[0]):

      img = image.array_to_img(generated_images[i] * 255., scale=False)

      plt.figure()

      plt.imshow(img)

      plt.show()

      Keras 機器學習 深度學習

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel表格怎樣添加水印圖片背景
      下一篇:怎么同一個表格里不同sheet表相加(不同sheet數據引用到同一張表格)
      相關文章
      另类小说亚洲色图| 亚洲日本香蕉视频| 亚洲人成网亚洲欧洲无码| 亚洲午夜久久影院| 亚洲精品无码高潮喷水在线| 综合一区自拍亚洲综合图区| 亚洲中文字幕无码av永久| 亚洲av永久综合在线观看尤物| 亚洲AV无码久久精品蜜桃| 国产偷v国产偷v亚洲高清| 国产日产亚洲系列| 国产亚洲精品国看不卡| 亚洲伊人久久综合影院| 最新精品亚洲成a人在线观看| 国产亚洲?V无码?V男人的天堂 | 亚洲免费在线视频播放| 亚洲宅男天堂a在线| 亚洲免费在线视频观看| 2019亚洲午夜无码天堂| 亚洲字幕AV一区二区三区四区| 亚洲最大av资源站无码av网址| 亚洲色www永久网站| 亚洲精品蜜夜内射| 国产成人精品亚洲一区| 亚洲国产午夜福利在线播放| 国产精品亚洲αv天堂无码| 亚洲一区二区三区无码中文字幕 | 麻豆亚洲AV永久无码精品久久| 亚洲精品福利在线观看| 亚洲人成伊人成综合网久久| 亚洲天堂一区二区三区四区| 精品久久亚洲中文无码| 亚洲精品理论电影在线观看| 午夜亚洲乱码伦小说区69堂| 国产亚洲精品激情都市| 亚洲AV乱码一区二区三区林ゆな| 亚洲人成电影福利在线播放 | 亚洲成人黄色在线| 亚洲日韩一区二区三区| 国产AV日韩A∨亚洲AV电影| 久久精品夜色噜噜亚洲A∨|