Introduction à la BDD MNIST
La base MNIST contient des chiffres manuscrits utilisés pour tester des algorithmes de classification d'images. Chaque image de la base MNIST est représentée par une matrice de dimension 8 x 8
Chaque élément de cette matrice correspond à un pixel de l'image, dont :
L'objectif principal est de reconnaître le chiffre à partir de cette image
Outils utilisés :
- python
- Descente de gradient (batch et stochastique) pour estimer les paramètres
- Keras pour la régression multinomiale
- Un réseau de neurones convolutionnel basé sur LeNet-5
1. MNIST DATA
Importation des librairies
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random, time
from keras.datasets import mnist
La BDD se télécharge via Keras comme
(X0, Y0), (X1, Y1) = mnist.load_data()
La BDD MNIST contient 60 000 images d'apprentissage et 10 000 de test.
X0
et Y0
représentent les images d'apprentissage et de test sous forme de numpy.ndarray
de taille (60000, 28, 28)
et (10000, 28, 28)
.
On prépare la DATA comme
# Conversion en float
X0 = X0.astype('float32')
X1 = X1.astype('float32')
# Image -> Vecteur
X0 = X0.reshape(60000, 784)
X1 = X1.reshape(10000, 784)
# Mise à l'échelle
X0 = X0 / 255.0
X1 = X1 / 255.0
On affiche une image comme
# indice = 3
n = np.where(Y0 == 3)[0][0]
# Affichage de l'image
plt.imshow(X0[n, :].reshape(28, 28), cmap="gray")
2. Régression multinomiale
La régression multinomiale attribue une classe à un individu via une variable aléatoire ( Y ) avec des étiquettes de classe. Pour chaque individu, on utilise un vecteur de régression ( x ), et la probabilité d'appartenance à une classe ( k ) est donnée par :
3. Descente de gradient
La descente de gradient minimise en mettant à jour :
Où est le pas fixe et est le gradient de .
Le gradient de l'entropie croisée est :
4. Application de la descente de gradient sur la dataset MNIST
Fonction implémentant la descente de gradient pour la régression multinomiale
def RegMultinomialGradDesc(X_train, Y_train, X_test, Y_test, Y_train_list, Y_test_list, epochs, alpha):
"""
Descente de gradient pour la régression multinomiale
Params
----------
X_train, Y_train : données d'entraînement
X_test, Y_test : données de test
epochs : nombre d'itérations
alpha : taux d'apprentissage
Return
--------
Theta : paramètres optimisés
Learning_T : temps d'exécution par époque
Lvals_train, Lvals_test : entropie croisée sur les données d'entraînement et de test
scores_train, scores_test : précision sur les données d'entraînement et de test
"""
# Initialisation
N, p = X_train.shape
X_train = np.c_[np.ones(N), X_train] # Ajout de biais (colonne de 1)
X_test = np.c_[np.ones(X_test.shape[0]), X_test] # Ajout de biais
K = Y_train.shape[1]
Theta = np.zeros((p + 1, K)) # Initialisation des paramètres
# Listes pour enregistrer les métriques
Learning_T, Lvals_train, Lvals_test = [], [], []
scores_train, scores_test = [], []
for epoch in range(epochs):
start_time = time.time()
# Calcul de l'entropie croisée et des prédictions
L_train = eval_L(X_train, Y_train, Theta)
L_test = eval_L(X_test, Y_test, Theta)
Lvals_train.append(L_train)
Lvals_test.append(L_test)
# Affichage des résultats
print(f"Epoch {epoch}: Train cost: {L_train}, Test cost: {L_test}")
# Mise à jour des paramètres
Theta -= (alpha / N) * Gradient(X_train, Y_train, Theta)
# Calcul des précisions
pred_train = prediction_Label(X_train[:, 1:], Theta)
pred_test = prediction_Label(X_test[:, 1:], Theta)
scores_train.append(np.mean(pred_train == Y_train_list))
scores_test.append(np.mean(pred_test == Y_test_list))
# Temps d'exécution
Learning_T.append(time.time() - start_time)
return Theta, Learning_T, Lvals_train, Lvals_test, scores_train, scores_test
Appliquons l'algo de descente de gradient comme
# Params
alpha = 0.01
epochs = 100
# DATA d'entraînement et de test
X_train = X0[:50000]
Y_train = Y0_[:50000]
X_test = X1
Y_test = Y1_
# Conversion en listes pour précision
Y_train_list = Y0[:50000]
Y_test_list = Y1
# Application de la descente de gradient
Theta, Learning_T, Lvals_train, Lvals_test, scores_train, scores_test = RegMultinomialGradDesc(
X_train, Y_train, X_test, Y_test, Y_train_list, Y_test_list, epochs, alpha
)
Résultat
5. Régression multinomiale en keras
Nous mettons en œuvre la régression multinomiale en Keras pour classifier les chiffres du dataset MNIST
# Importation des librairies
import numpy as np
import pandas as pd
import tensorflow as tf
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import to_categorical
# Chargement des données MNIST
(X_train_full, Y_train_full), (X_test, Y_test) = mnist.load_data()
# Reshape et normalisation des images
X_train_full = X_train_full.reshape(-1, 784) / 255.0
X_test = X_test.reshape(-1, 784) / 255.0
# Transformation des labels en format one-hot
Y_train_full_one_hot = to_categorical(Y_train_full)
Y_test_one_hot = to_categorical(Y_test)
# Séparation en sous-ensembles d'entraînement, validation et test
X_train = X_train_full[:50000]
Y_train = Y_train_full_one_hot[:50000]
X_valid = X_train_full[50000:60000]
Y_valid = Y_train_full_one_hot[50000:60000]
D'où le modèle de régression multinomiale sous keras
# Dimensions du modèle
input_dim = X_train.shape[1] # 784 variables
output_dim = Y_train.shape[1] # 10 classes
# Définition du modèle de régression multinomiale
def create_model():
model = tf.keras.Sequential([
tf.keras.layers.Dense(output_dim, input_dim=input_dim, activation='softmax')
])
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
return model
Entrainement
# Entrainement du modèle
keras_model = classification_model()
keras_model.fit(X_train, Y_train, epochs=300, verbose=0)
Précision
# Calcul du degré de précision ou accuracy sur X_valid
classes = np.argmax(keras_model.predict(X_valid), axis = 1)
N_valid = X_valid.shape[0]
numClassCorrect = 0
for i in range(N_valid):
if classes[i]==Y_valid[i]:
numClassCorrect+=1
accuracy = numClassCorrect/N_valid
print('Accuracy sur X_valid : ' + str(accuracy))
Résultat de Précision : (93%)
Accuracy sur X_valid : 0.9348
Entraînement d'un nouveau modèle pour comparaison.
On teste avec un exemple diffèrent si on apprend le modèle sur un ensemble train réduit. Prenons N_train = 1000 par exemple.
X_train = X0[:1000]
Y_train = Y0_[:1000]
X_valid = X0[:400]
Y_valid = Y0[:400]
Entrainement
# Entrainement du modèle
keras_model = classification_model()
keras_model.fit(X_train, Y_train, epochs=300, verbose=0)
Précision
# Calcul du degré de précision ou accuracy sur X_test
N_test = X_test.shape[0]
numClassCorrect = 0
for i in range(N_test):
if classes[i]==Y_test[i]:
numClassCorrect+=1
accuracy = numClassCorrect/N_test
print('Accuracy sur X_test : ' + str(accuracy))
Résultat de Précision : (86%)
Accuracy sur X_test : 0.8662
6. Conclusion
Le modèle a montré une performance parfaite sur les données de validation (100%) avant même la 5ème itération, et une amélioration de 0.6% sur les données de test par rapport au précédent. En comparant l'apprentissage sur un réseau dense et convolutionnel, ce dernier a montré une légère amélioration (+0.6%) malgré la réduction des données, contrairement au réseau dense où la performance avait chuté de 5%. Le modèle convolutionnel est donc plus efficace en termes de données et de temps d'entraînement, ce qui en fait un choix optimal lorsque les ressources sont limitées.
Top comments (0)