Keras : classificateur spirales

This commit is contained in:
Philippe Roy 2023-06-28 19:52:58 +02:00
parent 37e5fc2e58
commit 5497267973
3 changed files with 91 additions and 59 deletions

View File

@ -1,6 +1,8 @@
import os, time import os, time
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import tensorflow as tf import tensorflow as tf
from tensorflow import keras from tensorflow import keras
@ -54,57 +56,97 @@ from tensorflow import keras
# Initialisation # Initialisation
############################################################################### ###############################################################################
# Init de Tensorflow + Keras
# tf.__version__
# keras.__version__
# tf.config.list_physical_devices('GPU')
# Init du temps # Init du temps
t_debut = time.time() t_debut = time.time()
# Init des plots # Init des plots
fig = plt.figure(layout="constrained", figsize=(15, 5)) fig = plt.figure(figsize=(15, 5))
fig.suptitle("Réseaux de neurones avec Keras - Classificateur d'images") fig.suptitle("Réseaux de neurones avec Keras - Classificateur : points sur une spirale")
subfigs = fig.subfigures(1, 3) model_ax = fig.add_subplot(131) # Modèle
model_ax = subfigs[0].subplots(1, 1) apts_ax = fig.add_subplot(132) # Courbes d'apprentissage
apts_ax = subfigs[1].subplots(1, 1) donnees_ax = fig.add_subplot(133) # Observations : x1,x2 et cibles : y
img_ax = subfigs[2].subplots(4, 8)
############################################################################### ###############################################################################
# Observations # Observations
############################################################################### ###############################################################################
# Observations d'apprentissage, de validation et de test # Observations d'apprentissage
vetement = keras.datasets.fashion_mnist # Jeu de données Fashion MNIST m = 300 # Nombre d'observations
(X, y), (X_test, y_test) = vetement.load_data() bg = 1 # Quantité du bruit gaussien # FIXME : pas en place
X_train, y_train = X[5000:]/255.0 , y[5000:] rayon = 2.5 # Rayon de séparation
X_valid, y_valid = X[:5000]/255.0 , y[:5000] marge = 0.25
classes = ["Tshirt", "Pantalon", "Pull", "Robe", "Manteau", "Sandale", "Chemise", "Basket", "Sac", "Bottine"] x1 = np.empty(m)
x2 = np.empty(m)
y = np.empty(m)
# Go !
j=0
j_m= round(m/2)-1
for i in range (j_m):
# Première spirale
idx = np.random.uniform(0, j_m)
deltaT = 0
r= idx / j_m * 5
t = 1.75 * idx / j_m * 2 * np.pi + deltaT
x1[j] = r * np.sin(t)
x2[j] = r * np.cos(t)
y[j] = 1
j+=1
# Deuxième spirale
idx = np.random.uniform(0, j_m)
deltaT = np.pi
r= idx / j_m * 5
t = 1.75 * idx / j_m * 2 * np.pi + deltaT
x1[j] = r * np.sin(t)
x2[j] = r * np.cos(t)
y[j] = 0
j+=1
# Split en observations d'entrainement et de validation
test_size=0.1 # Ratio du lot de test
m_train = int(np.round(m*(1-test_size)))
x1_train, x2_train, y_train = x1[:m_train], x2[:m_train], y[:m_train] # Jeu d'entrainement
x1_valid, x2_valid, y_valid = x1[m_train:], x2[m_train:], y[m_train:] # Jeu de validation
X_train = np.c_[x1_train, x2_train]
X_valid = np.c_[x1_valid, x2_valid]
# Plots
donnees_ax.plot(x1_train[y_train==1], x2_train[y_train==1], "o", markerfacecolor="tab:blue", markeredgecolor='white', markeredgewidth=0.75)
donnees_ax.plot(x1_train[y_train==0], x2_train[y_train==0], "o" , markerfacecolor="tab:orange", markeredgecolor='white', markeredgewidth=0.75)
donnees_ax.plot(x1_valid[y_valid==1], x2_valid[y_valid==1], "o", markerfacecolor='tab:blue', markeredgecolor='black')
donnees_ax.plot(x1_valid[y_valid==0], x2_valid[y_valid==0], "o", markerfacecolor='tab:orange', markeredgecolor='black')
# Nouvelles observations
m_new = 100 # Résolution par axes
x1_new=np.linspace(-6, 6, m_new).reshape(-1, 1)
x2_new=np.linspace(-6, 6, m_new).reshape(-1, 1)
x1_new_mg, x2_new_mg = np.meshgrid(x1_new, x2_new)
X_new = np.c_[x1_new_mg.ravel(), x2_new_mg.ravel()]
############################################################################### ###############################################################################
# Phase d'apprentissage # Phase d'apprentissage
############################################################################### ###############################################################################
n = 30 # Nombre d'itérations (valeur par défaut : 30 , hyperparamètre) n = 3000 # Nombre d'itérations (valeur par défaut : 40 , hyperparamètre)
eta = 0.01 # Taux d'appentissage (valeur par défaut dans Keras : 0.01, hyperparamètre) eta = 0.01 # Taux d'appentissage (valeur par défaut dans Keras : 0.01, hyperparamètre)
lot=32 # Taille de lot (valeur par défaut dans Keras: 32 , hyperparamètre) lot=32 # Taille de lot (valeur par défaut dans Keras: 32 , hyperparamètre)
perte="sparse_categorical_crossentropy" # Type de perte (hyperparamètre)
#perte="mse" # Type de perte (hyperparamètre) # perte="sparse_categorical_crossentropy" # Type de perte (hyperparamètre)
perte="mse" # Type de perte (hyperparamètre)
# perte='mean_absolute_error'
keras.backend.clear_session() keras.backend.clear_session()
# np.random.seed(42)
# tf.random.set_seed(42)
model = keras.models.Sequential() # Modèle de reseau de neurones model = keras.models.Sequential() # Modèle de reseau de neurones
model.add(keras.layers.Flatten(input_shape=[28, 28])) # Couche d'entrée : mise à plat des données d'entrée -> 1 node / pixel soit 784 (28x28) model.add(keras.layers.Dense(20, input_dim=2, activation="relu")) # Couche 1 : 10 nodes
model.add(keras.layers.Dense(300, activation="relu")) # Couche 1 : 300 nodes model.add(keras.layers.Dense(20, activation="relu")) # Couche 2 : 10 nodes
# model.add(keras.layers.Dense(300, activation="relu")) # Couche 2 : 300 nodes -> passage de 100 à 300 model.add(keras.layers.Dense(20, activation="relu")) # Couche 3 : 10 nodes
# model.add(keras.layers.Dense(300, activation="relu")) # Couche 3 : 300 nodes -> ajout model.add(keras.layers.Dense(20, activation="relu")) # Couche 4 : 10 nodes
model.add(keras.layers.Dense(100, activation="relu")) # Couche 4 : 100 nodes -> ajout model.add(keras.layers.Dense(20, activation="relu")) # Couche 5 : 10 nodes
model.add(keras.layers.Dense(10, activation="softmax")) # Couche de sortie : 1 node par classe soit 10 model.add(keras.layers.Dense(20, activation="relu")) # Couche 6 : 10 nodes
model.add(keras.layers.Dense(1, activation="sigmoid")) # Couche de sortie : 1 node par classe
# model.compile(loss="sparse_categorical_crossentropy", optimizer="sgd", metrics=["accuracy"])
optimiseur=keras.optimizers.SGD(learning_rate= eta) optimiseur=keras.optimizers.SGD(learning_rate= eta)
model.compile(loss=perte, optimizer=optimiseur, metrics=["accuracy"]) # Compilation du modèle model.compile(loss=perte, optimizer=optimiseur, metrics=["accuracy"]) # Compilation du modèle
@ -114,20 +156,8 @@ apts = model.fit(X_train, y_train, epochs=n, batch_size=lot, validation_data=(X_
# Phase d'inférence # Phase d'inférence
############################################################################### ###############################################################################
# X_new=[] y_predict=model.predict(X_new) # Prédiction
# y_new=[] y_predict_map = y_predict.reshape(x1_new_mg.shape)
# for i in range(8):
# idx = np.random.randint(X_test.shape[0]) # Index aléatoire
# X_new.append(X_test[idx:idx+1]/255.0)
# y_new.append(y_test[idx:idx+1])
idx = np.random.randint(X_test.shape[0]-32) # Index aléatoire
print ("\n")
print ("Test sur les images de "+ str(idx) + " à "+ str(idx+32) + " sur un jeu de 10 000 images.")
X_new = X_test[idx:idx+32]
y_new = np.argmax(model.predict(X_new), axis=-1)
y_new_test= y_test[idx:idx+32]
print ("\n")
############################################################################### ###############################################################################
# Résultats # Résultats
@ -145,22 +175,23 @@ os.remove("model.png") # Supression du fichier temporaire
apts_ax.set_title("Courbes d'apprentissage") apts_ax.set_title("Courbes d'apprentissage")
apts_ax.plot(apts.epoch, apts.history['loss'], 'b-', label="Perte - entrainement") apts_ax.plot(apts.epoch, apts.history['loss'], 'b-', label="Perte - entrainement")
apts_ax.plot(apts.epoch, apts.history['val_loss'], 'r-', label="Perte - validation") apts_ax.plot(apts.epoch, apts.history['val_loss'], 'r-', label="Perte - validation")
apts_ax.plot(apts.epoch, apts.history['accuracy'], 'b:', label="Précision - entrainement") apts_ax.plot(apts.epoch, apts.history['accuracy'], 'c-', label="Précision - entrainement")
apts_ax.plot(apts.epoch, apts.history['val_accuracy'], 'r:', label="Précision - validation") apts_ax.plot(apts.epoch, apts.history['val_accuracy'], 'm-', label="Précision - validation")
apts_ax.set(ylim=(0, 1)) apts_ax.set(ylim=(-0.05, 1.05))
apts_ax.set_xlabel("Époque") apts_ax.set_xlabel("Époque")
apts_ax.legend() apts_ax.legend()
# Prédictions # Plot des données
for i in range (8): donnees_ax.set_title("Données")
for j in range (4): new_colors = ["tab:orange", "white", "tab:blue"]
img_ax[j][i].imshow(X_new[i*2+j], cmap="binary", interpolation="nearest") new_cmap = LinearSegmentedColormap.from_list("mycmap", new_colors) # FIXME : faire un dégradé
img_ax[j][i].set_axis_off() cc = donnees_ax.contourf(x1_new_mg, x2_new_mg, y_predict_map, cmap=new_cmap)
if y_new[i*2+j] == y_new_test[i*2+j]: donnees_ax.set_xticks([-5,0,5])
img_ax[j][i].set_title(classes[y_new[i*2+j]], fontsize=10) donnees_ax.set_yticks([-5,0,5])
else: donnees_ax.set_xlabel(r'$x_1$')
img_ax[j][i].set_title(classes[y_new[i*2+j]], fontsize=10, color="red") donnees_ax.set_ylabel(r'$x_2$', rotation=0)
donnees_ax.set(xlim=(-5.25, 5.25), ylim=(-5.25, 5.25))
fig.colorbar(cc, ax=donnees_ax)
plt.show() plt.show()
# Performances # Performances

View File

@ -20,5 +20,6 @@
![capture d'écran](img/05-keras-tf_playground-gauss.png) ![capture d'écran](img/05-keras-tf_playground-gauss.png)
### Réseaux de neurones avec Keras - Classificateur : Points sur spirales
![capture d'écran](img/06-keras-tf_playground-spiral.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB