VI-ME-RÉ-BAR sur vos propres données!#

Instructions:

  • Ci-dessous, mettez ici une description de votre jeu de données: lequel avez vous choisi ?

  • Quel est le défi ? Intuitivement quels critères pourraient permettre de distinguer les deux classes d’images?

VOTRE RÉPONSE ICI

from intro_science_donnees import *
## les utilitaires
%load_ext autoreload
%autoreload 2
from utilities import *
# Graphs and visualization library
import seaborn as sns; sns.set()      
# Configuration intégration dans Jupyter
%matplotlib inline

Étape 1: prétraitement et [VI]sualisation#

Le jeu de données consiste en les images suivantes:

Instruction : Chargez votre jeu de données comme dans la feuille 3_jeux_de_donnees.md de la semaine dernière, en stockant les images dans la variables images et en les affichant.

# VOTRE CODE ICI
raise NotImplementedError()
assert isinstance(images, pd.Series)
assert len(images) == 20

Prétraitement#

Les données sont très souvent prétraitées c’est-à-dire résumées selon différentes caractéristiques : chaque élément du jeu de données est décrit par un ensemble d’attributs – propriétés ou caractéristiques mesurables de cet élément ; pour un animal, cela peut être sa taille, sa température corporelle, etc.

C’est également le cas dans notre jeu de données : une image est décrite par le couleur de chacun de ses pixels. Cependant les pixels sont trop nombreux pour nos besoins. Nous voulons comme la semaine dernière les remplacer par quelques attributs mesurant quelques propriétés essentielles de l’image, comme sa couleur ou sa forme moyenne: ce sont les données prétraitées.

La semaine dernière, les données prétraitées vous ont été fournies pour les pommes et les bananes. Cette semaine, grâce aux trois feuilles précédentes, vous avez les outils et connaissances nécessaires pour effectuer le prétraitement directement vous-même:

Pour commencer, la table ci-dessous contient les attributs redness et elongation – tels que vous les avez défini dans la feuille extraction d’attributs – appliqués à votre jeu de données :

df = pd.DataFrame({
        'redness':    images.apply(redness),
        'elongation': images.apply(elongation),
        'class':      images.index.map(lambda name: 1 if name[0] == 'a' else -1),
})
df

Exercice

  1. Implémentez dans utilities.py au moins deux nouveaux attributs adaptés à votre jeu de données. Si vous en avez besoin pour les tests par exemple, vous pouvez utiliser les cellules ci-dessous voire en créer de nouvelles.

    Astuce

    Indications

    Vous pouvez par exemple vous inspirer

    • des attributes existants comme redness;

    • des exemples donnés dans le cours: matched filter, analyse en composantes principales (PCA).

# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()

VOTRE RÉPONSE ICI

# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()

Vérifications:

  • la table d’origine est préservée:

assert len(df[df['class'] ==  1]) == 10
assert len(df[df['class'] == -1]) == 10
assert 'redness' in df.columns
assert 'elongation' in df.columns
  • Nouveaux attributs:

assert len(df.columns) > 3, "Ajoutez au moins un attribut!"
assert df.notna().all(axis=None), "Valeurs manquantes!"
for attribute in df.columns[3:]:
    assert pd.api.types.is_numeric_dtype(df[attribute]), \
        f"L'attribut {attribute} n'est pas numérique"
assert len(df.columns) > 4, "Gagnez un point en ajoutant un autre attribut"

Exercice

  1. Standardisez les colonnes à l’exception de la colonne class, afin de calculer les corrélations entre colonnes.

# VOTRE CODE ICI
raise NotImplementedError()
dfstd

Vérifions :

dfstd.describe()
assert dfstd.shape == df.shape
assert dfstd.index.equals(df.index)
assert dfstd.columns.equals(df.columns)
assert (abs(dfstd.mean()) < 0.01).all()
assert (abs(dfstd.std() - 1) < 0.1).all()

Le prétraitement est terminé!

Visualisation#

Exercice

  1. Extrayez quelques statistiques de base du tableau de données:

# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()

Observations#

Exercice

Décrivez ici vos observations: corrélations apparentes ou pas, interprétation de ces corrélations à partir du nuage de points, etc. Est-ce que les attributs choisis semblent suffisants? Quel attribut semble le plus discriminant? Est-ce qu’un seul d’entre eux suffirait?

VOTRE RÉPONSE ICI

Étape 2: [ME]sure de performance ([ME]tric)#

Partition (split) du jeu de données en ensemble d’entraînement et ensemble de test#

Exercice

  1. Extrayez, depuis dfstd, les deux attributs choisis dans X et la vérité terrain dans Y:

# VOTRE CODE ICI
raise NotImplementedError()

Vérifions:

assert isinstance(X, pd.DataFrame), "X n'est pas une table Pandas"
assert X.shape == (20,2), "X n'est pas de la bonne taille"
assert set(X.columns) != {'redness', 'elongation'}
assert 'redness' not in X.columns and 'elongation' not in X.columns, \
   "Pour un point de plus: ne réutilisez ni la rougeur, ni l'élongation"
# VOTRE CODE ICI
raise NotImplementedError()
assert train_index.shape == test_index.shape
assert list(sorted(np.concatenate([train_index, test_index]))) == list(range(20))

assert Xtest.shape == Xtrain.shape
assert pd.concat([Xtest, Xtrain]).sort_index().equals(X.sort_index())

assert Ytest.shape == Ytrain.shape
assert pd.concat([Ytest, Ytrain]).sort_index().equals(Y.sort_index())
assert Ytest.value_counts().sort_index().equals(Ytrain.value_counts().sort_index())
# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()

Taux d’erreur#

Pour mesurer les performances de la classification, nous utiliserons comme la semaine dernière le taux d’erreur comme métrique, d’une part sur l’ensemble d’entraînement, d’autre part sur l’ensemble de test.

Exercice

Implémentez la fonction error_rate dans utilities.py. Pour vérifier que c’est correctement fait, nous affichons son code ci-dessous:

show_source(error_rate)

Étape 3: [RE]férence (base line)#

Classificateur#

Consignes

  • En Semaine 4: faites la suite de cette feuille avec l’algorithme du plus proche voisin, comme en Semaine 3.

  • En Semaine 5: faites d’abord la feuille sur les classificateurs puis faites la suite de cette feuille avec votre propre classificateur, en notant au préalable votre choix de classificateur ici:

Exercice

Quel classificateur avez-vous choisit en semaine 5 ? Pourquoi avez-vous choisis celui-ci ?

VOTRE RÉPONSE ICI

Exercice

  1. Ci-dessous, définissez puis entraînez votre classificateur sur l’ensemble d’entraînement.

    Indication

    Si vous avez besoin de code supplémentaire pour cela, mettez-le dans utilities.py.

# VOTRE CODE ICI
raise NotImplementedError()
# VOTRE CODE ICI
raise NotImplementedError()
print("Training error:", e_tr)
print("Test error:", e_te)
assert Ytrain_predicted.shape == Ytrain.shape
assert Ytest_predicted.shape == Ytest.shape
assert 0 <= e_tr and e_tr <= 1
assert 0 <= e_te and e_te <= 1

Visualisons les prédictions obtenues:

# The training examples are shown as white circles and the test examples are black squares.
# The predictions made are shown as letters in the black squares.
make_scatter_plot(X, images.apply(transparent_background_filter),
                  train_index, test_index, 
                  predicted_labels=Ytest_predicted, axis='square')

Interprétation#

Exercice

Quelle est la performance des prédictions pour le jeu d’entraînement et pour le jeu de test ? Celle-ci vous parait-elle optimate ? Donnez enfin une interprétation des résultats, en expliquant pourquoi votre performance est bonne ou pas. Avez vous une première intuition de comment l’améliorer ?

VOTRE RÉPONSE ICI

Étape 4: [BAR]res d’erreur (error bar)#

Barre d’erreur 1-sigma#

Exercice

Comme première estimation de la barre d’erreur, calculez la barre d’erreur 1-sigma pour le taux d’erreur e_te:

# VOTRE CODE ICI
raise NotImplementedError()
print("TEST SET ERROR RATE: {0:.2f}".format(e_te))
print("TEST SET STANDARD ERROR: {0:.2f}".format(sigma))
assert n_te + 5 == 3**2 + len(Ytest) - 2**2
assert round(sigma**2,3) == round((e_te/n_te - e_te**2/n_te),3)

Barre d’erreur par validation croisée (Cross-Validation)#

TODO L’an pro: REFORMULER et faire des questions

Nous calculons maintenant une autre estimation de la barre d’erreur en répétant l’évaluation de performance pour de multiples partitions entre ensemble d’entraînement et ensemble de test :

n_te = 10
SSS = StratifiedShuffleSplit(n_splits=n_te, test_size=0.5, random_state=5)
E = np.zeros([n_te, 1])
k = 0
for train_index, test_index in SSS.split(X, Y):
    print("TRAIN:", train_index, "TEST:", test_index)
    Xtrain, Xtest = X.iloc[train_index], X.iloc[test_index]
    Ytrain, Ytest = Y.iloc[train_index], Y.iloc[test_index]
    neigh.fit(Xtrain, Ytrain.ravel()) 
    Ytrain_predicted = neigh.predict(Xtrain)
    Ytest_predicted = neigh.predict(Xtest)
    e_tr = error_rate(Ytrain, Ytrain_predicted)
    e_te = error_rate(Ytest, Ytest_predicted)
    print("TRAIN ERROR RATE:", e_tr)
    print("TEST ERROR RATE:", e_te)
    E[k] = e_te
    k = k+1
    
e_te_ave = np.mean(E)
# It is bad practice to show too many decimal digits:
print("\n\nCV ERROR RATE: {0:.2f}".format(e_te_ave))
print("CV STANDARD DEVIATION: {0:.2f}".format(np.std(E)))

sigma = np.sqrt(e_te_ave * (1-e_te_ave) / n_te)
print("TEST SET STANDARD ERROR (for comparison): {0:.2f}".format(sigma))

Conclusion#

Exercice

Faites ci-dessous une synthèse des performances obtenues, tout d’abord avec votre référence (baseline), puis avec les variantes que vous aurez explorées en changeant d’attributs et de classificateur. Vous pouvez par exemple présenter votre réponse sous forme d’un tableau. Puis vous commenterez sur la difficulté du problème ainsi que les pistes possibles pour obtenir de meilleures performances ou pour généraliser le problème.

VOTRE RÉPONSE ICI

Exercice

Complétez votre rapport.