下面是完整的类代码及其实现示例。
import tensorflow as tf
import numpy as np
import time
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.applications.inception_v3 import preprocess_input
from scipy.linalg import sqrtm
class ImageGAN:
"""
Classe pour construire un GAN (Generative Adversarial Network) pour la génération d'images en utilisant TensorFlow.
Paramètres :
- generator : Modèle TensorFlow représentant le générateur du GAN.
- discriminator : Modèle TensorFlow représentant le discriminateur du GAN.
- noise_dim : Dimension du vecteur de bruit d'entrée du générateur.
- batch_size : Taille des mini-lots pour l'entraînement.
- epochs : Nombre d'epochs pour l'entraînement.
- learning_rate : Taux d'apprentissage pour l'optimiseur.
- verbose : Booléen indiquant s'il faut afficher les informations de progression à chaque epoch.
- fid_samples : Nombre d'échantillons pour le calcul de la FID.
- spectral_regularization : Booléen indiquant s'il faut appliquer la régularisation spectrale.
- metric : Métrique d'évaluation à utiliser (parmi 'fid', 'inception_score', 'kid', 'mse').
- conditional : Booléen indiquant si l'architecture doit être conditionnelle.
- use_adamw : Booléen indiquant si l'optimiseur AdamW doit être utilisé.
Méthodes :
- fit : Entraîne le GAN sur les données fournies.
- generate_images : Génère des images à l'aide du générateur entraîné.
- calculate_metric : Calcule la métrique d'évaluation spécifiée entre les images réelles et générées.
Exemple d'utilisation :
# Création du générateur et du discriminateur basés sur StyleGAN2
generator = build_stylegan2_generator(...)
discriminator = build_stylegan2_discriminator(...)
# Création de l'instance de la classe ImageGAN avec des options avancées
gan = ImageGAN(generator, discriminator, noise_dim=512, batch_size=32, epochs=100, learning_rate=0.0002,
verbose=True, fid_samples=1000, spectral_regularization=True, metric='fid', conditional=False,
use_adamw=True)
# Entraînement du GAN sur des données réelles
gan.fit(real_images)
# Génération d'images à l'aide du générateur entraîné
generated_images = gan.generate_images(10)
# Calcul de la métrique d'évaluation entre les images réelles et générées
metric_score = gan.calculate_metric(real_images, num_samples=1000)
"""
def __init__(self, generator, discriminator, noise_dim, batch_size=64, epochs=100, learning_rate=0.0002,
verbose=True, fid_samples=1000, spectral_regularization=True, metric='fid', conditional=False,
use_adamw=True):
self.generator = generator
self.discriminator = discriminator
self.noise_dim = noise_dim
self.batch_size = batch_size
self.epochs = epochs
self.learning_rate = learning_rate
self.verbose = verbose
self.fid_samples = fid_samples
self.spectral_regularization = spectral_regularization
self.metric = metric
self.conditional = conditional
self.use_adamw = use_adamw
def generate_latent_noise(batch_size, noise_dim):
return np.random.normal(size=(batch_size, noise_dim))
def train_step(real_images, generator_optimizer, discriminator_optimizer, loss_fn, batch_size, noise_dim, spectral_regularization, discriminator):
noise = generate_latent_noise(batch_size, noise_dim)
with tf.GradientTape(persistent=True) as tape:
generated_images = generator(noise, training=True)
real_output = discriminator(real_images, training=True)
generated_output = discriminator(generated_images, training=True)
gen_loss = loss_fn(tf.ones_like(generated_output), generated_output)
disc_loss_real = loss_fn(tf.ones_like(real_output), real_output)
disc_loss_generated = loss_fn(tf.zeros_like(generated_output), generated_output)
disc_loss = disc_loss_real + disc_loss_generated
if spectral_regularization:
disc_grads = tape.gradient(disc_loss, discriminator.trainable_variables)
disc_grads_norm = [tf.norm(grad) for grad in disc_grads]
disc_penalty = 10.0 * tf.reduce_mean(tf.square(disc_grads_norm))
disc_loss += disc_penalty
gen_gradients = tape.gradient(gen_loss, generator.trainable_variables)
disc_gradients = tape.gradient(disc_loss, discriminator.trainable_variables)
generator_optimizer.apply_gradients(zip(gen_gradients, generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(disc_gradients, discriminator.trainable_variables))
return gen_loss, disc_loss
def fit(self, real_images):
"""
Entraîne le GAN sur des données réelles (images réelles).
Paramètres :
- real_images : Tensor ou tableau numpy contenant les images réelles pour l'entraînement.
Retourne :
Rien.
"""
# Préparation des données
real_images = tf.data.Dataset.from_tensor_slices(real_images).shuffle(len(real_images)).batch(self.batch_size)
# Fonction de perte pour le générateur et le discriminateur
if self.conditional:
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
else:
loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True)
# Optimiseurs pour le générateur et le discriminateur
if self.use_adamw:
generator_optimizer = tf.keras.optimizers.AdamW(self.learning_rate)
discriminator_optimizer = tf.keras.optimizers.AdamW(self.learning_rate)
else:
generator_optimizer = tf.keras.optimizers.Adam(self.learning_rate)
discriminator_optimizer = tf.keras.optimizers.Adam(self.learning_rate)
# Entraînement du GAN sur plusieurs epochs
for epoch in range(self.epochs):
start_time = time.time()
gen_loss_avg = tf.keras.metrics.Mean()
disc_loss_avg = tf.keras.metrics.Mean()
for real_batch in real_images:
gen_loss, disc_loss = train_step(real_batch, generator_optimizer, discriminator_optimizer, loss_fn,
self.batch_size, self.noise_dim, self.spectral_regularization, self.discriminator)
gen_loss_avg.update_state(gen_loss)
disc_loss_avg.update_state(disc_loss)
duration = time.time() - start_time
if self.verbose:
print(f"Epoch {epoch+1}/{self.epochs}, Gen Loss: {gen_loss_avg.result():.4f}, Disc Loss: {disc_loss_avg.result():.4f}, Duration: {duration:.2f} seconds")
def generate_images(self, num_images):
"""
Génère des images à l'aide du générateur entraîné.
Paramètres :
- num_images : Nombre d'images à générer.
Retourne :
- Tensor : Images générées.
"""
noise = generate_latent_noise(num_images, self.noise_dim)
generated_images = self.generator.predict(noise)
return generated_images
def calculate_metric(self, real_images, num_samples=None, metric=None):
"""
Calcule la métrique d'évaluation spécifiée entre les images réelles et générées.
Paramètres :
- real_images : Tensor ou tableau numpy contenant les images réelles.
- num_samples : Nombre d'échantillons à utiliser pour le calcul de la métrique.
- metric : Métrique d'évaluation à utiliser (parmi 'fid', 'inception_score', 'kid', 'mse').
Retourne :
- float : Score de la métrique.
"""
if num_samples is None:
num_samples = self.fid_samples
if metric is None:
metric = self.metric
if self.metric == 'fid':
return self.calculate_fid(self.generator, real_images, num_samples)
elif self.metric == 'inception_score':
return self.calculate_inception_score(self.generator, num_samples)
elif self.metric == 'kid':
return self.calculate_kid(self.generator, real_images, num_samples)
elif self.metric == 'mse':
return self.calculate_mse(self.generator, real_images, num_samples)
else:
raise ValueError("Metric not supported. Available metrics: 'fid', 'inception_score', 'kid', 'mse'")
def calculate_fid(generator, real_images, num_samples):
"""
Calcule la Fréchet Inception Distance (FID) entre les images réelles et générées.
Paramètres :
- real_images : Tensor ou tableau numpy contenant les images réelles.
- num_samples : Nombre d'échantillons à utiliser pour le calcul de la FID.
Retourne :
- float : Score FID.
"""
# Générer des images à l'aide du générateur entraîné
noise = np.random.normal(size=(num_samples, generator.noise_dim))
generated_images = generator.generator.predict(noise)
# Chargement du modèle InceptionV3 pré-entraîné pour l'extraction des features
inception_model = InceptionV3(include_top=False, pooling='avg', input_shape=(299, 299, 3))
real_features = inception_model.predict(preprocess_input(real_images))
generated_features = inception_model.predict(preprocess_input(generated_images))
# Calcul des moyennes et matrices de covariance des features
real_mean, real_cov = np.mean(real_features, axis=0), np.cov(real_features, rowvar=False)
generated_mean, generated_cov = np.mean(generated_features, axis=0), np.cov(generated_features, rowvar=False)
# Calcul de la distance FID
diff = real_mean - generated_mean
cov_sqrt, _ = sqrtm(real_cov.dot(generated_cov), disp=False)
if np.iscomplexobj(cov_sqrt):
cov_sqrt = cov_sqrt.real
fid_score = np.dot(diff, diff) + np.trace(real_cov + generated_cov - 2 * cov_sqrt)
return fid_score
def calculate_inception_score(generator, num_samples):
# Générer des images à l'aide du générateur entraîné
noise = np.random.normal(size=(num_samples, generator.noise_dim))
generated_images = generator.generator.predict(noise)
# Charger le modèle InceptionV3 pré-entraîné
inception_model = InceptionV3(include_top=False, pooling='avg', input_shape=(299, 299, 3))
# Prétraitement des images pour le modèle InceptionV3
generated_images = tf.image.resize(generated_images, (299, 299))
generated_images = tf.image.grayscale_to_rgb(generated_images)
generated_images = preprocess_input(generated_images)
# Calculer les probabilités de chaque classe pour les images générées
inception_scores = inception_model.predict(generated_images)
inception_scores = tf.nn.softmax(inception_scores)
# Calculer l'entropie croisée pour obtenir l'Inception Score
entropy = -tf.reduce_sum(inception_scores * tf.math.log(inception_scores), axis=1)
inception_score = tf.exp(tf.reduce_mean(entropy))
return inception_score.numpy()
def calculate_kid(generator, real_images, num_samples):
# Générer des images à l'aide du générateur entraîné
noise = np.random.normal(size=(num_samples, generator.noise_dim))
generated_images = generator.generator.predict(noise)
# Charger le modèle InceptionV3 pré-entraîné pour les features
inception_model = InceptionV3(include_top=False, pooling='avg', input_shape=(299, 299, 3))
# Prétraitement des images pour le modèle InceptionV3
real_images = tf.image.resize(real_images, (299, 299))
real_images = tf.image.grayscale_to_rgb(real_images)
real_images = preprocess_input(real_images)
generated_images = tf.image.resize(generated_images, (299, 299))
generated_images = tf.image.grayscale_to_rgb(generated_images)
generated_images = preprocess_input(generated_images)
# Extraire les features pour les images réelles et générées
real_features = inception_model.predict(real_images)
generated_features = inception_model.predict(generated_images)
# Calculer la distance euclidienne moyenne entre les features réelles et générées
distances = tf.norm(real_features[:, np.newaxis] - generated_features, axis=2)
kid = tf.reduce_mean(distances).numpy()
return kid
def calculate_mse(generator, real_images, num_samples):
# Générer des images à l'aide du générateur entraîné
noise = np.random.normal(size=(num_samples, generator.noise_dim))
generated_images = generator.generator.predict(noise)
# Calculer la Mean Squared Error (MSE) entre les images réelles et générées
mse = tf.reduce_mean(tf.square(real_images - generated_images)).numpy()
return mse
个字符
在这里你会发现在执行过程中显示的错误
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-fcaa091262ee> in <cell line: 19>()
17
18 # Entraîner le GAN sur le jeu de données MNIST
---> 19 gan.fit(train_images)
20
21 # Générer des images à l'aide du générateur entraîné
<ipython-input-1-d5bbfe93e45e> in fit(self, real_images)
137
138 for real_batch in real_images:
--> 139 gen_loss, disc_loss = train_step(real_batch, generator_optimizer, discriminator_optimizer, loss_fn,
140 self.batch_size, self.noise_dim, self.spectral_regularization, self.discriminator)
141 gen_loss_avg.update_state(gen_loss)
NameError: name 'train_step' is not defined
型
先谢谢你的帮助。我提前为评论是法语的事实道歉!!因为这是我的母语,但你可以翻译!?
为了解决这个问题,我将“generate_latent_noise”和“train_step”函数中的代码重新引入到“fit”函数中-它工作了!但我并不满意
1条答案
按热度按时间g6baxovj1#
当两个
function
都在同一个class
下时,需要传递self
参数来从另一个function
调用function
。你可以从这个thread中了解更多。但是,要解决您的特定情况,请替换以下内容:
字符串
使用以下内容(我在这里只包含了
self
参数):型
然后在
fit
函数中,使用self.train_step
而不是train_step
:型
**附加:**您需要对您的
generate_latent_noise
函数进行相同的更改。并在train_step
函数下更改这些行:型
与:
型