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

2023-2024

parent 08ddc14a
Branches
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 notebook
%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)
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();
```
%% 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)
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=[10,6])
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();
# train loss plot
# (pas de possibilité simple d'obtenir le test loss)
plt.figure(figsize=[10,6])
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();
# 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))
```
......
%% Cell type:markdown id: tags:
# Introduction à l'apprentissage automatique: TP5 - Exercice 3
<br>
### Prédiction de la qualité de vins
Le dataset suivant:
https://www.openml.org/d/40691
fournit la description de 1599 vins rouges: 12 mesures physico-chimiques ainsi qu'un critère qualitatif donné comme une note entre 3 et 8 (plus haute est la note, meilleur est le vin).
Remarquez que les 12 caractéristiques doivent être normalisées.
La cellule suivante charge les données, construit des bases d'apprentissage et de test, et normalise les caractéristiques.
%% Cell type:code id: tags:
``` python
from sklearn import datasets, metrics, neural_network, svm, model_selection, preprocessing
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# chargement des données
X_wine, y_wine = datasets.fetch_openml('wine-quality-red', return_X_y=True, as_frame=False)
X_wine, y_wine = datasets.fetch_openml('wine-quality-red', return_X_y=True, as_frame=False, parser='auto')
n_samples = len(X_wine)
print("nombre total d'observations (apprentissage + test): %d" % n_samples)
n_features = len(X_wine[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_wine, y_wine, test_size=0.3, 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))
print("\n Cinq premières observations de X_train:")
print(X_train[:5,:])
print("\n et classes associées:")
print(y_train[:5])
# normalisation:
X_train_n = preprocessing.StandardScaler().fit_transform(X_train)
X_test_n = preprocessing.StandardScaler().fit(X_train).transform(X_test)
```
%% Cell type:markdown id: tags:
Deux remarques:
- Certaines caractéristiques semblent corrélées (on pourrait le vérifier en traçant des graphiques et en calculant des coefficients de corrélation comme dans le cours d'analyse de données): il serait sans doute pertinent de sélectionner des caractéristiques ou de réduire la dimension des observations.
- Nous allons envisager ce problème comme un problème de classification à 6 classes (les notes de 3 à 8). Néanmoins, il ne semblerait pas absurde de l'envisager comme un problème de régression.
<br>
Proposez des prédicteurs de la qualité en fonction des 12 mesures physico-chimiques. Vous explorerez les machines à vecteurs supports et les perceptrons multicouches, dont vous fixerez les hyperparamètres par _grid search_ et validation croisée.
<br>
Comparez vos résultats à ceux reportés ici:
https://www.openml.org/t/146217
(en vous demandant si les valeurs sont bien comparables)
%% Cell type:code id: tags:
``` python
# votre code ici:
```
%% Cell type:code id: tags:
``` python
```
......
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment