Skip to content
Snippets Groups Projects
Commit 32dbbdb6 authored by SUR Frederic's avatar SUR Frederic
Browse files

2024-2025

parent c277ae46
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# Introduction à l'apprentissage automatique: TP5 - Exercice 2
<br>
### Reconnaissance d'images par réseaux de neurones
<br>
On reprend la base de données Fashion-MNIST du TP4. Rappelons que l'on se restreint à un sous-ensemble de 10000 observations pour garder des temps de calcul raisonnables pendant la séance. Néanmoins, il serait plus satisfaisant d'utiliser l'ensemble de la base de données à notre disposition (à faire si vous avez une machine performante et du temps).
%% Cell type:code id: tags:
``` python
import numpy as np
import matplotlib.pyplot as plt
import time
from sklearn import datasets, metrics, neural_network, model_selection
%matplotlib inline
# Fashion-Mnist database sur openML: (il faut quelques dizaines de secondes pour charger la base)
size_images=(28,28)
X_fashion, y_fashion = datasets.fetch_openml(data_id=40996, return_X_y=True, as_frame=False, parser='auto')
X_fashion=X_fashion[:10000,:]/255. # normalisation des niveaux de gris entre 0 et 1
y_fashion=y_fashion[:10000]
for i in range(10):
n=np.sum(y_fashion==str(i))
print("nombre d'observations dans la classe %d: %d" %(i,n))
n_samples = len(X_fashion)
print("nombre total d'observations (apprentissage + test): %d" % n_samples)
n_features = len(X_fashion[0])
print("nombre de caractéristiques par observation: %d" % n_features)
X_train, X_test, y_train, y_test = model_selection.train_test_split(X_fashion, y_fashion, test_size=0.2, random_state=1)
print("nombre d'observations dans la base d'apprentissage: %d" %len(X_train))
print("nombre d'observations dans la base de test: %d" %len(X_test))
```
%% Cell type:markdown id: tags:
__Remarque__: ici, les données d'apprentissage sont les vecteurs des niveaux de gris pixel à pixel. On divise par 255 le niveau de gris (codé sur 8 bits, donc entre 0 et 255) de manière à normaliser les données entre 0 et 1. Comme on l'a déjà dit, cette manipulation améliore le comportement des algorithmes d'optimisation numérique.
%% Cell type:markdown id: tags:
La cellule suivante définit la fonction qui permet d'afficher les 150 premières images de la base de test, ainsi que la classe véritable et la classe déterminée par l'algorithme de classification:
%% Cell type:code id: tags:
``` python
def affichage_150_images(X_test,y_test,y_pred):
plt.figure(figsize=[10,12])
for n in range(150):
plt.subplot(10,15,n+1,xticks=[],yticks=[])
plt.imshow(np.reshape(X_test[n,:],size_images),cmap='gray_r')
if y_pred[n]==y_test[n]:
plt.text(0.1,0.1,str(y_pred[n])+' / '+str(y_test[n]),fontsize=6,bbox=dict(facecolor='white', alpha=1))
else:
plt.text(0.1,0.1,str(y_pred[n])+' / '+str(y_test[n]),fontsize=6,bbox=dict(facecolor='red', alpha=1))
plt.suptitle('classe predite / classe réelle')
plt.show();
plt.show()
```
%% Cell type:markdown id: tags:
L'entraînement d'un réseau de neurones _feedforward_ (perceptron multicouche) peut se faire de la manière suivante:
%% Cell type:code id: tags:
``` python
MLP = neural_network.MLPClassifier(hidden_layer_sizes=(10,), max_iter=20, alpha=0,
solver='sgd', verbose=True, learning_rate_init=.1, random_state=1)
MLP.fit(X_train, y_train)
print("Score sur l'ensemble d'apprentissage: %.3f" % MLP.score(X_train, y_train))
print("Score sur l'ensemble de test: %.3f" % MLP.score(X_test, y_test))
```
%% Cell type:markdown id: tags:
Chaque itération correspond à un parcours de la base d'apprentissage (une _epoch_ ): ce n'est pas une itération de l'algorithme de descente. On voit que le _loss_ décroît au fur et à mesure des itérations, ce qui est logique. Cependant, une faible augmentation du loss pourrait être observée d'une itération à l'autre car on utilise l'algorithme du gradient stochastique.
Consultez la documentation __[ici](https://scikit-learn.org/stable/modules/neural_networks_supervised.html)__ et __[](https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html)__ et faites le lien avec le cours. En particulier, notez que dans la cellule précédente: on a déclaré un réseau à une seule couche cachée de 10 neurones (`hidden_layer_sizes=(10,)`), on n'a pas de régularisation $L^2$ des poids (car `alpha=0`), et on a précisé le solveur _Stochastic Gradient Descent_ pour lequel on a fixé le taux d'apprentissage ( `learning_rate=.1` ). Notez qu'il existe d'autres solveurs (on ne pourra pas rentrer dans les détails dans ce cours), et notez également dans la documentation comment est fixée la taille du lot ( _batch_ ).
Comme on l'a vu en cours, le loss (entropie croisée après la couche SoftMax) n'est pas le taux de classifications correctes. Le petit script suivant permet de suivre l'évolution du taux de classification sur la base d'apprentissage et sur la base de test au cours des itérations (ignorez l'avertissement). Notez les valeurs des paramètres.
%% Cell type:code id: tags:
``` python
niter=150
score_train=[]
score_test=[]
loss_train=[]
MLP = neural_network.MLPClassifier(hidden_layer_sizes=(10,), alpha=0, activation="relu",
max_iter=1, warm_start=True,
solver='sgd', learning_rate_init=.01, random_state=1)
t0=time.time()
for k in range(1,niter):
print("\r %d / %d" %(k,niter),end="")
MLP.fit(X_train,y_train)
loss_train.append(MLP.loss_)
score_train.append(MLP.score(X_train,y_train))
score_test.append(MLP.score(X_test,y_test))
t1=time.time()
print("\ntemps par epoch: %.3f s" %((t1-t0)/niter))
# train & test score plot
plt.figure(figsize=[8,6])
X=np.array(range(1,niter))
plt.plot(X,score_train,X,score_test)
plt.legend(['train','test'])
plt.title('score de classification')
plt.ylim(bottom=0.7,top=1.)
plt.grid()
plt.show();
plt.show()
# train loss plot
# (pas de possibilité simple d'obtenir le test loss)
plt.figure(figsize=[8,6])
X=np.array(range(1,niter))
plt.plot(X,loss_train)
plt.legend(['train loss'])
plt.title('valeur du loss')
plt.ylim(bottom=0.,top=0.8)
plt.grid()
plt.show();
plt.show()
# scores finaux:
print('MLP train score: %.3f' %MLP.score(X_train,y_train))
print('MLP test score: %.3f' %MLP.score(X_test,y_test))
```
%% Cell type:markdown id: tags:
__Questions__:
- Pourquoi, avec ce jeu de paramètres, devrait-on se limiter à une soixantaine d'itérations?
- Observez les problèmes de convergence si `learning_rate` est trop grand (essayez $0.05$) ou trop petit (essayez $0.001$). Revenez à $0.01$.
- Essayez différentes combinaison de l'architecture (une couche cachée avec 10 neurones, 50 neurones, 100 neurones, puis deux couches cachées avec le même nombre de neurones), et du paramètre `alpha` (0 pour ne pas régulariser, 1e-4 par défaut, 1e-2, 1e-1, 1), ou de l'activation (`relu` ou `logistic`). Quel est le réseau le plus performant ? Soyez attentif aux situations de surapprentissage.
Trois principes peuvent vous guider:
- en situation de surapprentissage (grande différence entre scores d'apprentissage et de test qui finit par décroître), régularisez davantage
- si la régularisation ne fait que diminuer le score d'apprentissage mais n'augmente pas le score de test, c'est que votre réseau est trop compliqué: dans ce cas simplifiez-le
- si le score de test croît à peu près continûment, augmentez le nombre d'itérations car vous n'avez pas encore atteint l'optimum.
Fixer l'architecture et les hyperparamètres d'un réseau de neurones est assez rébarbatif... Il faut s'aider de l'expérience et de guides de "bonnes pratiques". Ne consacrez pas trop de temps à cet exercice!
_Indication_ : on n'arrive pas obtenir un score franchement supérieur à 0.85. Si vous arrivez à faire mieux, signalez-le nous! Comparez au meilleur classifieur du TP4.
%% Cell type:markdown id: tags:
<font color=red>
Réponses:
</font>
%% Cell type:markdown id: tags:
La cellule suivante permet l'affichage des résultats de la manière habituelle.
%% Cell type:code id: tags:
``` python
%time y_pred_MLP = MLP.predict(X_test)
print('MLP score: %f' % metrics.accuracy_score(y_test, y_pred_MLP))
affichage_150_images(X_test*255,y_test,y_pred_MLP)
print(metrics.classification_report(y_test,y_pred_MLP))
print(metrics.confusion_matrix(y_test,y_pred_MLP))
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment