Récemment, le système de génération profonde, appelé GAN, est chaud. J'essaye aussi diverses choses et je joue. Quant à la bibliothèque, Keras est intuitive et facile à comprendre.
Soit dit en passant, DCGAN et Wasserstein GAN ordinaires peuvent être mis en œuvre et appris rapidement même avec Keras, mais quand il s'agit de ceux qui ont apporté des améliorations mineures telles que l'optimisation des erreurs, «Comment écrivez-vous cela dans Keras? ,,? »Je pense que cela peut arriver. Je l'ai fait avec l'implémentation de Gradient Penalty proposée dans Amélioration de la formation des GAN Wasserstein. Je vais omettre l'explication de Gradient Penalty, mais pour cela, je pense qu'il serait bon que le modèle soit défini dans Keras et que l'apprentissage se fasse dans TensorFlow. Je pensais que, j'avais réussi à bien apprendre cela avec Wasserstein GAN normal, alors j'aimerais écrire un article. Je suis heureux que vous puissiez l'utiliser comme référence. Placez le code sur ici.
Generator et Discriminator sont écrits par Keras. C'est facile. (Voir model.py) Generator utilise Deconvolution (taille de filtre 4 * 4, pas 2 * 2) pour convertir une entrée aléatoire en une image. Le discriminateur émet la valeur de la fonction à partir de l'image d'entrée par Convolution (taille de filtre 4 * 4, foulée 2 * 2). Je l'ai écrit dans le modèle d'API fonctionnelle de Keras, mais il ne devrait y avoir aucun problème avec le modèle séquentiel (méthode d'écriture qui se connecte à model.add).
Dans Wasserstein GAN, Discriminator gère la sortie des valeurs de fonction plutôt que de déterminer l'authenticité de l'image d'entrée.
\max_{D} \min_{G} \mathbb{E}_{x\sim p(x)}D(x) - \mathbb{E}_{z \sim p(z)}D(G(z))
Cela rend l'apprentissage par gradient plus stable que le GAN d'origine, ce qui minimise la divergence Jensen-Shannon, mais consultez l'article original (https://arxiv.org/abs/1701.07875) et d'autres commentaires pour plus de détails. S'il te plait donne moi.
D'ailleurs, normalement, dans le cas de Keras, spécifiez la fonction de perte préparée ou celle définie par vous-même et model.compile, mais dans cet article, cette optimisation est effectuée par TensorFlow.
main.py
class WassersteinGAN:
def __init__(self, ...):
self.image_size = 64
self.gen = generator # model.Générateur défini dans py
self.disc = discriminator # model.Discriminateur défini dans py
#L'image d'entrée et le nombre aléatoire d'entrée sont définis par un espace réservé.
self.x = tf.placeholder(tf.float32, (None, self.image_size, self.image_size, 3), name = 'x') #Image réelle
self.z = tf.placeholder(tf.float32, (None, 100), name = 'z') #Entrer un nombre aléatoire
self.x_ = self.gen(self.z) #Fausse image<-Entrer un nombre aléatoire
self.d = self.disc(self.x) #Sortie avec image réelle en entrée
self.d_ = self.disc(self.x_) #Sortie avec une fausse image en entrée
self.d_loss = -(tf.reduce_mean(self.d) - tf.reduce_mean(self.d_)) #Fonction objective du discriminateur
self.g_loss = -tf.reduce_mean(self.d_) #Fonction objectif du générateur
#Définissez l'optimiseur. Le taux d'apprentissage de Generator est réglé un peu plus petit.
self.d_opt = tf.train.RMSPropOptimizer(learning_rate = 5e-5)\
.minimize(self.d_loss, var_list = self.disc.trainable_weights)
self.g_opt = tf.train.RMSPropOptimizer(learning_rate = 1e-5)\
.minimize(self.g_loss, var_list = self.gen.trainable_weights)
#Définissez la session de TensorFlow.
self.sess = tf.Session()
K.set_session(self.sess) #← Il semble nécessaire lorsqu'il est utilisé en combinaison avec Keras
def train(self, ...):
Sous ces paramètres, nous allons réellement diffuser les données et apprendre.
Dans mon code, une classe pour récupérer les images d'entrée et entrer des nombres aléatoires (misc / dataIO.py, InputSampler ) A été faite, L'échantillonneur qui apparaît dans le code suivant est une instance de ce InputSampler, et la méthode image_sample renvoie un mini-lot d'images réelles, et la méthode noise_sample renvoie un mini-lot de nombres aléatoires d'entrée. La méthode de rechargement est une méthode pour diviser et conserver un grand nombre d'images de données d'entraînement. (Étant donné que le jeu de données d'image de visage fréquemment utilisé CelebA contient plus de 200 000 images, nous avons créé cette spécification pour la commodité de la mémoire.)
De plus, si le modèle implémenté par Keras inclut la normalisation par lots, il est nécessaire de définir K.learning_phase () lors de la circulation des données. Y compris cela, il est décrit dans le code suivant.
main.py
class WassersteinGAN:
def __init__(self, ...):
# --Abréviation--
def train(self, ...):
for e in range(epochs):
for batch in range(num_batches):
#Le discriminateur apprend beaucoup
for _ in range(5):
#Coupure de poids pour garantir la continuité Lipsitz
d_weights = [np.clip(w, -0.01, 0.01) for w in self.disc.get_weights()]
self.disc.set_weights(d_weights)
#Mini lot d'images réelles
bx = sampler.image_sample(batch_size)
#Mini lot de nombres aléatoires d'entrée
bz = sampler.noise_sample(batch_size)
#Entrée et K pour passer à l'espace réservé.learning_phase()Pour apprendre Discriminator en spécifiant
self.sess.run(self.d_opt, feed_dict = {self.x: bx, self.z: bz,
K.learning_phase(): 1})
bz = sampler.noise_sample(batch_size, self.z_dim)
#Entrée et K pour passer à l'espace réservé.learning_phase()Pour apprendre Generator en spécifiant
self.sess.run(self.g_opt, feed_dict = {self.z: bz,
K.learning_phase(): 1})
#Lors de la sortie de la perte
d_loss, g_loss = self.sess.run([self.d_loss, self.g_loss],
feed_dict = {self.x: bx, self.z: bz,
K.learning_phase(): 1})
print('epoch : {}, batch : {}, d_loss : {}, g_loss : {}'\
.format(e, batch, d_loss, g_loss))
~~ Puisque le modèle est décrit dans Keras, les paramètres peuvent être enregistrés par la formule Keras. Je sauve souvent chaque époque. ~~
~~ * Si vous essayez d'enregistrer le modèle à la manière Keras dans une session TensorFlow, cela peut ne pas fonctionner. confirmer. ~~
Les paramètres du modèle peuvent être enregistrés avec l'expression Keras
model.save_weights () ''. Vous pouvez également charger les paramètres enregistrés avec
model.load_weights () ''.
main.py
class WassersteinGAN:
def __init__(self, ...):
# --Abréviation--
def train(self, ...):
for e in range(epochs):
for batch in range(num_batches):
# --Abréviation--
#Les paramètres peuvent être enregistrés de la manière Keras
self.gen.save_weights('path/to/g_{}epoch.h5'.format(e))
self.disc.save_weights('path/to/d_{}epoch.h5'.format(e))
Cela m'a assez bien appris, mais l'image générée était un peu floue. En général, Wasserstein GAN semble un peu flou que DCGAN, mais je pense qu'il peut être généré magnifiquement en fonction du réglage tel que le taux d'apprentissage.
De cette façon, j'ai pu créer un modèle avec Keras et m'entraîner avec TensorFlow. Récemment, j'ai le sentiment que de nombreuses méthodes avec une optimisation conçue ont été proposées, j'espère donc qu'elles seront utiles pour le test de suivi. N'hésitez pas à nous contacter si vous avez des suggestions ou des améliorations.
J'ai écrit le code pour apprendre avec Keras et tensorflow de la même manière avec un simple CNN. Si vous aimez le GAN, ici est facile à comprendre.
Recommended Posts