Vérification des versions¶

In [ ]:
#version de Python
import sys
sys.version
Out[ ]:
'3.11.9 | packaged by Anaconda, Inc. | (main, Apr 19 2024, 16:40:41) [MSC v.1916 64 bit (AMD64)]'
In [ ]:
#tensorflow
import tensorflow as tf
tf.__version__
Out[ ]:
'2.16.1'
In [ ]:
#et la version de Keras associée
tf.keras.__version__
Out[ ]:
'3.3.3'

Chargement et inspection d'une image¶

In [ ]:
#dossier par défaut
import os
os.chdir("C:/Users/ricco/Desktop/demo")
In [ ]:
#charger une image pour inspection
import matplotlib.pyplot as plt
f = open("./images/train/Beedrill/0ad2b3a7d4124698bfd65d1932323ec0.jpg","rb")
image = plt.imread(f)

#type
type(image)
Out[ ]:
numpy.ndarray
In [ ]:
#dimension de l'image -- 3 canaux RGB
image.shape
Out[ ]:
(502, 466, 3)
In [ ]:
#valeurs min et max
import numpy as np
print(f"Min = {np.min(image)}")
print(f"Max = {np.max(image)}")
Min = 0
Max = 255
In [ ]:
#affichage
plt.imshow(image)
Out[ ]:
<matplotlib.image.AxesImage at 0x1c099559dd0>
No description has been provided for this image

Chargement et inspection de la base TRAIN¶

In [ ]:
#outil pour chargement du flux d'images TRAIN
#structure itérable
#normalisation des valeurs des pixels entre [0, 1]
#harmonisation des définitions en (128, 128)
#chargement individuel - batch_size = 1
from tensorflow.keras.preprocessing.image import ImageDataGenerator
image_gen = ImageDataGenerator(rescale = 1.0/255)

#parser le dossier TRAIN
train_image_gen = image_gen.flow_from_directory(
    directory="./images/train/",
    target_size=(128,128),
    color_mode='rgb',
    shuffle=True,
    batch_size=1
)
Found 54 images belonging to 2 classes.
In [ ]:
#type de la structure
type(train_image_gen)
Out[ ]:
keras.src.legacy.preprocessing.image.DirectoryIterator
In [ ]:
#classes d'appartenance
train_image_gen.classes
Out[ ]:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
In [ ]:
#nom des classes
train_image_gen.class_indices
Out[ ]:
{'Beedrill': 0, 'Cubone': 1}
In [ ]:
#accès à une image de la structure itérable
image, label = next(train_image_gen)

#attention à la structure de label
#codage disjonctif complet 0/1
#colonne 0 : Beedrill
#colonne 1 : Cubone
print(label)
[[0. 1.]]
In [ ]:
#en d'autres termes pour avoir l'indice de la classe d'appartenance
np.argmax(np.array(label))
Out[ ]:
1
In [ ]:
#type de l'image
type(image)
Out[ ]:
numpy.ndarray
In [ ]:
#dimension de l'image ici -- 1 dim. supplémentaire
#cf. conséquence de batch_size = 1 
image.shape
Out[ ]:
(1, 128, 128, 3)
In [ ]:
#dim. après retrait de la dim = 1
image.squeeze().shape
Out[ ]:
(128, 128, 3)
In [ ]:
#affichage - en retirant la dim. à 1
plt.imshow(image.squeeze())
Out[ ]:
<matplotlib.image.AxesImage at 0x1c099606190>
No description has been provided for this image
In [ ]:
#accès à l'image suivante
image, label = next(train_image_gen)

print(label)
[[0. 1.]]
In [ ]:
#affichage
plt.imshow(image.squeeze())
Out[ ]:
<matplotlib.image.AxesImage at 0x1c0996a2e10>
No description has been provided for this image

ConvNet - Réseau de neurones convolutifs¶

Structure du réseau

In [ ]:
#construction du réseau - définir les différentes couches
from tensorflow.keras import layers

#définition du CNN
#utilisation de Sequential ici
#mais on pourrait faire autemenent avec Model
#voir https://keras.io/api/models/model/
mon_cnn = tf.keras.Sequential()
#départ -- dim. image en entrée
mon_cnn.add(tf.keras.Input(shape=(128,128,3)))
#convolutions
mon_cnn.add(layers.Conv2D(filters=6,kernel_size=5,activation='relu'))
mon_cnn.add(layers.MaxPool2D(pool_size=(2,2)))
mon_cnn.add(layers.Conv2D(filters=16,kernel_size=5,activation='relu'))
mon_cnn.add(layers.MaxPool2D(pool_size=(2,2)))
#flatten
mon_cnn.add(layers.Flatten())
#couches denses
mon_cnn.add(layers.Dense(120,activation='relu'))
mon_cnn.add(layers.Dense(84,activation='relu'))
#couche de sortie avec fn de transfert softmax
mon_cnn.add(layers.Dense(2,activation='softmax'))

#vérification
mon_cnn.summary()
Model: "sequential_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type)                    ┃ Output Shape           ┃       Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ conv2d_2 (Conv2D)               │ (None, 124, 124, 6)    │           456 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d_2 (MaxPooling2D)  │ (None, 62, 62, 6)      │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ conv2d_3 (Conv2D)               │ (None, 58, 58, 16)     │         2,416 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling2d_3 (MaxPooling2D)  │ (None, 29, 29, 16)     │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten_1 (Flatten)             │ (None, 13456)          │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_3 (Dense)                 │ (None, 120)            │     1,614,840 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_4 (Dense)                 │ (None, 84)             │        10,164 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_5 (Dense)                 │ (None, 2)              │           170 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
 Total params: 1,628,046 (6.21 MB)
 Trainable params: 1,628,046 (6.21 MB)
 Non-trainable params: 0 (0.00 B)

Paramétrage de l'entraînement

In [ ]:
# paramétrage de l'entraînement
# algo d'optimisation
# fonction de perte
# performance à suivre durant l'optimisation
mon_cnn.compile(optimizer='adam',
              loss=tf.keras.losses.categorical_crossentropy,
              metrics=['accuracy'])

Entraînement du modèle

In [ ]:
#entraînement du modèle
resultat = mon_cnn.fit(train_image_gen,epochs=15)
Epoch 1/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 3s 18ms/step - accuracy: 0.5339 - loss: 1.2520
Epoch 2/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 0.8278 - loss: 0.4875
Epoch 3/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 0.9589 - loss: 0.1959
Epoch 4/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 20ms/step - accuracy: 1.0000 - loss: 0.0079
Epoch 5/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 18ms/step - accuracy: 1.0000 - loss: 0.0016
Epoch 6/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 18ms/step - accuracy: 1.0000 - loss: 1.8448e-04
Epoch 7/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 3.8167e-04
Epoch 8/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 18ms/step - accuracy: 1.0000 - loss: 2.1795e-04
Epoch 9/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 1.2230e-04
Epoch 10/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 7.2162e-05
Epoch 11/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 8.0056e-05
Epoch 12/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 18ms/step - accuracy: 1.0000 - loss: 5.9983e-05
Epoch 13/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 18ms/step - accuracy: 1.0000 - loss: 6.9411e-05
Epoch 14/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 5.7248e-05
Epoch 15/15
54/54 ━━━━━━━━━━━━━━━━━━━━ 1s 19ms/step - accuracy: 1.0000 - loss: 4.9010e-05

Vérification du classement pour une image

In [ ]:
#application sur une image
image, label = next(train_image_gen)

#affichage de l'étiquette
print(label)

#affichage de l'image
plt.imshow(image.squeeze())
[[1. 0.]]
Out[ ]:
<matplotlib.image.AxesImage at 0x1c09aa67550>
No description has been provided for this image
In [ ]:
#prédiction
pred = mon_cnn.predict(image)
print(pred)
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step
[[9.9979883e-01 2.0112531e-04]]
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 85ms/step
[[9.9979883e-01 2.0112531e-04]]

Evaluation sur la base TEST¶

In [ ]:
#parser le dossier TEST avec les mêmes spécifs que "train"
#mais pas besoin de shuffle (shuffle = False)
test_image_gen = image_gen.flow_from_directory(
    directory="./images/test/",
    target_size=(128,128),
    color_mode='rgb',
    shuffle=False,
    batch_size=1
)
Found 20 images belonging to 2 classes.
In [ ]:
#nombre d'individus dans la base de test
test_image_gen.n
Out[ ]:
20
In [ ]:
#evaluation - calcul de l'accuracy
#structure pour stocker classe prédite et classe réelle
lst_pred = []
lst_real = []

#itérer sur chaque individu
for i in range(test_image_gen.n):
    #image et etiquette de l'individu
    image, label = next(test_image_gen)
    #prédiction du réseau
    sortie = mon_cnn.predict(image)
    #en déduire la classe attribuée
    pred = np.argmax(np.array(sortie))
    #et la classe réelle
    real = np.argmax(np.array(label))
    #stocker
    lst_pred.append(pred)
    lst_real.append(real)

#affichages
print("Prediction : ")
print(lst_pred)

print("Appartenance réelle :")
print(lst_real)
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 23ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 23ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 22ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 24ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 25ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 30ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 27ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 27ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 22ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 26ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 27ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 32ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 28ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 21ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 25ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 29ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 19ms/step
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 24ms/step
Prediction : 
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]
Appartenance réelle :
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
In [ ]:
#calcul de l'accuracy
acc = np.mean((np.array(lst_pred)==np.array(lst_real)))
print(f"Accuracy = {acc}")
Accuracy = 0.9