TensorFlow Autoencoder: exemple d'ensemble de données avec Deep Learning

Table des matières:

Anonim

Qu'est-ce qu'un encodeur automatique?

Un Autoencoder est un outil pour apprendre le codage de données de manière efficace et non supervisée. C'est un type de réseau neuronal artificiel qui vous aide à apprendre la représentation des ensembles de données pour la réduction de la dimensionnalité en apprenant au 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 encodée par le réseau pour se concentrer uniquement sur la fonctionnalité la plus critique. C'est l'une des raisons pour lesquelles l'autoencoder est populaire pour la réduction de la dimensionnalité. En outre, les auto-encodeurs peuvent être utilisés pour produire des modèles d'apprentissage génératif . Par exemple, le réseau neuronal peut être formé avec un ensemble de visages et peut ensuite produire de nouveaux visages.

Dans ce didacticiel TensorFlow Autoencoder, vous apprendrez:

  • Qu'est-ce qu'un encodeur automatique?
  • Comment fonctionne Autoencoder?
  • Exemple de codeur automatique empilé
  • Créer un encodeur automatique avec TensorFlow
  • Prétraitement d'image
  • Définir l'estimateur de jeu de données
  • Construisez le réseau

Comment fonctionne Autoencoder?

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 pouvez penser 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 se fait dans les couches attachées à la représentation interne. En fait, il existe deux blocs principaux de couches qui ressemblent à un réseau de neurones 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é l' encodeur . Cette représentation interne comprime (réduit) la taille de l'entrée. Dans le deuxième bloc se produit la reconstruction de l'entrée. C'est la phase de décodage.

Fonctionnement de l'Autoencoder

Le modèle mettra à jour les pondérations en minimisant la fonction de perte. Le modèle est pénalisé si la sortie de reconstruction est différente de l'entrée.

Concrètement, imaginez une image d'une taille de 50x50 (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 des caractéristiques qui est 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 de codeur automatique empilé

Dans ce didacticiel Autoencoder, vous apprendrez à utiliser un autoencoder empilé. L'architecture est similaire à un réseau de neurones traditionnel. L'entrée est dirigée 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'original. 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 en Deep Learning 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 du débruitage automatique du codeur 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.

Créer un encodeur automatique avec TensorFlow

Dans ce didacticiel, vous apprendrez à créer un auto-encodeur empilé pour reconstruire une image.

Vous utiliserez le jeu de données CIFAR-10 qui contient 60000 images couleur 32x32. L'ensemble de données Autoencoder est déjà divisé entre 50000 images pour la formation et 10000 pour les tests. Il y a jusqu'à dix classes:

  • Avion
  • Voiture
  • Oiseau
  • Chat
  • Cerf
  • Chien
  • La grenouille
  • Cheval
  • Bateau
  • Camion

Vous devez télécharger les images dans cette URL https://www.cs.toronto.edu/~kriz/cifar.html et le décompresser. Le dossier for-10-batches-py contient cinq lots de données avec 10 000 images chacun dans un ordre aléatoire.

Avant de créer et de former votre modèle, vous devez appliquer un traitement de données. Vous procéderez comme suit:

  1. Importez les données
  2. Convertissez les données au format noir et blanc
  3. Ajouter tous les lots
  4. Construire le jeu de données d'entraînement
  5. 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 les données et l' étiquette . Notez que le code est une fonction.

import numpy as npimport tensorflow as tfimport pickledef unpickle(file):import picklewith 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 allez convertir les données en niveaux de gris. Autrement dit, avec une seule dimension contre trois pour l'image en couleurs. La plupart du réseau neuronal ne fonctionne qu'avec une entrée de dimension.

def grayscale(im):return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)

Étape 3) Ajoutez tous les lots

Maintenant que les deux fonctions sont créées et que l'ensemble de données est chargé, vous pouvez écrire une boucle pour ajouter les données en mémoire. Si vous vérifiez attentivement, le fichier de décompression avec les données est nommé data_batch_ avec un nombre de 1 à 5. Vous pouvez parcourir les fichiers et l'ajouter aux données.

Lorsque cette étape est terminée, vous convertissez les données de couleurs dans un format d'échelle de gris. Comme vous pouvez le voir, la forme des données est de 50000 et 1024. Les 32 * 32 pixels sont maintenant aplatis à 2014.

# Load the data into memorydata, labels = [], []## Loop over the bfor 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_" l'emplacement réel de votre fichier. Par exemple pour une machine Windows, le chemin pourrait être filename = 'E: \ cifar-10-batches-py \ data_batch_' + str (i)

Étape 4) Construisez le jeu de données d'entraînement

Pour rendre l'entraînement plus rapide et plus facile, vous entraînerez un modèle uniquement sur les images de chevaux. Les chevaux sont la septième classe dans les données de l'étiquette. Comme mentionné dans la documentation du jeu de données CIFAR-10, chaque classe contient 5000 images. Vous pouvez imprimer la forme des données pour confirmer qu'il y a 5 000 images avec 1 024 colonnes, comme indiqué dans l'étape d'exemple TensorFlow Autoencoder ci-dessous.

horse_i = np.where(y == 7)[0]horse_x = x[horse_i]print(np.shape(horse_x))(5000, 1024)

Étape 5) Construisez 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 du codeur automatique.

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 inlineimport matplotlibimport matplotlib.pyplot as pltdef 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: l'entrée
  • Forme: liste, la dimension de l'image
  • Cmap: choisissez la palette de 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 sur un cheval.

plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r") 

Définir l'estimateur de jeu 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 allez créer un ensemble de données avec l'estimateur TensorFlow. Pour vous rafraîchir l'esprit, vous devez utiliser:

  • from_tensor_slices
  • répéter
  • grouper

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é de la forme suivante:

  • [Aucun, n_inputs]: définissez sur Aucun car le nombre d'images alimentant le réseau est égal à la taille du lot.

pour plus de détails, veuillez vous référer au tutoriel sur la régression linéaire.

Après cela, vous devez créer l'itérateur. Sans cette ligne de code, aucune donnée ne passera 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 que précédemment (c'est-à-dire un homme sur un cheval).

Vous définissez la taille du lot sur 1 car vous ne souhaitez alimenter le jeu de données qu'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, 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 ().

## Parametersn_inputs = 32 * 32BATCH_SIZE = 1batch_size = tf.placeholder(tf.int64)# using a placeholderx = tf.placeholder(tf.float32, shape=[None,n_inputs])## Datasetdataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()## Print the imagewith tf.Session() as sess:# feed the placeholder with datasess.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)

Construisez le réseau

Il est temps de construire le réseau. Vous allez entraîner un autoencodeur empilé, c'est-à-dire un réseau avec plusieurs couches cachées.

Votre réseau aura une couche d'entrée avec 1024 points, c'est-à-dire 32x32, la forme de l'image.

Le bloc encodeur aura une couche cachée supérieure avec 300 neurones, une couche centrale avec 150 neurones. Le bloc décodeur est symétrique du 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.

Construire le réseau pour Autoencoder

La création d'un auto-encodeur est très similaire à tout autre modèle d'apprentissage en profondeur.

Vous construirez le modèle en suivant ces étapes:

  1. Définir les paramètres
  2. Définir les couches
  3. Définir l'architecture
  4. Définir l'optimisation
  5. Exécutez le modèle
  6. É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 le jeu de données. Vous construirez un auto-encodeur avec quatre couches. Vous utilisez l'initialisation Xavier. Il s'agit d'une technique pour définir les poids initiaux égaux à la variance de l'entrée et de la sortie. Enfin, vous utilisez la fonction d'activation elu. Vous régularisez la fonction de perte avec le régulariseur L2.

Étape 1) Définissez 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'autoencodeur. Comme indiqué précédemment, l'auto-encodeur a deux couches, avec 300 neurones dans les premières couches et 150 dans les secondes couches. 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## Encodern_hidden_1 = 300n_hidden_2 = 150 # codings## Decodern_hidden_3 = n_hidden_1n_outputs = n_inputslearning_rate = 0.01l2_reg = 0.0001

La technique d'initialisation de Xavier est appelée avec l'objet xavier_initializer de l'estimateur contrib. Dans le même estimateur, vous pouvez ajouter le régulariseur avec l2_regularizer

## Define the Xavier initializationxav_init = tf.contrib.layers.xavier_initializer()## Define the L2 regularizerl2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)

Étape 2) Définissez les couches

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 layerdense_layer = partial(tf.layers.dense,activation=tf.nn.elu,kernel_initializer=xav_init,kernel_regularizer=l2_regularizer)

Étape 3) Définissez l'architecture

Si vous regardez l'image de l'architecture, vous notez 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 de la matrice d'entrée et les matrices contenant les 300 poids. Une fois le produit scalaire calculé, la sortie passe à 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. La multiplication des matrices est la même 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. Cela a du sens car c'est l'entrée reconstruite

## Make the mat mulhidden_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éfinissez 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 tutoriel 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 fonction car le modèle tente de reconstruire l'entrée. Par conséquent, vous voulez la moyenne de la somme de la différence du carré entre la sortie et l'entrée prévues. 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 objective est de minimiser la perte.

## Optimizeloss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)

Encore un paramètre 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 voulez passer 150 images à chaque fois et que vous savez qu'il y a 5000 images dans le jeu 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 33:

BATCH_SIZE = 150### Number of batches : length dataset / batch sizen_batches = horse_x.shape[0] // BATCH_SIZEprint(n_batches)33

Étape 5) Exécutez le modèle

Enfin, formez 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 de 2 à 5 minutes, selon le matériel de votre machine.

## Set paramsn_epochs = 100## Call Saver to save the model and re-use it later during evaluationsaver = tf.train.Saver()with tf.Session() as sess:sess.run(tf.global_variables_initializer())# initialise iterator with train datasess.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 shownprint("\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.45510 Train MSE: 1672.67620 Train MSE: 1514.70930 Train MSE: 1404.311840 Train MSE: 1425.05850 Train MSE: 1479.063160 Train MSE: 1609.525970 Train MSE: 1482.322380 Train MSE: 1445.703590 Train MSE: 1453.8597Model 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 sert de test à 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 une machine Windows, 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 allez utiliser la valeur de pixel de cette image et voir si l'encodeur peut reconstruire la même image après avoir réduit 1024 pixels. Notez que vous définissez une fonction pour évaluer le modèle sur différentes images. Le modèle devrait mieux fonctionner uniquement sur les chevaux.

La fonction prend deux arguments:

  • df: importer les données de test
  • image_number: indiquez quelle image importer

La fonction est divisée en trois parties:

  1. Remodeler l'image à la bonne dimension, c'est-à-dire 1, 1024
  2. Nourrissez le modèle avec l'image invisible, encodez / décodez l'image
  3. Imprimez 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, 1024x_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 imagewith 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 imageoutputs_val = outputs.eval()print(outputs_val.shape)fig = plt.figure()# Plot realax1 = fig.add_subplot(121)plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")# Plot estimatedax2 = 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 avoir un aperçu de l'image reconstruite numéro treize

reconstruct_image(df =test_x, image_number = 13) 
INFO:tensorflow:Restoring parameters from ./model.ckptModel 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 étroitement 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 le codeur automatique en utilisant:

  • Partiel: pour créer les couches 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

vous pouvez définir la fonction de perte et l'optimisation avec:

loss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)

Dernière exécution d'une session pour entraîner le modèle.