本文主要介紹,如何利用VAE變分自編碼器來訓練生成圖片。
訓練集資料將採用TF影像資料庫中的fashion_mnist
•VAE(Variational Auto-Encoder)中文名稱變分自編碼器,主要是一種將原始資料編碼到潛在向量空間,再編碼回來的神經網路。
Python version: 3.10.12
NumPy version: 1.25.2
Pandas version: 2.0.3
Matplotlib version: 3.7.1
TensorFlow version: 2.15.0
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.datasets import fashion_mnist
(x_train_set, y_train_set), (x_test, y_test) = fashion_mnist. load_data()
x_train_set = x_train_set / 255.0x_test = x_test / 255.0
顯示隨便一張圖
i = 5
print (y_train_set [i])
plt. imshow(x_train_set[i], cmap='binary')
plt.show()
主要分出訓練跟驗證集
from sklearn.model_selection import train_test_split
x_train, x_valid, y_train, y_valid = train_test_split(x_train_set, y_train_set,
class Sampling (keras.layers.Layer): #用於從潛在空間中進行采樣
def call(self, inputs):
mean, log_var = inputs
#ε 是從標準常態分配中抽出的,其個數必須和(log σ**2)一致
e = tf. random. normal(tf.shape (log_var))
# Z = μ + ε * exp(log σ**2/2)
# 最終的潛在變量,這樣生成的潛在變量具有正確的均值和方差。
return mean + e * tf.math.exp (log_var / 2)
#清除背景舊模型
keras.backend.clear_session() #清除背景舊模型
# 設置隨機種子
# 設置 TensorFlow 和 NumPy 的隨機種子,以確保實驗的可重現性
tf.random.set_seed(1)
np.random.seed (1)
#定義編碼器模型
d = 10#代表最后輸出時的數量
in_en = keras. layers. Input (shape= [28, 28])
#因結構特殊,不能使用Sequential,改用Functional方式
c = keras.layers.Flatten() (in_en)#(in_en)代表輸入層,要傳到Flatten層
c = keras.layers.Dense (150, activation="selu")(c)
c = keras.layers.Dense(100, activation="selu")(c)
c_mean = keras.layers.Dense(d)(c)
c_log_var = keras.layers.Dense(d)(c)
out_en = Sampling()([c_mean, c_log_var])
var_encoder = keras.models.Model(inputs= [in_en], outputs= [out_en])
var_encoder.summary()
#in_de:定義了解碼器的輸入層,形狀為 [d],其中 d 是潛在空間的維度(與編碼器中的輸出一致)
in_de = keras.layers.Input (shape= [d])
x = keras. layers.Dense(100, activation="selu")(in_de)
x = keras. layers.Dense(150, activation="selu")(x)
x = keras. layers.Dense(28 * 28, activation="sigmoid")(x)
# Reshape 層:將展平的輸出轉換回 [28, 28] 的形狀,即恢復為原始圖像的形狀。
out_de = keras.layers.Reshape( [28, 28])(x)
var_decoder = keras.models.Model(inputs=[in_de], outputs=[out_de])
codings = var_encoder(in_en) #通過編碼器 var_encoder 將輸入 in_en 轉換為潛在變量。
rec = var_decoder (codings) #通過解碼器 var_decoder 將潛在變量 codings 重建回圖像空間。
# 建立一個變分自編碼器(Variational Autoencoder, VAE)的完整模型
# 其輸入為 in_en(原始圖像),輸出為 rec(重建的圖像)
var_ae = keras.models.Model(inputs=[in_en], outputs= [rec])
var_ae.summary()
損失函數、優化器和評估指標的設置後,模型需要被編譯,才能進行訓練。
D_KL = -0.5 * tf. math. reduce_sum (
#公式:∑(1+log σ**2 - σ**2 - μ**2) ; σ**2 = exp(log σ**2)
1 + c_log_var - tf. math.exp (c_log_var) - tf.math. square (c_mean),
axis=1)
#所有累加值求平均
latent_loss = tf.math.reduce_mean(D_KL) / 784.0 #784個神經元
var_ae.add_loss(latent_loss)
def rounded_accuracy (y_true, y_pred):
# binary_accuracy用來計算二類分類問題的準確率。準確率是指預測值與真實標籤相匹配的比例。
return keras.metrics.binary_accuracy(tf.round (y_true), tf. round (y_pred)
loss='binary_crossentropy'
:設置模型的損失函數為二元交叉熵,適合二類分類問題。optimizer='rmsprop'
:使用 RMSprop 優化器來更新模型的權重。metrics=[rounded_accuracy]
:設置自定義的準確率指標 rounded_accuracy
來監控模型在訓練過程中的性能。var_ae.compile(loss='binary_crossentropy',
optimizer="rmsprop",
metrics= [rounded_accuracy])
x_train
:這是模型的訓練數據,通常是原始圖像或數據集。
x_train
:作為第二個參數:在自編碼器(包括變分自編碼器)中,訓練數據的輸入和目標是相同的,因為目標是將輸入數據重建回來。因此,這裡的 x_train
既是輸入數據也是目標數據。
epochs
:訓練過程中完整遍歷訓練數據集的次數。這裡設定為 20,表示將訓練 20 個循環(每個循環都遍歷一次完整的訓練數據集)。
validation_data
:這是用於模型驗證的數據集。與訓練數據類似,驗證數據的輸入和目標也是相同的。
train = var_ae.fit(x_train, x_train,
epochs=20, batch_size=256,
validation_data=(x_valid, x_valid))
#將這些歷史數據轉換為 Pandas DataFrame,以便於進行進一步的分析和可視化。
pd.DataFrame(train.history).plot()
plt.grid(True)
plt.show()
返回損失值及準確率
var_ae.evaluate(x_test, x_test)
將前 5 個測試樣本的原始圖像和相應的重建圖像並排顯示,以比較模型的重建效果。
這是評估變分自編碼器性能的一個直觀方法,幫助你檢查模型是否能夠有效地重建圖像,並理解其在數據生成方面的能力。
plt.figure(figsize=(10, 4))
j = 0
for i in range (5,10): #印出 第六筆到第十筆
plt.subplot(2, 5, 1 + j)#編號 1開始
plt.imshow(x_test[i], cmap='binary')
plt.title('original')
plt.axis('off')
plt.subplot(2, 5, 1 + 5 + j)#編號 6開始
plt.imshow (x_test_decoded [i], cmap='binary')
plt.title('reconstructed')
plt.axis('off')
j += 1
print(j)
plt.show()
var_decoder.save('var_decoder.h5')