Il est fortement recommandé d’avoir étudié le tutoriel #1 et le tutoriel #2 avant celui-ci car on y trouve de nombreux éléments communs qui ne sont pas re-expliqués ici.

Cet article commente le tutoriel Tensorflow #3 de Magnus Erik Hvass Pedersen  : Keras API. Le code est ici et la vidéo ici (en anglais).

Les convolutions ne sont pas expliquées dans notre article. Elles sont supposées connues (cf #1 et #2).

Dans ce tutoriel l’objectif est le même que pour le tutoriel #2 mais au lieu d’utiliser les API TensorFlow on utilisera les API de Keras (voir aussi Keras tutoriel #1)

Flux

Pour rappel, le réseau implémenté est représenté ci-dessous :

Imports

En plus des imports habituels, on importe de Keras :

# from tf.keras.models import Sequential  # This does not work!
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import InputLayer, Input
from tensorflow.python.keras.layers import Reshape, MaxPooling2D
from tensorflow.python.keras.layers import Conv2D, Dense, Flatten

Lorsque Magnus a écrit son code il semble qu’on ne pouvait pas écrire tout simplement :

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import InputLayer, Input, Reshape,MaxPooling2D, Conv2D, Dense, Flatten

désormais c’est possible.

on peut aussi écrire :

from keras.models import Sequential

mais il faut probablement une installation séparée de Keras.`

Sequential Model

Le modèle séquentiel de Keras est ce qu’il y a de plus intéressant dans l’API car il est très simple d’utilisation.

Il suffit de décrire l’empilement des couches de neurones.

# Start construction of the Keras Sequential model.
model = Sequential()

# Add an input layer which is similar to a feed_dict in TensorFlow.
# Note that the input-shape must be a tuple containing the image-size.
model.add(InputLayer(input_shape=(img_size_flat,)))

# The input is a flattened array with 784 elements,
# but the convolutional layers expect images with shape (28, 28, 1)
model.add(Reshape(img_shape_full))

# First convolutional layer with ReLU-activation and max-pooling.
model.add(Conv2D(kernel_size=5, strides=1, filters=16, padding='same',
                 activation='relu', name='layer_conv1'))
model.add(MaxPooling2D(pool_size=2, strides=2))

# Second convolutional layer with ReLU-activation and max-pooling.
model.add(Conv2D(kernel_size=5, strides=1, filters=36, padding='same',
                 activation='relu', name='layer_conv2'))
model.add(MaxPooling2D(pool_size=2, strides=2))

# Flatten the 4-rank output of the convolutional layers
# to 2-rank that can be input to a fully-connected / dense layer.
model.add(Flatten())

# First fully-connected / dense layer with ReLU-activation.
model.add(Dense(128, activation='relu'))

# Last fully-connected / dense layer with softmax-activation
# for use in classification.
model.add(Dense(num_classes, activation='softmax'))

Comme on peut le constater, la description du modèle est très explicite.

Attardons-nous ici sur Conv2D et MaxPooling2D.

Conv2D

Conv2D permet de faire des convolutions sur des images.

keras.layers.Conv2D(filters, kernel_size, strides=(1, 1), padding='valid', data_format=None, dilation_rate=(1, 1), activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zeros', kernel_regularizer=None, bias_regularizer=None, activity_regularizer=None, kernel_constraint=None, bias_constraint=None)

Les arguments de Conv2D retenus ici sont : filters, kernel_size, strides, padding, activation, name.

Ajoutons input_shape non présent dans l’exemple.

input_shape

When using this layer as the first layer in a model, provide the keyword argument input_shape (tuple of integers, does not include the batch axis), e.g. input_shape=(128, 128, 3) for 128×128 RGB pictures in data_format="channels_last".

Le choix d’implémentation de l’exemple est d’ajouter une couche « virtuelle » avant la convolution 2D.

Ce n’est pas ce qu’on voit dans les exemples récents. Rien n’empêche (au contraire) de commencer comme ici :

model = Sequential()
  model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))

filters

filters: Integer, the dimensionality of the output space (i.e. the number of output filters in the convolution).

Le schéma décrit au § flux, montre que l’output de la 1ère convolution est constitué de 16 channels et celui de la seconde de 36 channels.

kernel_size

kernel_size est la dimension de la fenêtre de convolution. Lorsque, comme dans notre exemple, kernel_size est donné avec une seule dimension, celle-ci suppose une dimension équivalente sur tous les axes. kernel_size=5 est identique à kernel_size=(5,5)

padding

Keras ne permet que deux options pour le padding de Conv2D. Soit same, soit valid.

Ces options sont celles disponibles avec TensorFlow.

Sometimes filter does not fit perfectly fit the input image. We have two options:

  • Pad the picture with zeros (zero-padding) so that it fits

  • Drop the part of the image where the filter did not fit. This is called valid padding which keeps only valid part of the image.

Pour une bonne explication du padding, voir ici.

VALID: Don’t apply any padding, i.e., assume that all dimensions are valid so that input image fully gets covered by filter and stride you specified.

SAME: Apply padding to input (if needed) so that input image gets fully covered by filter and stride you specified. For stride 1, this will ensure that output image size is same as input.

activation

Il existe différentes façons de mettre en place l’activation.

Activations can either be used through an Activation layer, or through the activation argument supported by all forward layers:

model.add(Dense(64))
model.add(Activation('tanh'))

est équivalent à :

model.add(Dense(64, activation='tanh'))

Keras propose de nombreuses fonctions d’activation. des plus connues (tanh, sigmoid, softmax, relu) aux moins (elu, selu, hard_sigmoid, …)

La fonction choisie ici est relu.

MaxPooling2D

A chaque fois que MaxPooling2D est utilisé dans notre exemple, c’est avec les mêmes arguments.

model.add(MaxPooling2D(pool_size=2, strides=2))
  • pool_size: integer or tuple of 2 integers, factors by which to downscale (vertical, horizontal). (2, 2) will halve the input in both spatial dimension. If only one integer is specified, the same window length will be used for both dimensions.

  • strides: Integer, tuple of 2 integers, or None. Strides values. If None, it will default to pool_size.

pool_size=2 est equivalent à pool_size=(2,2). Idem pour strides.

Les arguments sont les mêmes que ceux de TensorFlow.

Pour une explication du pooling, voir ici.

Le pooling choisi permet, après la 1ère convolution, de réduire la taille des images de 28*28 à 14*14 et après la seconde à 7*7

Model Compilation

Il ne reste ensuite qu’à ajouter les fonctions d’optimisation, de perte, et de calcul de l’exactitude.

from tensorflow.python.keras.optimizers import Adam

optimizer = Adam(lr=1e-3)

model.compile(optimizer=optimizer,
              loss='categorical_crossentropy',
              metrics=['accuracy'])

Le reste du code est le même que pour le tutoriel #2.

Le modèle fonctionnel est décrit dans notre article suivant.

 

 

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *