TensorFlow est en version 2 Alpha depuis mars 2019.
The 2.0 Alpha release is available now. Users can use this today and get started with all that TensorFlow 2.0 has to offer.
https://www.tensorflow.org/community/roadmap
Les changements sont importants, notamment en ce qui concerne la simplification d’usage. C’est ce que nous allons voir avec ce tutoriel.
Contrairement à nos tutoriels précédents (qui utilisaient Jupyter sur Mac), celui-ci, et les suivants, sont sur GCP (Google Colaboratory Platform).
Le logiciel est ici et le document ici.
L’exercice consiste à classifier des images d’habits (un peu du type de MNIST).
On utilise la sur-couche Keras à TensorFlow.
Installation
On commence par installer la bonne version de TensorFlow (si ce n’est pas déjà fait). Dans GCP c’est inutile !
!pip install -q tensorflow==2.0.0-alpha0
Imports
from __future__ import absolute_import, division, print_function
# TensorFlow and tf.keras
import tensorflow as tf
from tensorflow import keras
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)
Le from __future__ est là pour la compatibilité avec les versions précédentes de Python.
On importe les librairies de base (TensorFlow, Keras, numpy et pyplot). Pour ceux qui ne connaissent pas Keras, c’est ici (pour résumer, Keras est une API en Python au dessus de TensorFlow et CNTK), on importe numpy (indispensable pour les calculs scientifiques en Python) et pyplot pour les affichages.
Données
Les données à classer sont celles de Fashion-MNIST.
https://github.com/zalandoresearch/fashion-mnist
Fashion-MNIST
is a dataset of Zalando‘s article images—consisting of a training set of 60,000 examples and a test set of 10,000 examples. Each example is a 28×28 grayscale image, associated with a label from 10 classes. We intendFashion-MNIST
to serve as a direct drop-in replacement for the original MNIST dataset for benchmarking machine learning algorithms. It shares the same image size and structure of training and testing splits.
Ci-dessous un échantillon de ces images.

Lecture des données (téléchargement)
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
8192/5148 [===============================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
On utilise Keras pour le téléchargement des données.
Notez que l’import des données peut aussi se faire de cette façon (méthode que je préfère) :
from keras.datasets import fashion_mnist
(train_images, train_labels), (test_images, y_t test_labels est) = fashion_mnist.load_data()
A la suite de ces lignes, on dispose de données pour l’apprentissage (train_images) et pour le test (test_images). Le label (étiquettes, noms, catégories) de ces images est dans (train_labels) et (test_labels).
Il est important de distinguer le validation set du test set. Lire ici.
To reiterate the findings from researching the experts above, this section provides unambiguous definitions of the three terms.
https://machinelearningmastery.com/difference-test-validation-datasets/
Training Dataset: The sample of data used to fit the model.
Validation Dataset: The sample of data used to provide an unbiased evaluation of a model fit on the training dataset while tuning model hyperparameters. The evaluation becomes more biased as skill on the validation dataset is incorporated into the model configuration.
Test Dataset: The sample of data used to provide an unbiased evaluation of a final model fit on the training dataset.
fashion_mnist.load_data() return 2 tuples:
x_train, x_test: uint8 array of grayscale image data with shape (num_samples, 28, 28).
https://keras.io/datasets/
y_train, y_test: uint8 array of labels (integers in range 0-9) with shape (num_samples,).
Les étiquettes des données sont des catégories numériques, dont les noms sont :
Label | Description |
0 | T-shirt/top |
1 | Trouser |
2 | Pullover |
3 | Dress |
4 | Coat |
5 | Sandal |
6 | Shirt |
7 | Sneaker |
8 | Bag |
9 | Ankle boot |
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
Etudes des données
train_images.shape
affiche : le nombre de données d’apprentissage et leur taille
(60000, 28, 28)
soit 60 000 images carrées de 28 pixels de côté.
Le nombre d’étiquettes est donc aussi de 60 000
len(train_labels)
60000
chaque étiquette étant un nombre entre 0 et 9
train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
quant aux images de test, elles sont au même format et au nombre de 10 000
test_images.shape
(10000, 28, 28)
et le nombre de labels pour la validation est aussi de 10 000
len(test_labels)
10000
Préparation des données
Les images sont en niveaux de gris. Elles ont des valeurs entre 0 et 255, comme on peut le voir avec cet exemple :
plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

On veut que les valeurs soient entre 0 et 1. C’est ce qu’impose TensorFlow.
train_images = train_images / 255.0
test_images = test_images / 255.0
affichage des 25 premières images (apprentissage)
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(class_names[train_labels[i]])
plt.show()

Construction du modèle (architecture du réseau)
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation='relu'),
keras.layers.Dense(10, activation='softmax')
])
Keras permet de décrire séquentiellement les couches du réseau de neurones.
Commençons par la 1ère ligne, qui décrit la 1ère couche :
keras.layers.Flatten(input_shape=(28, 28))
The model needs to know what input shape it should expect. For this reason, the first layer in a Sequential model (and only the first, because following layers can do automatic shape inference) needs to receive information about its input shape.
https://keras.io/getting-started/sequential-model-guide/
On a bien un input_shape=(28, 28) de 28*28 puisque nos images ont cette taille. On commence par transformer notre matrice (image) 28*28 en un vecteur de dimension 28*28=784.
Ensuite, on est dans le cas d’un Dense dont la fonction d’activation est un ReLU (Rectified Linear Unit). On a ici une couche de 128 neurones. Cette couche est connectée à la couche précédente de 784 neurones.
keras.layers.Dense(128, activation='relu')
https://keras.io/layers/core/#dense
Dense
implements the operation:output = activation(dot(input, kernel) + bias)
whereactivation
is the element-wise activation function passed as theactivation
argument,kernel
is a weights matrix created by the layer, andbias
is a bias vector created by the layer (only applicable ifuse_bias
isTrue
)
A dense layer is a regular DNN (Deep Neural Network) layer that connects every neuron in the defined layer to every neuron in the previous layer. For instance, if Layer 1 has 5 neurons and Layer 2 (dense layer) has 3 neurons, the total number of connections between Layer 1 and Layer 2 would be 15 (5 × 3). Since it accommodates every possible connection between the layers, it is called a “dense” layer.
Learn Keras for Deep Neural Networks – Jojo Moolayil – apress
On termine avec une couche de 10 neurones (normal puisqu’on a 10 catégories).
La fonction d’activation est un softmax.
keras.layers.Dense(10, activation='softmax')
Notre réseau de neurones a cette architecture. Ne pas oublier que c’est pour 60 000 images.

compilation du modèle
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
Before training a model, you need to configure the learning process, which is done via the
https://keras.io/getting-started/sequential-model-guide/#compilationcompile
method. It receives three arguments:
An optimizer. This could be the string identifier of an existing optimizer (such asrmsprop
oradagrad
), or an instance of theOptimizer
class. See: optimizers.
A loss function. This is the objective that the model will try to minimize. It can be the string identifier of an existing loss function (such ascategorical_crossentropy
ormse
), or it can be an objective function. See: losses.
A list of metrics. For any classification problem you will want to set this tometrics=['accuracy']
. A metric could be the string identifier of an existing metric or a custom metric function.
3 paramètres sont nécessaires à la compilation : l’optimizer, la fonction de coût et la métrique.
optimizer
The optimizer function is a mathematical algorithm that uses derivatives, partial derivatives, and the chain rule
Learn Keras for Deep Neural Networks – Jojo Moolayil – apress
in calculus to understand how much change the network will see in the loss function by making a small change in the weight of the neurons. The change in the loss function, which would be an increase or decrease, helps in determining the direction of the change required in the weight of the connection.
L’optimizer retenu ici est Adam.
Adam, which stands for Adaptive Moment Estimation, is by far the most popular and widely used optimizer in DL. In most cases, you can blindly choose the Adam optimizer and forget about the optimization alternatives.
Learn Keras for Deep Neural Networks – Jojo Moolayil – apress
Il n’y a pas de choix par défaut pour l’optimizer mais le plus courant est Adam.
fonction de coût
La fonction de coût est sparse_categorical_crossentropy.
C’est la fonction qu’on utilise dans les cas comme le nôtre :
Categorical crossentropy with integer targets.
https://keras.io/backend/#sparse_categorical_crossentropy
métrique
La métrique est accuracy.
metrics: List of metrics to be evaluated by the model during training and testing. Typically you will use
https://keras.io/models/model/#compilemetrics=['accuracy']
.
Similar to the loss function, we also define metrics for the model in Keras. In a simple way, metrics can be understood as the function used to judge the performance of the model on a different unseen dataset, also called the validation dataset. The only difference between metrics and the loss function is that the results from metrics are not used in training the model with respect to optimization. They are only used to validate the test results
Learn Keras for Deep Neural Networks – Jojo Moolayil – apress
Notez bien que la métrique ne sert pas au calcul mais seulement à valider les résultats sur les données de test.
apprentissage
On indique au modèle d’utiliser les image train_images avec leur étiquettes train_labels sur 5 epochs (parcours complet du jeu de données).
model.fit(train_images, train_labels, epochs=5)
Epoch 1/5
60000/60000 [==============================] - 7s 118us/sample - loss: 1.0872 - accuracy: 0.6613
Epoch 2/5
60000/60000 [==============================] - 6s 93us/sample - loss: 0.6397 - accuracy: 0.7683
Epoch 3/5
60000/60000 [==============================] - 6s 92us/sample - loss: 0.5615 - accuracy: 0.8006
Epoch 4/5
60000/60000 [==============================] - 6s 108us/sample - loss: 0.5179 - accuracy: 0.8164
Epoch 5/5
60000/60000 [==============================] - 5s 88us/sample - loss: 0.4901 - accuracy: 0.8268
<tensorflow.python.keras.callbacks.History at 0x7fd9c719b7b8>
Après 5 epochs la perte est de 0.4901 pour une exactitude de 0.8268
validation
On étudie comment se comporte le modèle sur les données de validation.
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('\nTest accuracy:', test_acc)
Le résultat :
10000/10000 [==============================] - 1s 57us/sample - loss: 0.5076 - accuracy: 0.8156
Test accuracy: 0.8156
Le résultat 0.8156 est légèrement inférieur à 0.8268 calculé sur les données d’apprentissage, signe d’une léger sur-apprentissage (overfitting)
Prédictions
Testons quelques prédictions.
predictions = model.predict(test_images)
Si on s’intéresse à la première des prédictions :
predictions[0]
on obtient :
array([2.6798305e-06, 1.8942366e-07, 1.6576356e-05, 8.9628738e-06,
4.6992078e-05, 1.5858281e-01, 1.3067870e-05, 3.1452715e-01,
6.4298431e-03, 5.2037174e-01], dtype=float32)
La prédiction est 9 comme le montre les lignes suivantes :
np.argmax(predictions[0])
9
ce qui est une bonne prédiction, puisque le label est aussi 9
test_labels[0]
9
Conclusion
La suite du code n’est pas présentée car elle n’a que peu d’intérêt en ce qui concerne le Deep Learning. Il s’agit uniquement d’affichage des prédictions.
En résumé, on a construit un DNN avec seulement quelques lignes de code et on obtient un résultat honorable. Avec un réseau un peu plus complexe, du type CNN, on obtient plus de 93% d’accuracy.
Pour un exemple de CNN en analogie avec l’exemple MNIST Keras.
from __future__ import print_function
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
batch_size = 128
num_classes = 10
epochs = 12
# input image dimensions
img_rows, img_cols = 28, 28
fashion_mnist = keras.datasets.fashion_mnist
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
On obtient les résultats :
Train on 60000 samples, validate on 10000 samples
Epoch 1/12
60000/60000 [==============================] - 9s 152us/step - loss: 0.5690 - acc: 0.7981 - val_loss: 0.3662 - val_acc: 0.8690
Epoch 2/12
60000/60000 [==============================] - 9s 143us/step - loss: 0.3641 - acc: 0.8697 - val_loss: 0.3044 - val_acc: 0.8874
Epoch 3/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.3165 - acc: 0.8867 - val_loss: 0.2774 - val_acc: 0.9003
Epoch 4/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.2846 - acc: 0.8973 - val_loss: 0.2563 - val_acc: 0.9075
Epoch 5/12
60000/60000 [==============================] - 9s 143us/step - loss: 0.2593 - acc: 0.9073 - val_loss: 0.2508 - val_acc: 0.9076
Epoch 6/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.2391 - acc: 0.9137 - val_loss: 0.2508 - val_acc: 0.9098
Epoch 7/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.2259 - acc: 0.9181 - val_loss: 0.2417 - val_acc: 0.9126
Epoch 8/12
60000/60000 [==============================] - 9s 143us/step - loss: 0.2133 - acc: 0.9230 - val_loss: 0.2257 - val_acc: 0.9181
Epoch 9/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.1999 - acc: 0.9282 - val_loss: 0.2212 - val_acc: 0.9217
Epoch 10/12
60000/60000 [==============================] - 9s 143us/step - loss: 0.1909 - acc: 0.9305 - val_loss: 0.2216 - val_acc: 0.9189
Epoch 11/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.1813 - acc: 0.9341 - val_loss: 0.2183 - val_acc: 0.9211
Epoch 12/12
60000/60000 [==============================] - 9s 144us/step - loss: 0.1723 - acc: 0.9375 - val_loss: 0.2087 - val_acc: 0.9255
Test loss: 0.2087470836341381
Test accuracy: 0.9255
Dans cet exemple, seul les lignes
fashion_mnist = keras.datasets.fashion_mnist
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
ont été modifiées pour remplacer MNIST par Fashion MNIST
Epoch 12/12
60000/60000 [==============================] - 8s 140us/step - loss: 0.1471 - acc: 0.9451 - val_loss: 0.2175 - val_acc: 0.9267
Test loss: 0.2175135334253311
Test accuracy: 0.9267