[深度學習][Python]DCGAN訓練生成手寫阿拉伯數字_訓練篇

更新於 2024/07/27閱讀時間約 21 分鐘

本文參考TensorFlo官網Deep Convolutional Generative Adversarial Network的程式碼來加以實作說明。

示範如何使用深度卷積生成對抗網路(DCGAN) 生成手寫數位影像。程式碼是使用帶有訓練循環的Keras Sequential APItf.GradientTape編寫的。

使用 MNIST 資料集來訓練生成器和判別器。生成器將生成類似於 MNIST 資料的手寫數字。

動畫顯示

以下動畫顯示了生成器經過 50 個 epoch 訓練後生成的一系列圖像。這些圖像一開始是隨機噪聲,隨著時間的推移越來越像手寫數字。

訓練過程50次的過程

訓練過程50次的過程


本文在Colab上執行訓練,因本機電腦過於老舊XD

Python及套件版本

Python version: 3.10.12
imageio version: 2.34.2
matplotlib version: 3.7.1
numpy version: 1.25.2
PIL version: 9.4.0
tensorflow version: 2.15.0
IPython version: 7.34.0

1.載入相關套件

import glob
import imageio
import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf
from tensorflow.keras import layers
import time
from IPython import display

2. 載入訓練資料

# 取得 MNIST 訓練資料
(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
# 像素標準化
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5 # 使像素值介於 [-1, 1]

# 參數設定
BUFFER_SIZE = 60000 # 緩衝區大小
BATCH_SIZE = 256 # 訓練批量

# 轉為 Dataset
train_dataset = tf.data.Dataset.from_tensor_slices(train_images) \
.shuffle(BUFFER_SIZE).batch(BATCH_SIZE).prefetch(BUFFER_SIZE).cache()

3. 定義GAN模型

3.1 定義生成模型

將從一個隨機噪聲向量中生成28x28圖像

# 生成神經網路
def make_generator_model():
model = tf.keras.Sequential()
# 第一層 Dense
#輸入是一個100維的隨機向量,輸出是7x7x256個特徵圖(feature maps)。
model.add(layers.Dense(7*7*256, use_bias=False, input_shape=(100,)))
#對輸出進行批量標準化(Batch Normalization),有助於穩定和加速訓練過程。
model.add(layers.BatchNormalization())
#應用Leaky ReLU激活函數,這是一種具有輕微負斜率的ReLU激活函數,可以解決ReLU的“死亡神經元”問題
model.add(layers.LeakyReLU())
​​#將輸出重塑為7x7x256的形狀,以便於後續的卷積操作。
model.add(layers.Reshape((7, 7, 256)))
#檢查
assert model.output_shape == (None, 7, 7, 256) # None 代表批量不檢查
# 第一層 Conv2DTranspose​
# 將低分辨率的特徵圖轉換為高分辨率的特徵圖
model.add(layers.Conv2DTranspose(128, (5, 5), strides=(1, 1),
padding='same', use_bias=False))
assert model.output_shape == (None, 7, 7, 128)
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
# 第二層 Conv2DTranspose​
model.add(layers.Conv2DTranspose(64, (5, 5), strides=(2, 2),
padding='same', use_bias=False))
assert model.output_shape == (None, 14, 14, 64)
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
# 第三層 Conv2DTranspose​
# 將特徵圖尺寸放大到28x28,並使用'tanh'激活函數將輸出範圍限制在[-1, 1]之間。​
model.add(layers.Conv2DTranspose(1, (5, 5), strides=(2, 2),
padding='same', use_bias=False, activation='tanh'))
assert model.output_shape == (None, 28, 28, 1)

return model

顯示生成雜訊

# 產生生成神經網路
generator = make_generator_model()

# 測試產生的雜訊
noise = tf.random.normal([1, 100])
generated_image = generator(noise, training=False)

# 顯示雜訊生成的圖像
plt.imshow(generated_image[0, :, :, 0], cmap='gray')
raw-image

3.2 定義判別器模型

判别器模型在訓練過程中會學習區分真實圖像和生成圖像,並將其用於改進生成器模型,使得生成的圖像越來越真實。

# 判别神經網路
def make_discriminator_model():
model = tf.keras.Sequential() #定義模型:使用tf.keras.Sequential定義了一個順序模型。
model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same',
input_shape=[28, 28, 1])) #卷積層, 輸入28*28
model.add(layers.LeakyReLU()) #使用Leaky ReLU作為激活函數
model.add(layers.Dropout(0.3)) #應用Dropout層,隨機丟棄30%的神經元,防止過擬

model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
model.add(layers.LeakyReLU())
model.add(layers.Dropout(0.3))

model.add(layers.Flatten()) # 全連接層(Dense layer)
model.add(layers.Dense(1)) #一個神經元的全連接層,輸出一個單一的實值,用於判斷輸入圖像是真實還是生成的。

return model

測試判別器功能

# 測試判别神經網路
discriminator = make_discriminator_model()

# 預測值越大代表越像
decision = discriminator(generated_image)
print (f'預測值={decision}')
raw-image

4.定義損失函數及優化器

# 使用 TensorFlow 定義的二分類交叉熵損失函數
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)

# 定義判别神經網路損失函數為 真實影像 + 生成影像 的損失函數
def discriminator_loss(real_output, fake_output):
'''
真實影像損失 (real_loss):
這部分計算真實影像的損失,即將真實影像的輸出與全為1的標籤比較。
生成影像損失 (fake_loss):
這部分計算生成影像的損失,即將生成影像的輸出與全為0的標籤比較。
'''
real_loss = cross_entropy(tf.ones_like(real_output), real_output)
fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
total_loss = real_loss + fake_loss
return total_loss

# 定義生成神經網路損失函數為 生成影像 的損失函數
def generator_loss(fake_output):
#將生成影像的輸出與全為1的標籤比較。生成器的目標是騙過判别器,使其認為生成的影像是真實的,因此使用全1標籤。
return cross_entropy(tf.ones_like(fake_output), fake_output)

# 優化器均為 Adam
generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

5.儲存檢查點

儲存和復原模型,這在長時間運行的訓練任務中斷時非常有用。

checkpoint_dir = './dcgan_training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt")
checkpoint = tf.train.Checkpoint(generator_optimizer=generator_optimizer,
discriminator_optimizer=discriminator_optimizer,
generator=generator,
discriminator=discriminator)
在Colab儲存示意圖

在Colab儲存示意圖


6.參數設定

這樣的設計確保了生成器和判别器在每個訓練步驟中都能相互對抗,從而提升生成影像的質量。

# 參數設定
EPOCHS = 50 # 訓練執行週期,即整個訓練資料集將被完整地訓練50次。
noise_dim = 100 # 雜訊向量大小,這個向量將作為生成神經網路的輸入。
num_examples_to_generate = 16 # 每次生成的樣本數量。

# 產生亂數(雜訊)'
seed = tf.random.normal([num_examples_to_generate, noise_dim])

# 定義梯度下降,分別對判别神經網路、生成神經網路進行訓練
@tf.function # 產生運算圖 裝飾器將函數編譯成 TensorFlow 運算圖以提高性能。
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])

with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
# 生成神經網路進行訓練
generated_images = generator(noise, training=True)

# 判别神經網路進行訓練
real_output = discriminator(images, training=True) # 真實影像
fake_output = discriminator(generated_images, training=True) # 生成影像

# 計算損失
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)

# 梯度下降
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = disc_tape.gradient(disc_loss,
discriminator.trainable_variables)

# 更新權重
generator_optimizer.apply_gradients(zip(gradients_of_generator,
generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator,
discriminator.trainable_variables))

7.定義訓練函數及產生圖像並存檔

def train(dataset, epochs):
for epoch in range(epochs):
start = time.time()

for image_batch in dataset:
train_step(image_batch)

# 產生圖像
display.clear_output(wait=True)
generate_and_save_images(generator, epoch + 1, seed)

# 每 10 個執行週期存檔一次
if (epoch + 1) % 10 == 0:
checkpoint.save(file_prefix = checkpoint_prefix)

print ('epoch {} 花費 {} 秒'.format(epoch + 1, time.time()-start))

# 顯示最後結果
display.clear_output(wait=True)
generate_and_save_images(generator, epochs, seed)

# 產生圖像並存檔
def generate_and_save_images(model, epoch, test_input):
# 預測
predictions = model(test_input, training=False)

# 顯示 4x4 的格子
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('./GAN_result/image_at_epoch_{:04d}.png'.format(epoch))
plt.show()

8.訓練模型

#產生儲存結果的資料夾
import os
if not os.path.exists('./GAN_result'):
  os.makedirs('./GAN_result'

train(train_dataset, EPOCHS) #需要一段時間

9.顯示結果

# 顯示最後結果
def display_image(epoch_no):
return PIL.Image.open('./GAN_result/image_at_epoch_{:04d}.png'.format(epoch_no))

display_image(EPOCHS)

10.將訓練過程的存檔圖像轉為GIF 檔,並顯示GIF檔

要先安裝tensorflow_docs才可以使用它的embed在colab上顯示gif檔

!pip install git+https://github.com/tensorflow/docs
# 產生 GIF
anim_file = './GAN_result/dcgan.gif'
with imageio.get_writer(anim_file, mode='I') as writer: #創建一個 GIF 檔案的寫入器​
filenames = glob.glob('./GAN_result/image*.png') #使用 glob.glob 搜尋符合 image*.png 的所有檔案名稱
filenames = sorted(filenames)
for filename in filenames:
# print(filename)
image = imageio.imread(filename)
writer.append_data(image)

# 顯示 GIF
import tensorflow_docs.vis.embed as embed

embed.embed_file(anim_file)

11.儲存模型

generator.save('DCGAN.h5')


參考文獻


avatar-img
128會員
209內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
本文將延續上一篇文章,經由訓練好的GAN模型中的生成器來生成圖片 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 [深度學習][Python]訓練CNN的GAN模型來生成圖片_訓練篇 相較之下CNN的GAN生成的效果比較好,但模型也相對比較複雜,訓練時間花的也比較
延續上一篇訓練GAM模型,這次我們讓神經網路更多層更複雜一點,來看訓練生成的圖片是否效果會更好。 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 資料集分割處理的部分在延續上篇文章,從第五點開始後修改即可,前面都一樣 訓練過程,比較圖 是不是CNN的效果比MLP還要好,
本文主要介紹,如何利用GAN生成對抗網路來訓練生成圖片。 利用tensorflow,中的keras來建立生成器及鑑別器互相競爭訓練,最後利用訓練好的生成器來生成圖片。 GAN生成對抗網路的介紹 它由生成網路(Generator Network)和鑑別網路(Discriminator Netwo
本文將延續上一篇文章,經由訓練好的VAE模型其中的解碼器,來生成圖片。 [深度學習]訓練VAE模型用於生成圖片_訓練篇 輸入產生的隨機雜訊,輸入VAE的解碼器後,生成的圖片
本文主要介紹,如何利用VAE變分自編碼器來訓練生成圖片。 訓練集資料將採用TF影像資料庫中的fashion_mnist VAE變分自編碼器簡單介紹 •VAE(Variational Auto-Encoder)中文名稱變分自編碼器,主要是一種將原始資料編碼到潛在向量空間,再編碼回來的神經網路。
本文下方連結的文章,利用Stable Diffusion生成512 * 512大小的圖片。 輸入的文字是 dog flying in space,此模型需輸入英文句子才會準確生成。 參考文獻 連結該作者在Hugging Face公開的模型去做使用。 本文是在Colab上執行。
本文將延續上一篇文章,經由訓練好的GAN模型中的生成器來生成圖片 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 [深度學習][Python]訓練CNN的GAN模型來生成圖片_訓練篇 相較之下CNN的GAN生成的效果比較好,但模型也相對比較複雜,訓練時間花的也比較
延續上一篇訓練GAM模型,這次我們讓神經網路更多層更複雜一點,來看訓練生成的圖片是否效果會更好。 [深度學習][Python]訓練MLP的GAN模型來生成圖片_訓練篇 資料集分割處理的部分在延續上篇文章,從第五點開始後修改即可,前面都一樣 訓練過程,比較圖 是不是CNN的效果比MLP還要好,
本文主要介紹,如何利用GAN生成對抗網路來訓練生成圖片。 利用tensorflow,中的keras來建立生成器及鑑別器互相競爭訓練,最後利用訓練好的生成器來生成圖片。 GAN生成對抗網路的介紹 它由生成網路(Generator Network)和鑑別網路(Discriminator Netwo
本文將延續上一篇文章,經由訓練好的VAE模型其中的解碼器,來生成圖片。 [深度學習]訓練VAE模型用於生成圖片_訓練篇 輸入產生的隨機雜訊,輸入VAE的解碼器後,生成的圖片
本文主要介紹,如何利用VAE變分自編碼器來訓練生成圖片。 訓練集資料將採用TF影像資料庫中的fashion_mnist VAE變分自編碼器簡單介紹 •VAE(Variational Auto-Encoder)中文名稱變分自編碼器,主要是一種將原始資料編碼到潛在向量空間,再編碼回來的神經網路。
本文下方連結的文章,利用Stable Diffusion生成512 * 512大小的圖片。 輸入的文字是 dog flying in space,此模型需輸入英文句子才會準確生成。 參考文獻 連結該作者在Hugging Face公開的模型去做使用。 本文是在Colab上執行。
你可能也想看
Google News 追蹤
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
前言 最近在研究GAT,在網路上看到使用torch和DGL實作的GAT模型的程式碼,就想說下載下來自己跑跑看,這篇文章:Understand Graph Attention Network。途中遇到問題,把找到的解法記錄下來,給也有一樣問題的朋友參考。 正文 在Colab直接使用: !p
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 Google Brain 開發了 Tensor2Tensor(T2T),讓深度學習開發變得更加容易,T2T 是 TensorFlow 的擴展,包含深度學習模型庫,其中包
Thumbnail
前言 讀了許多理論,是時候實際動手做做看了,以下是我的模型訓練初體驗,有點糟就是了XD。 正文 def conv(filters, kernel_size, strides=1): return Conv2D(filters, kernel_size,
Thumbnail
此篇調查論文探討了Diffusion模型在文字、圖片和聲音轉換為影片,以及影片衍生和編輯的應用類型。作者也介紹了U-Net架構和Vision Transformer等生成圖像架構,並詳細探討了訓練模型的方法以及不同的影像資料集來源。
Thumbnail
VQGAN是一種基於GAN(生成對抗式網路)的生成式模型,可以創造新的、逼真的圖像或修改已有圖像。本論文介紹了改進VQGAN用於StableDiffusion中的新方法架構,並提出了一種新的非對稱式VQGAN,具有更強的解碼器和兩個設計條件解碼器。論文下方另附相關資料連結。
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 Transformers for Natural Language Processing and Computer Vision, 2024 這本書中講 Decoder
前言 在閱讀《強化式學習:打造最強 AlphaZero 通用演算法》時,對一些看似基本,但是重要且會影響到之後實作的項目概念有點疑惑,覺得應該查清楚,所以搞懂後記錄下來,寫下這篇文章(應該說是筆記?)。 正文 下面這段程式碼: model = Sequential() model.add
為了將輸入文本轉換成深度學習模型可以使用的嵌入向量, 我們需要先將「輸入文本 Input Text」轉為「符元化文本 Tokenized Text」。 而實際上「符元化文本 Tokenized Text」與「嵌入向量 Embedding Vector」之間, 還有一個步驟稱為「符元
Thumbnail
這篇文章探討了生成式對抗網路中機率分佈的使用與相關的訓練方式,包括Generator不同的點、Distriminator的訓練過程、生成圖片的條件設定等。此外,也提到了GAN訓練的困難與解決方式以及不同的learning方式。文章內容豐富且詳細,涵蓋了GAN的各個相關面向。
Thumbnail
徵的就是你 🫵 超ㄅㄧㄤˋ 獎品搭配超瞎趴的四大主題,等你踹共啦!還有機會獲得經典的「偉士牌樂高」喔!馬上來參加本次的活動吧!
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
前言 最近在研究GAT,在網路上看到使用torch和DGL實作的GAT模型的程式碼,就想說下載下來自己跑跑看,這篇文章:Understand Graph Attention Network。途中遇到問題,把找到的解法記錄下來,給也有一樣問題的朋友參考。 正文 在Colab直接使用: !p
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 Google Brain 開發了 Tensor2Tensor(T2T),讓深度學習開發變得更加容易,T2T 是 TensorFlow 的擴展,包含深度學習模型庫,其中包
Thumbnail
前言 讀了許多理論,是時候實際動手做做看了,以下是我的模型訓練初體驗,有點糟就是了XD。 正文 def conv(filters, kernel_size, strides=1): return Conv2D(filters, kernel_size,
Thumbnail
此篇調查論文探討了Diffusion模型在文字、圖片和聲音轉換為影片,以及影片衍生和編輯的應用類型。作者也介紹了U-Net架構和Vision Transformer等生成圖像架構,並詳細探討了訓練模型的方法以及不同的影像資料集來源。
Thumbnail
VQGAN是一種基於GAN(生成對抗式網路)的生成式模型,可以創造新的、逼真的圖像或修改已有圖像。本論文介紹了改進VQGAN用於StableDiffusion中的新方法架構,並提出了一種新的非對稱式VQGAN,具有更強的解碼器和兩個設計條件解碼器。論文下方另附相關資料連結。
Thumbnail
我想要一天分享一點「LLM從底層堆疊的技術」,並且每篇文章長度控制在三分鐘以內,讓大家不會壓力太大,但是又能夠每天成長一點。 Transformers for Natural Language Processing and Computer Vision, 2024 這本書中講 Decoder
前言 在閱讀《強化式學習:打造最強 AlphaZero 通用演算法》時,對一些看似基本,但是重要且會影響到之後實作的項目概念有點疑惑,覺得應該查清楚,所以搞懂後記錄下來,寫下這篇文章(應該說是筆記?)。 正文 下面這段程式碼: model = Sequential() model.add
為了將輸入文本轉換成深度學習模型可以使用的嵌入向量, 我們需要先將「輸入文本 Input Text」轉為「符元化文本 Tokenized Text」。 而實際上「符元化文本 Tokenized Text」與「嵌入向量 Embedding Vector」之間, 還有一個步驟稱為「符元
Thumbnail
這篇文章探討了生成式對抗網路中機率分佈的使用與相關的訓練方式,包括Generator不同的點、Distriminator的訓練過程、生成圖片的條件設定等。此外,也提到了GAN訓練的困難與解決方式以及不同的learning方式。文章內容豐富且詳細,涵蓋了GAN的各個相關面向。