TPCNN
TPCNN
TPCNN
1. Problème :
Nous allons créer un réseau de neurones convolutionnels capable de reconnaître les
chiffres écrits à la main ! Le principe est simple : à partir d’une banque d’images de
chiffres écrits à la main (et annoté pour dire de quel chiffre il s’agit), fournie par Keras
(un framework de deep learning), nous allons entraîner 3 IA différentes et les comparer.
2. Installations préalables :
Nous installons Tensorflow et Keras.
Commençons par installer Tensorflow, le framework de Google pour faire du Deep
Learning. Notez dès à présent que nous ne nous en servirons pas… mais on utilisera
Keras, qui est un framework s’appuyant sur Tensorflow en backend (il en simplifie
les commandes et ajoute certaines fonctionnalités).
3. Nos réseaux cibles :
Voici le schéma d’architecture des réseaux de neurones que nous allons réaliser dans ce
TP. Vous remarquerez un certain nombre de différences, qui aboutissent à des résultats
plus ou moins bons. Les paramètres ont été sélectionnés à la fois par expérience et
de manière empirique, car bien souvent on essaie plusieurs architectures avant de
trouver la meilleure !
1
3 CNN distincts pour un même problème : la reconnaissance de chiffres manuscrits (Lambert Rosique)
De Keras, on va prendre le mnist (qui est le nom du dataset que l’on va utiliser), et le
backend Tensorflow, nommé K, pour lequel on va spécifier le format de saisie des
couches du modèle grâce à « channels_first ».
« channels_first » signifie que les kernels des convolutions auront pour format (depth,
input_depth, rows, cols), à l’inverse de « channels_last » qui veut dire (rows, cols,
input_depth, depth). Nous prendrons aussi le modèle, les couches (convolutions,
pooling, etc…).
Lors de la génération du modèle, de nombreux paramètres sont choisis aléatoirement par
Keras via Numpy. Afin d’avoir exactement le même modèle (et donc les mêmes résultats),
il est courant de fixer le random grâce à np.random.seed (que vous devez donc ajouter).
import numpy as np
from keras.datasets import mnist
from keras.utils import np_utils
from keras import backend as K
K.set_image_data_format('channels_first')
fix random seed for reproducibility
seed = 7
np.random.seed(seed)
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
2
Commençons par charger les données, qui sont
#load data
(X_train, y_train),(X_test, y_test)= mnist.load_data()
Ensuite, par rapport à notre configuration de TensorFlow, il va falloir modifier
légèrement la structure des matrices pour qu’elles soient utilisables dans le modèle.
On a pour l’instant du 60000x28x28, et on voudrait du 60000x1x28x28 (nombre
d’entrées, nombre de channels, largeur d’une entrée, hauteur d’une entrée). La
commande « reshape » permet exactement de faire ça, à laquelle on ajoute « astype »
pour convertir les matrices en float32 au lieu de uint8 (Unsigned integer (0 to 255)).
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 1, 28,28).astype
('float32')
X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype
('float32')
Travaillons maintenant les vecteurs de sorties pour qu’ils reflètent la valeur prédite
par le réseau. En effet, il serait très compliqué (voire impossible de manière efficace
et juste) d’avoir un CNN qui nous renverrait un seul et unique résultat entre 0 et 9
valant le chiffre détecté dans l’image. A l’inverse, il est plus facile pour un CNN de
nous donner la probabilité que ce soit un 0, la probabilité que ce soit un 1, etc…
jusqu’à 9.
Question : Définissez une fonction get_data_mnist() qui sera appelée par notre 1er
CNN, et qui retournera les différentes variables.
Def get_data_mnist() :
#load data
...
# reshape to be [samples][pixels][width][height]
...
#one hot encode outputs
3
...
return (X_train, y_train), (X_test, y_test), num_classes
Pour déclarer un nouveau modèle de deep learning dans Keras, on utilise l’instruction
suivante, qui vaut aussi bien pour des ANN que des CNN qu’autre chose :
model = Sequential()
Ensuite, les méthodes à appeler sont très parlantes. Notre objectif est d’avoir successivement :
# create model
model = Sequential()
model.add(Conv2D(64, (3, 3), input_shape=(1, 28, 28),
activation='relu'))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(Flatten())
model.add(Dense(num_classes, activation='softmax'))
le loss : c’est une fonction qui va servir à mesurer l’écart entre les prédictions de
notre modèle et les résultats attendus. Elle évalue donc la justesse du CNN et permet
de mieux l’adapter aux données si besoin! Nous allons utiliser
« categorical_crossentropy » comme loss, car on a des données de type
« catégories » en sortie de l’algorithme.
l’optimizer : c’est un algorithme qui va dicter comment mettre à jour le CNN pour
diminuer le loss, et avoir donc de meilleures prédictions. Ici on s’appuiera sur
« adam » (adaptive moment estimation), très souvent utilisé.
Le paramètre metrics : c’est exactement comme le loss, sauf que metrics n’est PAS
utilisée par le CNN, à l’inverse du loss qui sert pour la mise à jour des variables du
4
CNN via l’optimizer. On utilisera cette fois « accuracy », sans que cela ait de réelle
importance pour nous.
def small_model():
# create model
...
#compile model
...
return model
Pour entraîner un modèle, il suffit d’appeler la méthode fit qui prend en arguments :
5
60000/60000 [==============================] - 203s 3ms/step - loss: 0.0126 - accuracy: 0.9955
- val_loss: 0.0971 - val_accuracy: 0.9796
Epoch 7/10
60000/60000 [==============================] - 204s 3ms/step - loss: 0.0114 - accuracy: 0.9963
- val_loss: 0.1044 - val_accuracy: 0.9779
Epoch 8/10
60000/60000 [==============================] - 189s 3ms/step - loss: 0.0142 - accuracy: 0.9954
- val_loss: 0.1227 - val_accuracy: 0.9768
Epoch 9/10
60000/60000 [==============================] - 142s 2ms/step - loss: 0.0115 - accuracy: 0.9966
- val_loss: 0.1266 - val_accuracy: 0.9767
Epoch 10/10
60000/60000 [==============================] - 138s 2ms/step - loss: 0.0132 - accuracy: 0.9959
- val_loss: 0.1291 - val_accuracy: 0.9760
6
Le dropout pour sa part est ajouté via Dropout, qui reçoit directement le taux
de dropout (i.e. 0.2). Cela signifie que 20% des neurones seront ignorés
4. Construire, entrainer et évaluer le large_CNN défini comme suit :
Une convolution de 30 filtres en 5×5 avec une activation ReLU (n’oubliez pas
l’input_shape)
Un max-pooling de 2×2
Une convolution de 15 filtres en 3×3 avec ReLU
Un dropout de 0.2
Un flatten
Un dense de 128 sorties avec ReLU
Un dense de 50 sorties avec ReLU
Un dense de 10 sorties avec softmax