From be4ccfc14cd301af8bf59d94898fc32c62cf2cd7 Mon Sep 17 00:00:00 2001 From: Philippe Roy Date: Fri, 7 Jul 2023 18:40:09 +0200 Subject: [PATCH] Apprentissage par renforcement : mise en place --- 03-vision/#04-cnn-cartes.py# | 253 ------------------------------ 03-vision/.#04-cnn-cartes.py | 1 - 03-vision/README.md | 2 +- 04-renforcement/01-cartpole-gp.py | 75 +++++++++ 04-renforcement/README.md | 13 ++ 5 files changed, 89 insertions(+), 255 deletions(-) delete mode 100644 03-vision/#04-cnn-cartes.py# delete mode 120000 03-vision/.#04-cnn-cartes.py create mode 100644 04-renforcement/01-cartpole-gp.py create mode 100644 04-renforcement/README.md diff --git a/03-vision/#04-cnn-cartes.py# b/03-vision/#04-cnn-cartes.py# deleted file mode 100644 index f414338..0000000 --- a/03-vision/#04-cnn-cartes.py# +++ /dev/null @@ -1,253 +0,0 @@ -import os, time -import numpy as np -import matplotlib.pyplot as plt - -import tensorflow as tf -from tensorflow import keras - -############################################################################### -# 04-cnn-cartes.py -# @title: Vision par ordinateur - Visualisation des noyaux (carte, couche, filtre) de convolution -# @project: Mes scripts de ML -# @lang: fr -# @authors: Philippe Roy -# @copyright: Copyright (C) 2023 Philippe Roy -# @license: GNU GPL -############################################################################### - -### -# Installation : -# - pip3 install tensorflow -# - pip3 install keras -### - -### -# Commandes NumPy : -# - np.array : créer un tableau à partir d'une liste de listes -# - np.c_ : concatène les colonnes des tableaux -# - np.linspace : créer un tableau 1D de la valeur de début à la valeur de fin avec n valeurs -# - np.meshgrid : créer un tableau 2D avec l'ensemble des combinaisons allant des deux valeurs de début aux deux valeurs de fin -# - .reshape : reformater la tableau avec le nombre de lignes et le nombre de colonnes -### - -### -# Commandes Keras : -# - keras.models.Sequential() : créer un modèle où les couches de neurones sont reliées séquentiellement (modèle simple) -# - model.add : ajout d'une couche -# - keras.layers.Flatten : couche de formatage de mise à plat -# - keras.layers.Dense : couche de neurones -# - keras.layers.Conv2D : couche de convolution 2D (filtre) -# - keras.layers.MaxPool2D : couche d'agrégation des cartes (noyaux de convolution) type Pooling max -# - keras.layers.Dropout : couche de régularisation par extinction (Dropout) -# - keras.backend.clear_session() : reset de la session -# - model.compile : compilation du modèle -# - model.fit : entrainement du modèle -# - model.predict : prédiction du modèle -# - keras.utils.plot_model : créer le diagramme d'un modèle -### - -############################################################################### -# Initialisation -############################################################################### - -# Init du temps -t_debut = time.time() - -# Init des plots -fig = plt.figure(layout="constrained", figsize=(15, 5)) -fig.suptitle("Vision par ordinateur - Visualisation des noyaux de convolution") -subfigs = fig.subfigures(1, 3) - -############################################################################### -# Observations -############################################################################### - -# Observations d'apprentissage, de validation et de test -mnist = keras.datasets.mnist # Jeu de données MNIST (digit) -(X, y), (X_test, y_test) = mnist.load_data() -X_train, y_train = X[5000:]/255.0 , y[5000:] -X_valid, y_valid = X[:5000]/255.0 , y[:5000] - -X_train = X_train[..., np.newaxis] # Ajout du canal nuance de gris -X_valid = X_valid[..., np.newaxis] # Ajout du canal nuance de gris -X_test = X_test[..., np.newaxis] # Ajout du canal nuance de gris - -############################################################################### -# Phase d'apprentissage -############################################################################### - -n = 10 # Nombre d'itérations (valeur par défaut : 10 , 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) - -perte="sparse_categorical_crossentropy" # Type de perte (hyperparamètre) -#perte="mse" # Type de perte (hyperparamètre) - -keras.backend.clear_session() - -# Version 1 -# model = keras.models.Sequential() # Modèle de reseau de neurones -# conv1 = keras.layers.Conv2D(32, kernel_size=3, padding="same", activation="relu") # Couche de convolution avec 32 cartes -# conv2 = keras.layers.Conv2D(64, kernel_size=3, padding="same", activation="relu") # Couche de convolution avec 64 cartes -# model.add(conv1) -# model.add(conv2) -# model.add(keras.layers.MaxPool2D()) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Flatten()) # Couche de mise à plat des données -# model.add(keras.layers.Dropout(0.25)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(128, activation="relu")) # Couche dense : 128 nodes -# model.add(keras.layers.Dropout(0.5)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(10, activation="softmax")) # Couche de sortie : 1 node par classe soit 10 - -# Version 2 -# model = keras.models.Sequential() # Modèle de reseau de neurones -# model.add(keras.layers.Conv2D(64, kernel_size=7, padding="same", input_shape=[28,28,1], activation="relu")) # Couche de convolution avec 64 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Conv2D(128, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 128 cartes -# model.add(keras.layers.Conv2D(128, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 128 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Conv2D(256, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 256 cartes -# model.add(keras.layers.Conv2D(256, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 256 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Flatten()) # Couche de mise à plat des données -# model.add(keras.layers.Dense(16, activation="relu")) # Couche dense : 16 nodes -# model.add(keras.layers.Dropout(0.5)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(8, activation="relu")) # Couche dense : 8 nodes -# model.add(keras.layers.Dropout(0.5)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(2, activation="softmax")) # Couche de sortie : 1 node par classe soit 2 - -# Version 3 -# model = keras.models.Sequential() # Modèle de reseau de neurones -# model.add(keras.layers.Conv2D(4, kernel_size=7, padding="same", input_shape=[28,28,1], activation="relu")) # Couche de convolution avec 4 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Conv2D(8, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 8 cartes -# model.add(keras.layers.Conv2D(8, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 8 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Conv2D(16, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 16 cartes -# model.add(keras.layers.Conv2D(16, kernel_size=3, padding="same", activation="relu")) # Couche de convolution avec 16 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Flatten()) # Couche de mise à plat des données -# model.add(keras.layers.Dense(16, activation="relu")) # Couche dense : 16 nodes -# model.add(keras.layers.Dropout(0.5)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(8, activation="relu")) # Couche dense : 8 nodes -# model.add(keras.layers.Dropout(0.5)) # Couche de régularisation par abandon -# model.add(keras.layers.Dense(2, activation="softmax")) # Couche de sortie : 1 node par classe soit 2 - -# Version 4 -# model = keras.models.Sequential() # Modèle de reseau de neurones -# model.add(keras.layers.Conv2D(16, kernel_size=28, padding="same", input_shape=[28,28,1], activation="relu")) # Couche de convolution avec 4 cartes -# model.add(keras.layers.Conv2D(16, kernel_size=28, padding="same", activation="relu")) # Couche de convolution avec 4 cartes -# model.add(keras.layers.MaxPool2D(2)) # Couche d'agrégation des cartes type Pooling max -# model.add(keras.layers.Flatten()) # Couche de mise à plat des données -# model.add(keras.layers.Dense(16, activation="relu")) # Couche dense : 16 nodes -# model.add(keras.layers.Dense(2, activation="softmax")) # Couche de sortie : 1 node par classe soit 2 - -# model=keras.models.load_model("04-cnn-cartes-v4.h5") # Lire le modèle + entrainement -# print ("Lecture du modèle entrainé : 04-cnn-cartes-v4.h5") - -# Version 5 -model = keras.models.Sequential() # Modèle de reseau de neurones -convo1 = keras.layers.Conv2D(16, kernel_size=3, padding="same", input_shape=[28,28,1], activation="relu") # Couche de convolution avec 16 cartes -model.add(convo1) -convo2 = keras.layers.Conv2D(16, kernel_size=3, padding="same", activation="relu") # Couche de convolution avec 16 cartes -model.add(convo2) -maxpool = keras.layers.MaxPool2D(2) # Couche d'agrégation des cartes type Pooling max -model.add(maxpool) -model.add(keras.layers.Flatten()) # Couche de mise à plat des données -model.add(keras.layers.Dense(16, activation="relu")) # Couche dense : 16 nodes -model.add(keras.layers.Dense(10, activation="softmax")) # Couche de sortie : 1 node par classe soit 10 - -optimiseur=keras.optimizers.SGD(learning_rate= eta) -model.compile(loss=perte, optimizer=optimiseur, metrics=["accuracy"]) # Compilation du modèle - -apts = model.fit(X_train, y_train, epochs=n, batch_size=lot, validation_data=(X_valid, y_valid)) # Entrainement -# model.save("04-cnn-cartes-v5.h5") -# model=keras.models.load_model("04-cnn-cartes-v5.h5") # Lire le modèle + entrainement -# print ("Lecture du modèle entrainé : 04-cnn-cartes-v5.h5") - -############################################################################### -# Phase d'inférence -############################################################################### - -print ("\n") -print ("Test sur le jeu de test ("+str(X_test.shape[0])+" images).") -X_new = X_test -y_new = np.argmax(model.predict(X_new), axis=-1) # Prédictions -y_new_target= y_test # Cibles -eval=model.evaluate(X_new, y_new_target) -print ("Il y a "+str(int(np.round((1-eval[1])*X_new.shape[0]))) + " images non reconnues.\n") - -############################################################################### -# Résultats -############################################################################### - -# Récupérer les poids de couche de convolution -def convo_poids(layer_name): - _poids = model.get_layer(name=layer_name).get_weights()[0] - _poids = np.squeeze(_poids) - # _poids = _poids.reshape((_poids.shape[0], _poids.shape[1], _poids.shape[2]*_poids.shape[3])) - return _poids - -# Couche de convolution 1 -X_convo = X[..., np.newaxis]/255.0 -subfigs[0].suptitle("Couche de convolution 1 : 3x3 - 16 cartes") -convo1_axs = subfigs[0].subplots(8, 8) -convo1_poids = convo_poids("conv2d") -convo1_img = convo1(X_convo[:10]) -i=0 -for ligne in range (2): # Filtres (poids) - for colonne in range (8): - convo1_axs[ligne][colonne].set_axis_off() - convo1_axs[ligne][colonne].imshow(convo1_poids[:,:,i], cmap="binary", interpolation="nearest") - convo1_axs[ligne][colonne].set_title("Filtre "+str(i), fontsize=10) - i +=1 -for ligne in range (2, 8): # Résultats - convo1_axs[ligne][0].set_axis_off() - convo1_axs[ligne][0].imshow(X[ligne-2], cmap="binary", interpolation="nearest") - convo1_axs[ligne][0].set_title("Image "+str(ligne-2), fontsize=10)g - for colonne in range (1, 8): - convo1_axs[ligne][colonne].set_axis_off() - convo1_axs[ligne][colonne].imshow(convo1_img[ligne-2, :,:,colonne-1], cmap="binary", interpolation="nearest") - convo1_axs[ligne][colonne].set_title("Filtre "+str(colonne-1), fontsize=10) - -# Couche de convolution 2 -subfigs[1].suptitle("Couche de convolution 2 : 3x3 - 16 cartes") -convo2_axs = subfigs[1].subplots(8, 8) -convo2_poids = convo_poids("conv2d_1") -convo2_img = convo2(convo1_img) -i=0 -for ligne in range (2): # Filtres (poids) - for colonne in range (8): - convo2_axs[ligne][colonne].set_axis_off() - convo2_axs[ligne][colonne].imshow(convo2_poids[:,:,0, i], cmap="binary", interpolation="nearest") - convo2_axs[ligne][colonne].set_title("Filtre 0-"+str(i), fontsize=8) - i +=1 -for ligne in range (2, 8): # Résultats - convo2_axs[ligne][0].set_axis_off() - convo2_axs[ligne][0].imshow(X[ligne-2], cmap="binary", interpolation="nearest") - convo2_axs[ligne][0].set_title("Image "+str(ligne-2), fontsize=10) - for colonne in range (1, 8): - convo2_axs[ligne][colonne].set_axis_off() - convo2_axs[ligne][colonne].imshow(convo2_img[ligne-2, :,:,colonne-1], cmap="binary", interpolation="nearest") - convo2_axs[ligne][colonne].set_title("Filtre "+str(colonne-1), fontsize=10) - -# Couche d'agrégation MaxPooling -subfigs[2].suptitle("Couche d'agrégation MaxPool : 2 -> sortie 14x14") -maxpool_axs = subfigs[2].subplots(8, 8) # 1 couches de 16 cartes -maxpool_img = maxpool(convo2_img) -for ligne in range (2): # Filtres -> rien - for colonne in range (8): - maxpool_axs[ligne][colonne].set_axis_off() -for ligne in range (2, 8): # Résultats - maxpool_axs[ligne][0].set_axis_off() - maxpool_axs[ligne][0].imshow(X[ligne-2], cmap="binary", interpolation="nearest") - maxpool_axs[ligne][0].set_title("Image "+str(ligne-2), fontsize=10) - for colonne in range (1, 8): - maxpool_axs[ligne][colonne].set_axis_off() - maxpool_axs[ligne][colonne].imshow(maxpool_img[ligne-2, :,:,colonne-1], cmap="binary", interpolation="nearest") - maxpool_axs[ligne][colonne].set_title("Filtre "+str(colonne-1), fontsize=10) - -plt.show() - -# Performances -print ("\n") -print ("Temps total : "+str(time.time()-t_debut)) diff --git a/03-vision/.#04-cnn-cartes.py b/03-vision/.#04-cnn-cartes.py deleted file mode 120000 index 2c08a0d..0000000 --- a/03-vision/.#04-cnn-cartes.py +++ /dev/null @@ -1 +0,0 @@ -phroy@debian.3622:1688640982 \ No newline at end of file diff --git a/03-vision/README.md b/03-vision/README.md index e7ac466..3864703 100644 --- a/03-vision/README.md +++ b/03-vision/README.md @@ -4,7 +4,7 @@ ![capture d'écran](img/01-digit-prepa_data.png) -### Reconnaissance de digits - Réseaux de neurones simples (RNA) +### Reconnaissance de digits - Réseaux de neurones simples (PMC) ![capture d'écran](img/02-digit-simple.png) diff --git a/04-renforcement/01-cartpole-gp.py b/04-renforcement/01-cartpole-gp.py new file mode 100644 index 0000000..85065bb --- /dev/null +++ b/04-renforcement/01-cartpole-gp.py @@ -0,0 +1,75 @@ +import os, time, random +import numpy as np +import matplotlib.pyplot as plt + +import tensorflow as tf +from tensorflow import keras + +############################################################################### +# 01-cartpole-gp.py +# @title: Apprentissage par renforcement - Apprentissage par gradient de politique (PG) +# @project: Mes scripts de ML +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2023 Philippe Roy +# @license: GNU GPL +############################################################################### + +### +# Commandes NumPy : +# - np.array : créer un tableau à partir d'une liste de listes +# - np.c_ : concatène les colonnes des tableaux +# - np.linspace : créer un tableau 1D de la valeur de début à la valeur de fin avec n valeurs +# - np.meshgrid : créer un tableau 2D avec l'ensemble des combinaisons allant des deux valeurs de début aux deux valeurs de fin +# - .reshape : reformater la tableau avec le nombre de lignes et le nombre de colonnes +### + +############################################################################### +# Initialisation +############################################################################### + +# Init du temps +t_debut = time.time() + +# Init des plots +fig = plt.figure(layout="constrained", figsize=(20, 7)) +fig.suptitle(" Vision par ordinateur - Reconnaissance de digit - Analyse et préparation des données") +img_ax = fig.subplots(10, 40) + +############################################################################### +# Observations +############################################################################### + +# Observations d'apprentissage, de validation et de test + +chiffre = keras.datasets.mnist # Jeu de données MNIST (digit) +# train_filter = np.unique(Y_train, return_index=True) +# X_train, Y_train = X_train[train_filter[1:]], Y_train[train_filter[1:]] +(X, y), (X_test, y_test) = chiffre.load_data() +X_train, y_train = X[5000:]/255.0 , y[5000:] +X_valid, y_valid = X[:5000]/255.0 , y[:5000] +classes = [0,1,2,3,4,5,6,7,8,9] + +############################################################################### +# Affichage des images avec l'étiquette +############################################################################### + +print ("\n") +print ("Recherche de 400 images sur le jeu de test (10 000 images).") +# X_new_unique = np.unique(X_test, axis=0, return_index=True) + +for ligne in range (10): # Ligne + i_first=-1 + for colonne in range (40): # Colonne + for i in range (i_first+1, X_test.shape[0]): + if y_test[i] == ligne: + # if y_test[i] == 2: + img_ax[ligne][colonne].imshow(X_test[i], cmap="binary", interpolation="nearest") + img_ax[ligne][colonne].set_axis_off() + img_ax[ligne][colonne].set_title(str(i), fontsize=10) + i_first=i + break + +print ("\n") + +plt.show() diff --git a/04-renforcement/README.md b/04-renforcement/README.md new file mode 100644 index 0000000..e7af817 --- /dev/null +++ b/04-renforcement/README.md @@ -0,0 +1,13 @@ +# Mes scripts de ML - Apprentissage par renforcement + +### Apprentissage par gradient de politique (PG) + +![capture d'écran](img/01-cartpole-gp.png) + +### Apprentissage par décision markoviens (MDP) + +![capture d'écran](img/02-cartpole-mdp.png) + +### Apprentissage par réseaux de neurones Q profond (DQN) + +![capture d'écran](img/03-cartpole-dqn.png)