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

閱讀時間約 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')


參考文獻


113會員
172Content count
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
發表第一個留言支持創作者!
螃蟹_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上執行。
你可能也想看
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
在現今少子化的時代,提升學習效率至關重要。卡爾·紐波特的書《DEEP WORK深度工作力》提供了有效的時間管理和學習策略,能夠幫助我們在競爭激烈的社會中脫穎而出。書中介紹的學習方法和策略,不僅適用於大學生,也可應用在日常生活中,幫助我們擁有良好的學習力,增進生活效率。
Thumbnail
本文介紹了self-attention在處理不固定大小輸入值時的應用,並討論瞭如何計算self-attention以及transformer中的multi-head self-attention。此外,文章還探討了在語音辨識和圖片處理中使用self-attention的方法,以及與CNN的比較。
Thumbnail
這本書訪談了大學學生,並且歸納出幾點建議,書中也提到不必每條條都嚴格遵守,而是選擇一組吸引你的規則,並在大學生活中履行。 我自己在看這本書的時候,結合自己的大學經歷,選取幾點我比較有感觸的部分,分為以下幾點,後面則會提到一些關於書中內容反思
Thumbnail
透過麗鳳督導在心理諮商上的應用,能夠讓我們看待個案問題時有了全新的視角。學理論要浸泡到自動化思考,分析個案時需要考慮家庭結構、互動關係和人際界線等重要元素。此外,心理諮商師需用關係去理解表徵問題,並運用大量的探問與對話,從而從症狀到系統的探索。
Thumbnail
不是只是硬記硬背,而是要用對方法。學習,不分年紀,不分時候,我們隨時都在學習,但有良好的學習技能,像故事/小說書中,電影裡那些擁有超能力的人一樣,可以在自己想學的技能中,一眼就記住,過目不忘的技能,如果擁有或許也是一件不錯的事,但切換到現實,我們認真學習,雖然也能記住,但所要花費的時間成本...
深度學習是機器學習的一個分支,它使用多層神經網絡來模擬和解決複雜的問題。有許多不同的深度學習框架可供選擇,這些框架提供了用於訓練神經網絡的工具和函數。以下是一些常用的深度學習框架的簡介: TensorFlow: TensorFlow由Google開發,是最流行的深度學習框架之一。它具有靈活的計算
Thumbnail
如何與錯誤打交道,就是對於自身的錯誤的察覺,又或者是對於所學的知識正確性如何思辨。 大家好,今天我們來談談「第二層思考」。這是一個相當重要的概念,尤其在現代社會中,我們需要面對各種各樣的資訊和知識,但有時候這些資訊和知識並不是那麼正確。所以,我們必須學會用第二層思考去判斷和分析這些資訊和知識。 首先
Thumbnail
「品酒」已經不再是有錢人的權利,在這個美酒當道的年代,我們要如何像 Somm 電影的品酒師,一口就能辨別出「口感」、「年份」、「產地」,甚至預測下一季爆款的酒呢? 情境: 這時候,機器學習與深度學習都是相當好的辦法,但我們要成為好的品酒工程師之前,我們必須學會理解「數據來源」、「產業知識」、「演算法
Thumbnail
師範大學的 陳佩英 教授來訪均一! 讓我們有機會向教授請益有關個人化學習的前瞻發展可能性。 教授很親切給予我們許多建言與引導,聽完教授的回饋,有三個小心得: 真的覺得自己懂得不過廣泛,也不夠深啊! 2. 也很喜歡教授提醒我們要注意工具背後的教育理念。 a. 特別是對非認知能力的評量,不能用行為主義來
Thumbnail
是什麼讓一個人的成長速度比另一個人更快呢? 《深度學習的技術》的作者楊大輝的答案是:學習的深淺。
Thumbnail
重點摘要: 1.9 月降息 2 碼、進一步暗示年內還有 50 bp 降息 2.SEP 上修失業率預期,但快速的降息速率將有助失業率觸頂 3.未來幾個月經濟數據將繼續轉弱,經濟復甦的時點或是 1Q25 季底附近
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
在現今少子化的時代,提升學習效率至關重要。卡爾·紐波特的書《DEEP WORK深度工作力》提供了有效的時間管理和學習策略,能夠幫助我們在競爭激烈的社會中脫穎而出。書中介紹的學習方法和策略,不僅適用於大學生,也可應用在日常生活中,幫助我們擁有良好的學習力,增進生活效率。
Thumbnail
本文介紹了self-attention在處理不固定大小輸入值時的應用,並討論瞭如何計算self-attention以及transformer中的multi-head self-attention。此外,文章還探討了在語音辨識和圖片處理中使用self-attention的方法,以及與CNN的比較。
Thumbnail
這本書訪談了大學學生,並且歸納出幾點建議,書中也提到不必每條條都嚴格遵守,而是選擇一組吸引你的規則,並在大學生活中履行。 我自己在看這本書的時候,結合自己的大學經歷,選取幾點我比較有感觸的部分,分為以下幾點,後面則會提到一些關於書中內容反思
Thumbnail
透過麗鳳督導在心理諮商上的應用,能夠讓我們看待個案問題時有了全新的視角。學理論要浸泡到自動化思考,分析個案時需要考慮家庭結構、互動關係和人際界線等重要元素。此外,心理諮商師需用關係去理解表徵問題,並運用大量的探問與對話,從而從症狀到系統的探索。
Thumbnail
不是只是硬記硬背,而是要用對方法。學習,不分年紀,不分時候,我們隨時都在學習,但有良好的學習技能,像故事/小說書中,電影裡那些擁有超能力的人一樣,可以在自己想學的技能中,一眼就記住,過目不忘的技能,如果擁有或許也是一件不錯的事,但切換到現實,我們認真學習,雖然也能記住,但所要花費的時間成本...
深度學習是機器學習的一個分支,它使用多層神經網絡來模擬和解決複雜的問題。有許多不同的深度學習框架可供選擇,這些框架提供了用於訓練神經網絡的工具和函數。以下是一些常用的深度學習框架的簡介: TensorFlow: TensorFlow由Google開發,是最流行的深度學習框架之一。它具有靈活的計算
Thumbnail
如何與錯誤打交道,就是對於自身的錯誤的察覺,又或者是對於所學的知識正確性如何思辨。 大家好,今天我們來談談「第二層思考」。這是一個相當重要的概念,尤其在現代社會中,我們需要面對各種各樣的資訊和知識,但有時候這些資訊和知識並不是那麼正確。所以,我們必須學會用第二層思考去判斷和分析這些資訊和知識。 首先
Thumbnail
「品酒」已經不再是有錢人的權利,在這個美酒當道的年代,我們要如何像 Somm 電影的品酒師,一口就能辨別出「口感」、「年份」、「產地」,甚至預測下一季爆款的酒呢? 情境: 這時候,機器學習與深度學習都是相當好的辦法,但我們要成為好的品酒工程師之前,我們必須學會理解「數據來源」、「產業知識」、「演算法
Thumbnail
師範大學的 陳佩英 教授來訪均一! 讓我們有機會向教授請益有關個人化學習的前瞻發展可能性。 教授很親切給予我們許多建言與引導,聽完教授的回饋,有三個小心得: 真的覺得自己懂得不過廣泛,也不夠深啊! 2. 也很喜歡教授提醒我們要注意工具背後的教育理念。 a. 特別是對非認知能力的評量,不能用行為主義來
Thumbnail
是什麼讓一個人的成長速度比另一個人更快呢? 《深度學習的技術》的作者楊大輝的答案是:學習的深淺。