7.1. TP reconnaissance de chiffres avec scikit-learn#

Marc Buffat, Dpt Mécanique, UCB Lyon 1

from Python Machine Learning Tutorial

handwritten digits

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
# police des titres
plt.rc('font', family='serif', size='18')
from IPython.display import display,Markdown
import sklearn as sk

from validation.validation import info_etudiant
def printmd(string):
    display(Markdown(string))
# test si numero étudiant spécifier
try: NUMERO_ETUDIANT
except NameError: NUMERO_ETUDIANT = None 
if type(NUMERO_ETUDIANT) is not int :
    printmd("**ERREUR:** numéro d'étudiant non spécifié!!!")
    NOM,PRENOM,NUMERO_ETUDIANT=info_etudiant()
    #raise AssertionError("NUMERO_ETUDIANT non défini")
# parametres spécifiques
_uid_    = NUMERO_ETUDIANT
np.random.seed(_uid_)
printmd("**Login étudiant {} {} uid={}**".format(NOM,PRENOM,_uid_))

7.1.1. Principe reconnaissance d’images par IA#

digits database IA

7.1.2. Base de données de chiffres manuscrits#

Une version basse résolution de cette base de données est fourni avec scikit-learn.

On commence par charger l’échantillon :

from sklearn import datasets
digits = datasets.load_digits()
# information sur la base de données : dataset
display(Markdown(digits.DESCR))

7.1.2.1. Base de données#

Résultat sous forme de dictionnaire généralisé: Bunch (accès avec des clés aux données)

  • exploration de la base de données

    • data (feature) : images de chiffres manuscrits

    • résultats (target) : valeur numérique 0,1,2,..9

les images de l’échantillon sont des images de 8x8 pixels, en noir et blanc avec 16 niveaux de gris (de 0 à 15) (i.e. codé sur 4 bits).

print(type(digits))
print("clés:",digits.keys())

Afficher dans la cellule suivante la valeur de la première donnée (data) et du premier résultat (target).

print("Données:",digits.data.shape)
print("Résultats:",digits.target.shape)
### BEGIN SOLUTION
### END SOLUTION

7.1.2.2. Affichage des images#

  • affichage d’une image avec imshow

  • affichage d’une série de nmax images avec la fonction plot_data

plt.imshow(digits.images[0],cmap='binary')
plt.title(digits.target[0])
plt.axis('off')
plt.show()
def plot_data(data,target,pred=None,nmax=64,titre=None):
    '''affiche les 64 premiers elts de la BD'''
    # set up the figure
    fig = plt.figure(figsize=(12, 12))  # figure size 
    if titre is not None: plt.title(titre)
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)
    # plot the digits: each image is 8x8 pixels
    for i in range(nmax):
        ax = fig.add_subplot(8, 8, i + 1, xticks=[], yticks=[])
        image = data[i].reshape(8,8)
        ax.imshow(image, cmap=plt.cm.binary, interpolation='nearest')    
        # label the image with the target value
        ax.text(0, 7, str(target[i]),color='b')
        # and the predicted value
        if pred is not None: ax.text(7,7, str(pred[i]),color='r')
plot_data(digits.data,digits.target,titre="data set initial")

7.1.3. Création des datasets pour l’apprentissage#

  • data set d’apprentissage (learn)

  • data set de validation (test)

décomposition des données: 80% training et 20% test avec un choix aléatoire (fct numéro étudiant)

from sklearn.model_selection import train_test_split

res = train_test_split(digits.data, digits.target, 
                       train_size=0.8,
                       test_size=0.2,
                       random_state=NUMERO_ETUDIANT)
train_data, test_data, train_labels, test_labels = res 
print("dataset training:",train_data.shape)
print("dataset test    :",test_data.shape)
plot_data(train_data, train_labels,titre="data set d'entrainement")
plot_data(test_data, test_labels,titre="data set de test")

7.1.3.1. définition des données#

définir les données normalisées (tableaux numpy)

  • X_train, y_train

  • X_test, y_test

  • attention à l’aliasing (utilisation de copy)

# normalisation des donnees
X_train = None
y_train = None
X_test  = None
y_test  = None
### BEGIN SOLUTION
### END SOLUTION
assert (X_train.shape == train_data.shape)
assert (y_train.shape == train_labels.shape)
assert (X_test.shape == test_data.shape)
assert (y_test.shape == test_labels.shape)

7.1.4. Modèle linéaire de regréssion logistique#

Création d’un modèle linéaire

 scikit learn  linear_model
  • modèle: LogisticRegression

La régression logistique, malgré son nom, est un modèle linéaire de classification plutôt que de régression. La régression logistique est également connue dans la littérature sous le nom de « logit régression », de « classification à entropie maximale » (MaxEnt) ou de « classificateur log-linéaire ». Dans ce modèle, les probabilités décrivant les résultats possibles d’un seul essai sont modélisées à l’aide d’une fonction logistique.

La régression logistique est implémentée dans LogisticRegression. Cette implémentation peut s’adapter à une régression logistique binaire, One-vs-Rest ou multinomiale avec régularisation facultative (l1, l2, elasticnet, aucune)

7.1.4.1. Régression logistique#

La régression logistique est une méthode statistique de prédiction des classes binaires. Le résultat ou la variable cible est de nature dichotomique. Dichotomique signifie qu’il n’y a que deux classes possibles. Il calcule la probabilité d’occurrence d’un événement.

Il s’agit d’un cas particulier de régression linéaire où la variable cible est de nature catégorielle. Il utilise un journal des cotes comme variable dépendante. La régression logistique prédit la probabilité d’occurrence d’un événement binaire à l’aide d’une fonction logit.

Equation linéaire de régression

\[ z = \beta_0 + \beta_1 X_1 + ... + \beta_n X_n \]

Fonction sigmoide $\( p = \frac{1}{1+e^{-z}} \)$

probalité y=1 $\( p = \frac{1}{1+e^{-(\beta_0 + \beta_1 X_1 + ... + \beta_n X_n)}}\)$

Y = np.linspace(-10,10,100)
plt.title("probabilité Y=1 (sigmoide)")
plt.plot(Y,1./(1+np.exp(-Y)))
Y1 = np.linspace(-10,-3,10)
plt.plot(Y1,np.zeros(10),'or')
plt.plot(-Y1,np.ones(10),'or')
plt.xlabel('z(X)');

Remarque La régularisation est appliquée par défaut, ce qui est courant dans le machine learning mais pas dans les statistiques. Un autre avantage de la régularisation est qu’elle améliore la stabilité numérique.

à faire: modifier les paramètres en utilisant la documentation

paramétres

  • max_iter (de 100 à 200)

  • normalisation des données

  • régularisation

Dans les 2 cellules suivantes faire

  1. l’apprentissage du modèle avec son score

  2. le test du modèle et l’analyse de la qualité de la prédiction (critère accuracy_score, r2_score)

  • on calulera y_pred et accuracy (taux de prediction)

import sklearn.linear_model

model=None
### BEGIN SOLUTION
### END SOLUTION
assert(model.score(X_train,y_train))
print("score=",model.score(X_train,y_train))

from sklearn.metrics import accuracy_score,r2_score

y_pred = None
accuracy = None
### BEGIN SOLUTION
### END SOLUTION
assert(len(y_test) == len(y_pred))
assert(accuracy is not None)

7.1.4.2. Bonus#

  • visualiser les échantillons où le modèle s’est trompé de beaucoup

  • conclusion

# test erreur
## BEGIN SOLUTION
## END SOLUTION

7.1.5. Optionnel (test avec modèle random forest, SVM)#

7.1.5.1. Test du modèle Random Forest#

A faire: modifier les paramètres de RandomForestClassifier pour améliorer le score.

Il est au moins possible d’arriver à 97% en changeant juste les valeurs de n_estimators et max_features. La documentation est disponible à cette adresse :

Dans les 2 cellules suivantes faire

  1. l’apprentissage du modèle avec son score

  2. le test du modèle et l’analyse de la qualité de la prédiction (critère accuracy_score, r2_score)

  • on calulera y_pred et accuracy (taux de prediction)

from sklearn.ensemble import RandomForestClassifier

model=None
### BEGIN SOLUTION
### END SOLUTION
assert(model.score(X_train,y_train))
print("score=",model.score(X_train,y_train))

y_pred = None
accuracy = None
### BEGIN SOLUTION
### END SOLUTION
assert(len(y_test) == len(y_pred))
assert(accuracy is not None)

7.1.5.2. Test modèle: machines à vecteurs de support SVM#

A faire: modifier les paramètres de svm.SVC pour améliorer le score. Il est au moins possible d’arriver à 95%.

La documentation est disponible à cette adresse :

Dans les 2 cellules suivantes faire

  1. l’apprentissage du modèle avec son score

  2. le test du modèle et l’analyse de la qualité de la prédiction (critère accuracy_score, r2_score)

  • on calulera y_pred et accuracy (taux de prediction)

from sklearn import svm

model=None
### BEGIN SOLUTION
### END SOLUTION
assert(model.score(X_train,y_train))
print("score=",model.score(X_train,y_train))

y_pred == None
accuracy = None
### BEGIN SOLUTION
### END SOLUTION
assert(len(y_test) == len(y_pred))
assert(accuracy is not None)

7.1.5.3. Analyse et conclusion#

écrire votre analyse et conclusion en markdown dans la cellule suivante:

7.1.6. FIN du TP#