Encodeur automatique dans TensorFlow avec exemple
Qu’est-ce que l’autoencodeur dans le Deep Learning ?
An Encodeur automatique est un outil permettant d'apprendre efficacement le codage de données de manière non supervisée. Il s'agit d'un type de réseau neuronal artificiel qui vous aide à apprendre la représentation d'ensembles de données pour la réduction de dimensionnalité en entraînant le réseau neuronal à ignorer le bruit du signal. C'est un excellent outil pour recréer une entrée.
En termes simples, la machine prend, disons, une image et peut produire une image étroitement liée. L’entrée dans ce type de réseau neuronal n’est pas étiquetée, ce qui signifie que le réseau est capable d’apprendre sans supervision. Plus précisément, l'entrée est codée par le réseau pour se concentrer uniquement sur la fonctionnalité la plus critique. C'est l'une des raisons pour lesquelles l'auto-encodeur est populaire pour la réduction de dimensionnalité. En outre, les auto-encodeurs peuvent être utilisés pour produire modèles d'apprentissage génératifs. Par exemple, le réseau neuronal peut être entraîné avec un ensemble de visages, puis produire de nouveaux visages.
Comment fonctionne l'encodeur automatique TensorFlow ?
Le but d'un auto-encodeur est de produire une approximation de l'entrée en se concentrant uniquement sur les caractéristiques essentielles. Vous vous demandez peut-être pourquoi ne pas simplement apprendre à copier et coller l'entrée pour produire la sortie. En fait, un auto-encodeur est un ensemble de contraintes qui obligent le réseau à apprendre de nouvelles façons de représenter les données, différentes de la simple copie de la sortie.
Un auto-encodeur typique est défini avec une entrée, une représentation interne et une sortie (une approximation de l'entrée). L'apprentissage s'effectue dans les couches attachées à la représentation interne. En fait, il existe deux blocs principaux de couches qui ressemblent à un réseau neuronal traditionnel. La légère différence est que la couche contenant la sortie doit être égale à l’entrée. Dans l'image ci-dessous, l'entrée d'origine va dans le premier bloc appelé le codeur. Cette représentation interne compresse (réduit) la taille de l’entrée. Dans le deuxième bloc a lieu la reconstruction de l'entrée. C'est la phase de décodage.
Le modèle mettra à jour les poids en minimisant la fonction de perte. Le modèle est pénalisé si le résultat de la reconstruction est différent de l'entrée.
Concrètement, imaginez une image d'une taille de 50×50 (soit 250 pixels) et un réseau de neurones avec une seule couche cachée composée d'une centaine de neurones. L'apprentissage se fait sur une carte de caractéristiques deux fois plus petite que l'entrée. Cela signifie que le réseau doit trouver un moyen de reconstruire 250 pixels avec seulement un vecteur de neurones égal à 100.
Exemple d'encodeur automatique empilé
Dans ce didacticiel Autoencoder, vous apprendrez à utiliser un autoencodeur empilé. L'architecture est similaire à un réseau de neurones traditionnel. L'entrée va vers une couche cachée afin d'être compressée, ou de réduire sa taille, puis atteint les couches de reconstruction. L'objectif est de produire une image de sortie aussi proche que l'originale. Le modèle doit apprendre un moyen d’accomplir sa tâche sous un ensemble de contraintes, c’est-à-dire avec une dimension inférieure.
De nos jours, les auto-encodeurs dans L'apprentissage en profondeur sont principalement utilisés pour débruiter une image. Imaginez une image avec des rayures ; un humain est toujours capable de reconnaître le contenu. L'idée de l'auto-encodeur de débruitage est d'ajouter du bruit à l'image pour forcer le réseau à apprendre le modèle derrière les données.
L’autre famille utile d’Autoencoder Deep Learning est l’autoencodeur variationnel. Ce type de réseau peut générer de nouvelles images. Imaginez que vous formez un réseau à l'image d'un homme ; un tel réseau peut produire de nouveaux visages.
Comment créer un encodeur automatique avec TensorFlow
Dans ce didacticiel, vous apprendrez à créer un encodeur automatique empilé pour reconstruire une image.
Vous utiliserez le Ensemble de données CIFAR-10 qui contient 60000 32 images couleur 32 × 50000. L'ensemble de données Autoencoder est déjà réparti entre 10000 images pour la formation et pour les tests. Il existe jusqu'à dix classes :
- Avion
- Automobile
- Oiseau
- Cathy
- Cerf
- Chien
- grenouille
- Cheval
- Expédier
- Camion
Vous devez télécharger les images dans cette URL https://www.cs.toronto.edu/~kriz/cifar.html et les décompresser. Le dossier for-10-batches-py contient cinq lots de données contenant chacun 10000 images dans un ordre aléatoire.
Avant de créer et d'entraîner votre modèle, vous devez appliquer un certain traitement des données. Vous procéderez comme suit :
- Importez les données
- Convertir les données au format noir et blanc
- Ajouter tous les lots
- Construire l'ensemble de données de formation
- Construire un visualiseur d'images
Prétraitement d'image
Étape 1) Importez les données
Selon le site officiel, vous pouvez télécharger les données avec le code suivant. Le code Autoencoder chargera les données dans un dictionnaire avec le données et la étiquette. Notez que le code est une fonction.
import numpy as np import tensorflow as tf import pickle def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='latin1') return dict
Étape 2) Convertissez les données au format noir et blanc
Pour plus de simplicité, vous convertirez les données en niveaux de gris. C'est-à-dire avec une seule dimension contre trois pour l'image en couleurs. La plupart des réseaux neuronaux fonctionnent uniquement avec une entrée à une dimension.
def grayscale(im): return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Étape 3) Ajouter tous les lots
Maintenant que les deux fonctions sont créées et l'ensemble de données chargé, vous pouvez écrire une boucle pour ajouter les données en mémoire. Si vous vérifiez attentivement, le fichier de décompression contenant les données est nommé data_batch_ avec un nombre de 1 à 5. Vous pouvez parcourir les fichiers et l'ajouter aux données.
Une fois cette étape terminée, vous convertissez les données de couleurs au format d'échelle de gris. Comme vous pouvez le voir, la forme des données est 50000 1024 et 32 32. Les 2014* pixels sont désormais aplatis à .
# Load the data into memory data, labels = [], [] ## Loop over the b for i in range(1, 6): filename = './cifar-10-batches-py/data_batch_' + str(i) open_data = unpickle(filename) if len(data) > 0: data = np.vstack((data, open_data['data'])) labels = np.hstack((labels, open_data['labels'])) else: data = open_data['data'] labels = open_data['labels'] data = grayscale(data) x = np.matrix(data) y = np.array(labels) print(x.shape) (50000, 1024)
Remarque : remplacez « ./cifar-10-batches-py/data_batch_ » par l'emplacement réel de votre fichier. Par exemple pour Windows machine, le chemin pourrait être filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)
Étape 4) Construire l'ensemble de données de formation
Pour rendre l'entraînement plus rapide et plus facile, vous entraînerez un modèle sur les images du cheval uniquement. Les chevaux constituent la septième classe dans les données de l'étiquette. Comme mentionné dans la documentation de l'ensemble de données CIFAR-10, chaque classe contient 5000 5.000 images. Vous pouvez imprimer la forme des données pour confirmer qu'il y a 1024 images avec colonnes, comme indiqué ci-dessous. TensorFlow Exemple d’étape d’encodeur automatique.
horse_i = np.where(y == 7)[0] horse_x = x[horse_i] print(np.shape(horse_x)) (5000, 1024)
Étape 5) Construire un visualiseur d'images
Enfin, vous construisez une fonction pour tracer les images. Vous aurez besoin de cette fonction pour imprimer l'image reconstruite à partir de l'auto-encodeur.
Un moyen simple d'imprimer des images consiste à utiliser l'objet imshow de la bibliothèque matplotlib. Notez que vous devez convertir la forme des données de 1024 en 32*32 (c'est-à-dire le format d'une image).
# To plot pretty figures %matplotlib inline import matplotlib import matplotlib.pyplot as plt def plot_image(image, shape=[32, 32], cmap = "Greys_r"): plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest") plt.axis("off")
La fonction prend 3 arguments :
- Image(s): l'entrée
- Forme: liste, la dimension de l'image
- cmap:choisissez la carte des couleurs. Par défaut, gris
Vous pouvez essayer de tracer la première image de l'ensemble de données. Vous devriez voir un homme à cheval.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Définir l'estimateur d'ensemble de données
Très bien, maintenant que l'ensemble de données est prêt à être utilisé, vous pouvez commencer à utiliser Tensorflow. Avant de construire le modèle, utilisons l'estimateur Dataset de Tensorflow pour alimenter le réseau.
Vous construirez un ensemble de données avec l'estimateur TensorFlow. Pour vous rafraîchir l'esprit, vous devez utiliser :
- from_tensor_slices
- répéter
- lot
Le code complet pour créer l’ensemble de données est :
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Notez que x est un espace réservé avec la forme suivante :
- [Aucun,n_inputs] : défini sur Aucun car le nombre d'images transmises au réseau est égal à la taille du lot.
pour plus de détails, veuillez vous référer au tutoriel sur régression linéaire.
Après cela, vous devez créer l'itérateur. Sans cette ligne de code, aucune donnée ne transitera par le pipeline.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Maintenant que le pipeline est prêt, vous pouvez vérifier si la première image est la même qu'avant (c'est-à-dire un homme sur un cheval).
Vous définissez la taille du lot sur 1 car vous souhaitez uniquement alimenter l'ensemble de données avec une seule image. Vous pouvez voir la dimension des données avec print(sess.run(features).shape). Il est égal à (1, 1024). 1 signifie qu'une seule image avec 1024 est alimentée chacune. Si la taille du lot est définie sur deux, alors deux images passeront par le pipeline. (Ne modifiez pas la taille du lot. Sinon, cela générera une erreur. Une seule image à la fois peut accéder à la fonction plot_image().
## Parameters n_inputs = 32 * 32 BATCH_SIZE = 1 batch_size = tf.placeholder(tf.int64) # using a placeholder x = tf.placeholder(tf.float32, shape=[None,n_inputs]) ## Dataset dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size) iter = dataset.make_initializable_iterator() # create the iterator features = iter.get_next() ## Print the image with tf.Session() as sess: # feed the placeholder with data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print(sess.run(features).shape) plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r") (1, 1024)
Construire le réseau
Il est temps de construire le réseau. Vous entraînerez un auto-encodeur empilé, c'est-à-dire un réseau avec plusieurs couches cachées.
Votre réseau aura une couche d'entrée avec 1024 points, soit 32×32, la forme de l'image.
Le bloc codeur aura une couche supérieure cachée avec 300 neurones, une couche centrale avec 150 neurones. Le bloc décodeur est symétrique au codeur. Vous pouvez visualiser le réseau dans l'image ci-dessous. Notez que vous pouvez modifier les valeurs des calques masqués et centraux.
La construction d'un encodeur automatique est très similaire à tout autre modèle d'apprentissage en profondeur.
Vous construirez le modèle en suivant ces étapes :
- Définir les paramètres
- Définir les calques
- Définir l'architecture
- Définir l'optimisation
- Exécuter le modèle
- Évaluer le modèle
Dans la section précédente, vous avez appris à créer un pipeline pour alimenter le modèle. Il n'est donc pas nécessaire de créer à nouveau l'ensemble de données. Vous construirez un auto-encodeur à quatre couches. Vous utilisez l'initialisation Xavier. Il s'agit d'une technique permettant de définir les poids initiaux égaux à la variance de l'entrée et de la sortie. Enfin, vous utilisez la fonction d'activation d'elu. Vous régularisez la fonction de perte avec le régularisateur L2.
Étape 1) Définir les paramètres
La première étape consiste à définir le nombre de neurones dans chaque couche, le taux d'apprentissage et l'hyperparamètre du régulariseur.
Avant cela, vous importez partiellement la fonction. C'est une meilleure méthode pour définir les paramètres des couches denses. Le code ci-dessous définit les valeurs de l'architecture de l'auto-encodeur. Comme indiqué précédemment, l'auto-encodeur comporte deux couches, avec 300 neurones dans les premières couches et 150 dans les secondes. Leurs valeurs sont stockées dans n_hidden_1 et n_hidden_2.
Vous devez définir le taux d'apprentissage et l'hyperparamètre L2. Les valeurs sont stockées dans learning_rate et l2_reg
from functools import partial ## Encoder n_hidden_1 = 300 n_hidden_2 = 150 # codings ## Decoder n_hidden_3 = n_hidden_1 n_outputs = n_inputs learning_rate = 0.01 l2_reg = 0.0001
La technique d'initialisation Xavier est appelée avec l'objet xavier_initializer de la contrib de l'estimateur. Dans le même estimateur, vous pouvez ajouter le régulariseur avec l2_regularizer
## Define the Xavier initialization xav_init = tf.contrib.layers.xavier_initializer() ## Define the L2 regularizer l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
Étape 2) Définir les calques
Tous les paramètres des couches denses ont été définis ; vous pouvez tout emballer dans la variable dense_layer en utilisant l'objet partial. dense_layer qui utilise l'activation ELU, l'initialisation Xavier et la régularisation L2.
## Create the dense layer dense_layer = partial(tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer)
Étape 3) Définir l'architecture
Si vous regardez l’image de l’architecture, vous remarquez que le réseau empile trois couches avec une couche de sortie. Dans le code ci-dessous, vous connectez les couches appropriées. Par exemple, la première couche calcule le produit scalaire entre les caractéristiques matricielles d'entrée et les matrices contenant les 300 poids. Une fois le produit scalaire calculé, la sortie est envoyée à la fonction d'activation Elu. La sortie devient l'entrée de la couche suivante, c'est pourquoi vous l'utilisez pour calculer Hidden_2 et ainsi de suite. Les multiplications des matrices sont les mêmes pour chaque couche car vous utilisez la même fonction d'activation. Notez que la dernière couche, les sorties, n'applique pas de fonction d'activation. C'est logique car il s'agit de l'entrée reconstruite
## Make the mat mul hidden_1 = dense_layer(features, n_hidden_1) hidden_2 = dense_layer(hidden_1, n_hidden_2) hidden_3 = dense_layer(hidden_2, n_hidden_3) outputs = dense_layer(hidden_3, n_outputs, activation=None)
Étape 4) Définir l'optimisation
La dernière étape consiste à construire l'optimiseur. Vous utilisez l’erreur quadratique moyenne comme fonction de perte. Si vous vous souvenez du didacticiel sur la régression linéaire, vous savez que le MSE est calculé avec la différence entre la sortie prédite et l'étiquette réelle. Ici, l'étiquette est la fonctionnalité car le modèle tente de reconstruire l'entrée. Par conséquent, vous voulez la moyenne de la somme des différences du carré entre la sortie et l’entrée prédites. Avec TensorFlow, vous pouvez coder la fonction de perte comme suit :
loss = tf.reduce_mean(tf.square(outputs - features))
Ensuite, vous devez optimiser la fonction de perte. Vous utilisez l'optimiseur Adam pour calculer les dégradés. La fonction objectif est de minimiser la perte.
## Optimize loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)
Un réglage supplémentaire avant d'entraîner le modèle. Vous souhaitez utiliser une taille de lot de 150, c'est-à-dire alimenter le pipeline avec 150 images à chaque itération. Vous devez calculer le nombre d'itérations manuellement. C'est trivial à faire :
Si vous souhaitez transmettre 150 images à chaque fois et que vous savez qu'il y a 5000 33 images dans l'ensemble de données, le nombre d'itérations est égal à . En python, vous pouvez exécuter les codes suivants et vous assurer que la sortie est :
BATCH_SIZE = 150 ### Number of batches : length dataset / batch size n_batches = horse_x.shape[0] // BATCH_SIZE print(n_batches) 33
Étape 5) Exécuter le modèle
Enfin et surtout, entraînez le modèle. Vous entraînez le modèle avec 100 époques. Autrement dit, le modèle verra 100 fois les images avec des poids optimisés.
Vous connaissez déjà les codes pour entraîner un modèle dans Tensorflow. La légère différence est de canaliser les données avant d'exécuter la formation. De cette façon, le modèle s'entraîne plus rapidement.
Vous souhaitez imprimer la perte après dix époques pour voir si le modèle apprend quelque chose (c'est-à-dire que la perte diminue). La formation dure 2 à 5 minutes, selon le matériel de votre machine.
## Set params n_epochs = 100 ## Call Saver to save the model and re-use it later during evaluation saver = tf.train.Saver() with tf.Session() as sess: sess.run(tf.global_variables_initializer()) # initialise iterator with train data sess.run(iter.initializer, feed_dict={x: horse_x, batch_size: BATCH_SIZE}) print('Training...') print(sess.run(features).shape) for epoch in range(n_epochs): for iteration in range(n_batches): sess.run(train) if epoch % 10 == 0: loss_train = loss.eval() # not shown print("\r{}".format(epoch), "Train MSE:", loss_train) #saver.save(sess, "./my_model_all_layers.ckpt") save_path = saver.save(sess, "./model.ckpt") print("Model saved in path: %s" % save_path) Training... (150, 1024) 0 Train MSE: 2934.455 10 Train MSE: 1672.676 20 Train MSE: 1514.709 30 Train MSE: 1404.3118 40 Train MSE: 1425.058 50 Train MSE: 1479.0631 60 Train MSE: 1609.5259 70 Train MSE: 1482.3223 80 Train MSE: 1445.7035 90 Train MSE: 1453.8597 Model saved in path: ./model.ckpt
Étape 6) Évaluer le modèle
Maintenant que votre modèle est formé, il est temps de l'évaluer. Vous devez importer le test sert à partir du fichier /cifar-10-batches-py/.
test_data = unpickle('./cifar-10-batches-py/test_batch') test_x = grayscale(test_data['data']) #test_labels = np.array(test_data['labels'])
REMARQUE: Pour un Windows machine, le code devient test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)
Vous pouvez essayer d'imprimer les images 13, qui est un cheval
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Pour évaluer le modèle, vous utiliserez la valeur en pixels de cette image et verrez si l'encodeur peut reconstruire la même image après avoir réduit de 1024 pixels. Notez que vous définissez une fonction pour évaluer le modèle sur différentes images. Le modèle ne devrait fonctionner mieux que sur les chevaux.
La fonction prend deux arguments :
- df: Importer les données de test
- numéro_image: indique quelle image importer
La fonction est divisée en trois parties :
- Remodeler l'image à la bonne dimension, c'est-à-dire 1, 1024
- Nourrir le modèle avec l'image invisible, encoder/décoder l'image
- Imprimer l'image réelle et reconstruite
def reconstruct_image(df, image_number = 1): ## Part 1: Reshape the image to the correct dimension i.e 1, 1024 x_test = df[image_number] x_test_1 = x_test.reshape((1, 32*32)) ## Part 2: Feed the model with the unseen image, encode/decode the image with tf.Session() as sess: sess.run(tf.global_variables_initializer()) sess.run(iter.initializer, feed_dict={x: x_test_1, batch_size: 1}) ## Part 3: Print the real and reconstructed image # Restore variables from disk. saver.restore(sess, "./model.ckpt") print("Model restored.") # Reconstruct image outputs_val = outputs.eval() print(outputs_val.shape) fig = plt.figure() # Plot real ax1 = fig.add_subplot(121) plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r") # Plot estimated ax2 = fig.add_subplot(122) plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r") plt.tight_layout() fig = plt.gcf()
Maintenant que la fonction d'évaluation est définie, vous pouvez jeter un œil à l'image reconstruite numéro treize
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt Model restored. (1, 1024)
Résumé
- L'objectif principal d'un encodeur automatique est de compresser les données d'entrée, puis de les décompresser en une sortie qui ressemble beaucoup aux données d'origine.
- L'architecture d'un auto-encodeur symétrique avec une couche pivot nommée couche centrale.
- Vous pouvez créer l'encodeur automatique en utilisant :
Partiel: pour créer les calques denses avec le réglage typique :
tf.layers.dense, activation=tf.nn.elu, kernel_initializer=xav_init, kernel_regularizer=l2_regularizer
dense_layer(): pour faire la multiplication matricielle
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)