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 ce URL https://www.cs.toronto.edu/~kriz/cifar.html and unzip it. The folder for-10-batches-py contains five batches of data with 10000 images each in a random order.
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)




