Académique Documents
Professionnel Documents
Culture Documents
Coco le Perroquet
dmarche de rsolution dun problme dans ce domaine via deux
branches principales : Cration du
a L'apprentissage supervise, dataset en lien
a L'apprentissage non-supervise. avec limage
Sachant le rsultat dun phnomne, lapprentissage supervis permet de Pour rduire le nombre
comprendre son mcanisme afin dtre capable de bien prdire les rsul- de couleurs, regroupons
tats venir et de prendre des dcisions pertinentes. celles qui se ressem-
Par phnomne, on peut envisager plusieurs choses, par exemple si le fait blent dans les 238135
quun e-mail soit un spam ou non, le prix du mtre carr dans une ville don- prsentes. Pour ce faire,
Fig.1
ne, lidentification dun code postal, la probabilit quun client achte tel il nous faut donc
ou tel produit, etc. construire un dataset
Derrire cette ide, on identifie une variable Y (prix, label spam/non-spam, qui va reprsenter la couleur de chaque pixel. En utilisant la codification
etc.) reprsentant le rsultat que lon cherche prdire et que lon appelle RGB, il nous faut donc trois colonnes dans notre dataset et autant de
la cible. On dispose aussi dun ensemble de variables dites features, qui lignes quil y a de pixel, soit 1024*768 = 786432 lignes. Ce dataset se
permet de capter et dcrire le phnomne tudi. construit rapidement partir de limage charge en appelant la fonction
Lapprentissage non-supervis, quant lui, ne suppose pas la connaissan- getdata() :
coordonnes, comme reprsentes dans limage ci-dessous : Fig.2. def recreate_image(cluster_centers, labels, width, height):
Limage (a) montre les donnes de dpart qui sont visiblement sparables # Dimension of a center (3 in our case)
en deux groupes distincts. Deux centrodes vont alors tre initialiss de d = cluster_centers.shape[1]
faon alatoire (figure (b)). Les points sont alors affects son centrode le # Initialization of the compressed image
plus proche, formant des clusters (figure (c)). Les centrodes se replacent image_comp = np.zeros((height, width, d))
en calculant la distance moyenne de tous les points qui lui sont affects # Initialization of a counter on the pixels indexes
(figure (d)). Au fil des mises jour, certains points seront certainement plus label_idx = 0
proches dautres centrodes, ce qui modifiera leur appartenance aux clus- # Reconstruction of the image, pixel by pixel
ters (figure (e)).. Le processus de mise jour des centrodes et daffecta- for i in range(height):
tion des points dans les clusters est itr plusieurs fois jusqu ce que les for j in range(width):
clusters ne changent plus (ou trs peu). On obtient alors nos groupes de image_comp[i][j] = cluster_centers[labels[label_idx]]
points finaux, comme montr sur la figure (f). label_idx += 1
return image_comp
Clustering des couleurs de limage
Tout est maintenant notre disposition pour reconstruire limage avec un
Maintenant que nous savons comment fonctionne lalgorithme du K-
nombre de couleurs rduit.
# Recreation of the array with the initial images dimensions
Means, appliquonsle sur le dataset reprsentant notre image initiale.
plt.figure(2)
le nombre de couleurs que lon va utiliser dans limage.
plt.clf()
Limplmentation se fait alors de la manire suivante :
labels = kmeans.predict(image_array)
en se restreignant 64
couleurs sur limage :
Le paramtre random_state=0 nest pas obligatoire et permet de rgler Fig.3.
linitialisation alatoire. En se restreignant 64
couleurs, limage garde
Reconstruction de limage compresse donc une bonne quali-
Nous avons alors disposition les coordonnes RGB de chaque centrode t. Le perroquet est
(prsentes dans lattribut kmeans.cluster_centers_), ainsi que le label du
Fig.3
bien reproduit grce
groupe dans lequel chaque pixel est affect (prsent dans labels). des couleurs trs mar-
A prsent, nous devons reconstruire un tableau de mme dimension que ques, la diffrence du fond (mer et nuages) du fait de limportance de la
limage originale, car pour le moment nous avons simplement un tableau continuit des couleurs (du bleu clair au bleu fonc). De ce fait, en se
de trois colonnes et dautant de lignes que de pixels. Nous allons donc restreignant un plus petit nombre de couleurs, limpression de continuit
construire une fonction permettant de reconstruire limage avec ces diff- entre les couleurs est plus difficilement ralisable, do ces coupures
rentes contraintes. Elle a donc pour paramtres les centrodes, les labels entre chaque couleur.
de chaque pixel, ainsi que la largeur et la hauteur de limage. Si on compare les tailles des images, limage originale faisait 122 Ko, alors
que limage compresse rduite 64 couleurs ne fait plus que 52 Ko.
Fig.2 Voici les rsultats obtenus pour plusieurs K. On peut voir que notre oeil a
rapidement limpression que limage est loriginale ( partir de 64 ou 128),
alors que le nombre de couleurs est beaucoup plus faible Fig.4.
Nous avons ici illustr un algorithme de clustering dans le cadre dune
rduction de nombre de couleurs dans une image. Il y a cependant de
nombreuses autres applications au clustering, comme par exemple cher-
cher regrouper des utilisateurs dun site Internet selon leur comporte-
ment sur celui-ci, ou bien crer des zones pour optimiser les circuits de
distribution dune entreprise. Pour plus dinformations, se rfrer au tuto-
riel sur le mme sujet sur le site de scikit-learn.
vous proposons ici dappliquer un modle de rgression pour prdire la Fig.5. Plusieurs features sont notre disposition pour lanalyse : certaines
demande de location de vlos dans une ville. Le but est alors de faire mer- correspondent la date (saison, anne, mois, etc.), dautres au temps
ger une variable cible (notre target), qui nest autre que le nombre de vlos (mto, temprature, humidit, etc.). Les trois dernires colonnes sont des
lous dans une journe, en prenant en compte diffrentes variables (jour variables cibles . Casual correspond au nombre de locations par des uti-
de la semaine, temprature, mto, etc.). Pour cela, nous allons appliquer lisateurs occasionnels, Registered au nombre de locations par des utili-
une dmarche systmatique en Data Science : sateurs enregistrs et Count au nombre total de locations. Pour la suite
a Exploration des donnes : comprhension et connaissance des don- de notre tude, nous allons nous concentrer sur les features season, mnth,
nes disposition. holiday, weekday, workingday, weathersit, temp, hum et windspeed, et ten-
a Feature Engineering : cration des features qui vont servir de base pour ter de prdire la target casual. Restreignons donc notre dataset :
nos modles.
a Splitting : sparation des donnes en trois jeux diffrents, un pour lap- target = data.casual
prentissage (training set), un pour le tunning des paramtres (validation list_features = ['season','mnth','holiday','weekday','workingday','weathersit','temp','hum','
set) et le dernier pour lvaluation du modle (test set). windspeed']
a Modelling: cration et paramtrage dun modle de Machine Learning X = data[list_features]
pour pouvoir raliser la prdiction.
Exploration des donnes et Feature Engineering
Chargement des donnes Deux types de variables sont notre disposition :
Avant toute chose, nous allons charger les donnes en allant les chercher a Des variables catgorielles : elles reprsentent un nombre fini de cas
leur source. possibles, sans quil ny ait forcment de relation dordre entre les tats
import pandas as pd
(typiquement les jours de la semaine)
a Des variables continues : le nombre de possibilits est infini et il existe une
from StringIO import StringIO
from zipfile import ZipFile
relation dordre entre les valeurs observes (typiquement la temprature)
url = urlopen("https://archive.ics.uci.edu/ml/machine-learning-databases/00275/Bike-
Observons prsent les diffrentes modalits des variables catgorielles
Sharing-Dataset.zip")
notre disposition.
zipfile = ZipFile(StringIO(url.read()))
print "Nombre de modalits de la variable %s: %d" % ('season',len(X['season'].unique()))
data = pd.read_csv(zipfile.open("day.csv"), parse_dates = ['dteday'])
print "Nombre de modalits de la variable %s: %d" % ('mnth',len(X['mnth'].unique()))
Voyons quoi ressemblent les donnes pour mieux comprendre comment print "Nombre de modalits de la variable %s: %d" % ('holiday',len(X['holiday'].unique()))
les traiter par la suite : print "Nombre de modalits de la variable %s: %d" % ('weekday',len(X['weekday'].unique()))
print "Nombre de modalits de la variable %s: %d" % ('workingday',len(X['workingday']
data.head()
.unique()))
Fig.4 print "Nombre de modalits de la variable %s: %d" % ('weathersit',len(X['weathersit']
.unique()))
Fig.5
68 Programmez! a Avril 2015
066_070_184 18/03/15 21:59 Page69
Une fois que les prdictions sont faites, il est important de pouvoir
Variables continues mesurer leur qualit. Pour cela, il faut avant tout se fixer une mesure de
X[['temp','hum','windspeed']].describe()
lerreur. Dans notre cas, nous allons utiliser le Root Mean Squared Error.
Fig.8.
Cest une mesure classique de lerreur faite par un modle de rgression.
Nous allons donc pralablement dfinir la fonction de calcul de lerreur
Regarder la description statistique pour lappliquer ensuite aux prdictions faites sur le training set, ainsi
globale des variables continues dans que sur le test set.
notre dataset est une tape importan-
te car elle permet de lexplorer ou de le def rmse(obs, pred):
modifier lorsquil contient des valeurs return np.sqrt(np.mean((obs-pred)**2))
manquantes ou des valeurs aber-
rantes. Cela permet aussi d'avoir une rmse_train = rmse(target_train, model.predict(X_train))
ide des ordres de grandeur des rmse_test = rmse(target_test, prediction)
variables ainsi que de leur distribution.
print "Train Error: %.2f" % rmse_train
Splitting print "Test Error: %.2f" % rmse_test
Ce concept consiste sparer les donnes en au moins deux parties : une Train Error: 0.00
base dapprentissage nomme training set et une deuxime qui servira Test Error: 501.31
Remarque : il existe dj une implmentation du mse (sans la racine) dans sklearn mais nous
tester notre apprentissage sur des donnes nouvelles encore jamais
observes, on parle de test set. avons pris le parti de le rcrire dans un but didactique.
Il est aussi recommand dajouter une troisime partie, appele validation
set; il va tre utilis pour valider un modle et ses paramtres lors de sa Avec un Train Error faible et un Test Error lev, nous nous retrouvons
construction ( noter qu'il existe d'autres mthodes d'valuation qui ne dans une situation dlicate appele loverfitting. Du fait quil nexiste
ncessitent pas la prsence de ce validation set, parmi lesquelles la cross- aucune erreur sur le training set, loverfitting peut tre vu comme de lap-
validation ou encore le principe du Bootstrap, mais dont l'explication sorti- prentissage par coeur. Larbre de dcision, auquel nous navons donn
rait du cadre de cet article). Le test set servira alors pour la validation finale aucune restriction dans les paramtres, a russi trouver des combi-
du modle, nous donnant ainsi une estimation fiable de notre erreur. naisons de caractristiques lui permettant tous les coups de prdire
Construisons maintenant nos training, validation et test set : exactement la bonne valeur sur les donnes quil a apprises. Le problme
est que ds que de nouvelles donnes, encore jamais observes, sont
import numpy as np soumises au modle, il va trs souvent faire de fortes erreurs, comme ont
np.random.seed(seed=1234) peut le constater sur le rmse du test set. Afin dviter ce phnomne, il faut
ind_train = np.random.choice(len(X),0.5*len(X),replace=False) faire ce que lon appelle du tunning : trouver les paramtres donner au
ind_val_test = list(set(range(len(X))) - set(ind_train)) modle qui vont minimiser lerreur sur des donnes non observes. Pour
ind_val = np.random.choice(ind_val_test,0.7*len(ind_val_test),replace=False) notre arbre de dcision, lun des paramtres sur lesquels il est possible de
ind_test = list(set(ind_val_test) - set(ind_val)) jouer est sa profondeur maximale, soit son nombre de rgles. En effet, plus
un arbre est profond, moins il y a de donnes dans ses feuilles et plus il y
X_train, X_val, X_test, target_train, target_val, target_test = X.iloc[ind_train], X.iloc a de chance de faire de loverfitting. En fixant par exemple la profondeur
[ind_val], X.iloc[ind_test], target.iloc[ind_train], target.iloc[ind_val], target.iloc[ind_test] maximale 1, nous obtenons larbre suivant :
tre plus robuste quun simple arbre de dcision. Pour chaque arbre de la
Random Forest, seulement une partie des variables vont lui tre pro-
poses, et les donnes sont slectionnes alatoirement avec remise.
Cela permet de rajouter plus dalatoire dans les donnes et dans la slec-
tion des features, ce qui est statistiquement plus viable dans le but davoir
une meilleure capacit de gnralisation. Encore une fois, il est ncessaire
Nous navons autoris ici quune profondeur de 1 : larbre a donc t con- de faire un bon tunning pour viter loverfitting. Pour une Random Forest,
traint de trouver la meilleure caractristique et son seuil, ceci pour spar- il est classique doptimiser la profondeur maximale de chaque arbre, ainsi
er en deux les donnes puis estimer la valeur donner. que le nombre minimal dlments par feuille. Cest ce que nous allons
Appliquons maintenant une dmarche complte de tunning qui va nous faire maintenant avec une Random Forest compose de 2000 arbres.
scores = []
permettant de minimiser lerreur sur le validation set.
max_depth_best = tab_scores.max_depth.iloc[0]
struire un arbre de dcision plus stable.
min_samples_leaf_best = tab_scores.min_samples_leaf.iloc[0]
model = DecisionTreeRegressor(max_depth=tab_scores.max_depth.iloc[0])
model.fit(pd.concat([X_train, X_val]), pd.concat([target_train,target_val]))
model = RandomForestRegressor(n_estimators=5000, max_depth=max_depth_best,
prediction = model.predict(X_test) # Prediction on the test set
min_samples_leaf=min_samples_leaf_best)
model.fit(pd.concat([X_train, X_val]), pd.concat([target_train, target_val]))
rmse_train = rmse(pd.concat([target_train,target_val]), model.predict(pd.concat([X_
prediction = model.predict(X_test)
train, X_val])))
rmse_test = rmse(target_test, prediction)
rmse_train = rmse(pd.concat([target_train, target_val]), model.predict(pd.concat([X_
train, X_val])))
print "Train Error: %.2f" % rmse_train
rmse_test = rmse(target_test, prediction)
print "Test Error: %.2f" % rmse_test