Implémentation étape par étape de VGG16 dans Keras pour les débutants

VGG16 est une architecture de réseau neuronal à convolution (CNN) qui a été utilisée pour remporter le concours ILSVR (Imagenet) en 2014. Il est considéré comme l’un des excellents modèles d’architecture de vision jusqu’à ce jour. La chose la plus unique à propos de VGG16 est qu’au lieu d’avoir un grand nombre d’hyperparamètres, ils se sont concentrés sur des couches de convolution de filtre 3×3 avec une foulée 1 et ont toujours utilisé le même rembourrage et la couche maxpool de filtre 2×2 de foulée 2. Il suit cet arrangement de convolution et de couches de pool max de manière cohérente dans toute l’architecture. En fin de compte, il a 2 FC (couches entièrement connectées) suivies d’un softmax pour la sortie. Le 16 dans VGG16 fait référence à 16 couches qui ont des poids. Ce réseau est un réseau assez grand et il a environ 138 millions de paramètres (environ).

Architecture de VGG16

Je vais implémenter VGG16 complet à partir de zéro dans Keras. Cette implémentation sera effectuée sur l’ensemble de données Chiens vs Chats. Vous pouvez télécharger le jeu de données à partir du lien ci-dessous.

https://www.kaggle.com/c/dogs-vs-cats/data

Une fois que vous avez téléchargé les images, vous pouvez suivre les étapes écrites ci-dessous.

import keras,os
from keras.models import Sequential
from keras.layers import Dense, Conv2D, MaxPool2D , Flatten
from keras.preprocessing.image import ImageDataGenerator
import numpy as np

Ici, j’importe d’abord toutes les bibliothèques dont j’aurai besoin pour implémenter VGG16. J’utiliserai la méthode séquentielle pendant que je crée un modèle séquentiel. Le modèle séquentiel signifie que toutes les couches du modèle seront disposées en séquence. Ici, j’ai importé ImageDataGenerator de keras.prétraitement. L’objectif d’ImageDataGenerator est d’importer facilement des données avec des étiquettes dans le modèle. C’est une classe très utile car elle a de nombreuses fonctions pour redimensionner, faire pivoter, zoomer, retourner, etc. La chose la plus utile à propos de cette classe est qu’elle n’affecte pas les données stockées sur le disque. Cette classe modifie les données en déplacement tout en les transmettant au modèle.

trdata = ImageDataGenerator()
traindata = trdata.flow_from_directory(directory="data",target_size=(224,224))
tsdata = ImageDataGenerator()
testdata = tsdata.flow_from_directory(directory="test", target_size=(224,224))

Ici, je crée et objet d’ImageDataGenerator pour les données d’entraînement et de test et je transmets le dossier qui contient des données de train à l’objet trdata et de même le dossier qui contient des données de test à l’objet tsdata. La structure des dossiers des données sera la suivante –

>

Structure du dossier des données à transmettre à ImageDataGenerator

L’ImageDataGenerator étiquettera automatiquement toutes les données du dossier cat en tant que dossier cat et vis-à-vis du dossier dog. De cette façon, les données sont facilement prêtes à être transmises au réseau de neurones.

model = Sequential()model.add(Conv2D(input_shape=(224,224,3),filters=64,kernel_size=(3,3),padding="same", activation="relu"))model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=128, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=256, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(Conv2D(filters=512, kernel_size=(3,3), padding="same", activation="relu"))model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))

Ici, j’ai commencé à initialiser le modèle en spécifiant que le modèle est un modèle séquentiel. Après avoir initialisé le modèle, j’ajoute

→ 2 x couche de convolution de 64 canaux de 3×3 kernal et même rembourrage

→ 1 x couche maxpool de taille de piscine 2×2 et foulée 2×2

→ 2 x couche de convolution de 128 canaux de kernal 3×3 et même rembourrage

→ 1 x couche maxpool de taille de piscine 2×2 et foulée 2×2

→ 3 x couche de convolution de 256 canal de 3×3 kernal et même rembourrage

→ 1 x couche maxpool de 2×2 taille de piscine et foulée 2×2

→ 3 x couche de convolution de 512 canal de 3×3 kernal et même rembourrage

→ 1 x couche maxpool de 2×2 taille de piscine et foulée 2×2

→ 3 x couche de convolution de canal 512 de noyau 3×3 et même remplissage

→ 1 x couche maxpool de taille de pool 2×2 et foulée 2×2

J’ajoute également une activation relu (Unité Linéaire rectifiée) à chaque couche afin que toutes les valeurs négatives ne soient pas transmises à la couche suivante.

model.add(Flatten())model.add(Dense(units=4096,activation="relu"))model.add(Dense(units=4096,activation="relu"))model.add(Dense(units=2, activation="softmax"))

Après avoir créé toute la convolution, je passe les données à la couche dense pour que j’aplatisse le vecteur qui sort des circonvolutions et ajoute

→ 1 x Couche dense de 4096 unités

→ 1 x Couche Dense de 4096 unités

→ 1 x Couche Dense Softmax de 2 unités

J’utiliserai l’activation RELU pour les deux la couche dense de 4096 unités afin que j’arrête de transmettre des valeurs négatives via le réseau. J’utilise une couche dense de 2 unités à la fin avec l’activation de softmax car j’ai 2 classes à prédire à la fin qui sont le chien et le chat. Le calque softmax affichera la valeur entre 0 et 1 en fonction de la confiance du modèle à laquelle appartient la classe à laquelle appartiennent les images.

Après la création du calque softmax, le modèle est enfin préparé. Maintenant, je dois compiler le modèle.

from keras.optimizers import Adam
opt = Adam(lr=0.001)model.compile(optimizer=opt, loss=keras.losses.categorical_crossentropy, metrics=)

Ici, j’utiliserai l’optimiseur Adam pour atteindre les minima globaux tout en m’entraînant sur le modèle. Si je suis coincé dans des minima locaux pendant l’entraînement, l’optimiseur adam nous aidera à sortir des minima locaux et à atteindre les minima mondiaux. Nous préciserons également le taux d’apprentissage de l’optimiseur, ici dans ce cas il est fixé à 0,001. Si notre formation rebondit beaucoup sur les époques, nous devons réduire le taux d’apprentissage afin d’atteindre des minima globaux.

Je peux vérifier le résumé du modèle que j’ai créé en utilisant le code ci-dessous.

model.summary()

La sortie de ceci sera le résumé du modèle que je viens de créer.

Résumé du modèle
from keras.callbacks import ModelCheckpoint, EarlyStoppingcheckpoint = ModelCheckpoint("vgg16_1.h5", monitor='val_acc', verbose=1, save_best_only=True, save_weights_only=False, mode='auto', period=1)early = EarlyStopping(monitor='val_acc', min_delta=0, patience=20, verbose=1, mode='auto')hist = model.fit_generator(steps_per_epoch=100,generator=traindata, validation_data= testdata, validation_steps=10,epochs=100,callbacks=)

Après la création du modèle, j’importerai ModelCheckpoint et la méthode EarlyStopping de keras. Je vais créer un objet des deux et le transmettre en tant que fonctions de rappel à fit_generator.

ModelCheckpoint nous aide à enregistrer le modèle en surveillant un paramètre spécifique du modèle. Dans ce cas, je surveille la précision de la validation en passant val_acc à ModelCheckpoint. Le modèle ne sera enregistré sur le disque que si la précision de validation du modèle à l’époque actuelle est supérieure à ce qu’elle était à la dernière époque.

EarlyStopping nous aide à arrêter l’entraînement du modèle tôt s’il n’y a pas d’augmentation du paramètre que j’ai défini pour surveiller dans EarlyStopping. Dans ce cas, je surveille la précision de la validation en passant val_acc à EarlyStopping. J’ai ici mis la patience à 20, ce qui signifie que le modèle s’arrêtera pour s’entraîner s’il ne voit aucune augmentation de la précision de validation dans 20 époques.

J’utilise le modèle.fit_generator car j’utilise ImageDataGenerator pour transmettre des données au modèle. Je transmettrai les données de train et de test à fit_generator. Dans fit_generator, steps_per_epoch définira la taille du lot pour transmettre les données d’entraînement au modèle et validation_steps fera de même pour les données de test. Vous pouvez le modifier en fonction des spécifications de votre système.

Après avoir exécuté la ligne ci-dessus, le modèle commencera à s’entraîner et vous commencerez à voir la précision et la perte de la formation / validation.

Formation de la model

Une fois que vous avez formé le modèle, vous pouvez visualiser la précision et la perte de la formation / validation. Comme vous l’avez peut-être remarqué, je passe la sortie du mode.fit_generator à la variable hist. Toute la précision et la perte de la formation / validation sont stockées dans hist et je la visualiserai à partir de là.

import matplotlib.pyplot as plt
plt.plot(hist.history)
plt.plot(hist.history)
plt.plot(hist.history)
plt.plot(hist.history)
plt.title("model accuracy")
plt.ylabel("Accuracy")
plt.xlabel("Epoch")
plt.legend()
plt.show()

Ici, je vais visualiser la précision et la perte de la formation / validation à l’aide de matplotlib.

précision et perte de la formation / validation

Pour faire des prédictions sur le modèle entraîné, je dois charger le modèle le mieux enregistré, pré-traiter l’image et transmettre l’image au modèle pour la sortie.

from keras.preprocessing import imageimg = image.load_img("image.jpeg",target_size=(224,224))
img = np.asarray(img)
plt.imshow(img)
img = np.expand_dims(img, axis=0)from keras.models import load_model
saved_model = load_model("vgg16_1.h5")output = saved_model.predict(img)
if output > output:
print("cat")
else:
print('dog')

Sortie du modèle

Ici, j’ai chargé l’image en utilisant la méthode image dans keras et l’ai convertie en tableau numpy et ajouté une dimension supplémentaire à l’image à l’image pour faire correspondre le format NHWC (Nombre, Hauteur, Largeur, Canal) des keras.

Ceci est une implémentation complète de VGG16 dans keras en utilisant ImageDataGenerator. Nous pouvons faire fonctionner ce modèle pour n’importe quel nombre de classes en changeant l’unité de la dernière couche dense softmax en le nombre que nous voulons en fonction des classes que nous devons classer

Lien de dépôt Github: https://github.com/1297rohit/VGG16-In-Keras

Si vous avez moins de données, au lieu de former votre modèle à partir de zéro, vous pouvez essayer l’apprentissage par transfert. J’ai également écrit un guide étape par étape pour les débutants sur l’apprentissage par transfert sur VGG16 à l’aide de Keras. Vous pouvez le vérifier à : https://medium.com/@1297rohit/transfer-learning-from-scratch-using-keras-339834b153b9

Si vous souhaitez apprendre étape par étape sur la Détection et la reconnaissance des visages à partir de zéro, vous pouvez vous diriger vers mon article sur ce sujet sur le lien: https://medium.com/@1297rohit/step-by-step-face-recognition-code-implementation-from-scratch-in-python-cc95fa041120

Profitez de la classification!

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.