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>
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>
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>
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>
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