#changer le dossier par défaut
import os
os.chdir("C:/Users/ricco/Desktop/demo")
#charger les données
import pandas
df = pandas.read_excel("wave5300.xlsx")
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5300 entries, 0 to 5299 Data columns (total 23 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 CLASSE 5300 non-null object 1 V1 5300 non-null float64 2 V2 5300 non-null float64 3 V3 5300 non-null float64 4 V4 5300 non-null float64 5 V5 5300 non-null float64 6 V6 5300 non-null float64 7 V7 5300 non-null float64 8 V8 5300 non-null float64 9 V9 5300 non-null float64 10 V10 5300 non-null float64 11 V11 5300 non-null float64 12 V12 5300 non-null float64 13 V13 5300 non-null float64 14 V14 5300 non-null float64 15 V15 5300 non-null float64 16 V16 5300 non-null float64 17 V17 5300 non-null float64 18 V18 5300 non-null float64 19 V19 5300 non-null float64 20 V20 5300 non-null float64 21 V21 5300 non-null float64 22 SAMPLE_STATUS 5300 non-null object dtypes: float64(21), object(2) memory usage: 952.5+ KB
#valeurs de SAMPLE_STATUS
#protocole expérimental décrit dans le livre de Breiman et al., 1984
#pages 49 et 50
df.SAMPLE_STATUS.value_counts()
test 5000 train 300 Name: SAMPLE_STATUS, dtype: int64
#partition learning-test basé sur la colonne SAMPLE_STATUS
dfTrain = df.loc[df.SAMPLE_STATUS == 'train'].drop(columns='SAMPLE_STATUS')
dfTrain.head()
CLASSE | V1 | V2 | V3 | V4 | V5 | V6 | V7 | V8 | V9 | ... | V12 | V13 | V14 | V15 | V16 | V17 | V18 | V19 | V20 | V21 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | A | 0.75 | 0.05 | 2.60 | 2.28 | 2.07 | 3.42 | 3.66 | 2.65 | 2.30 | ... | 1.69 | 0.82 | 1.59 | 1.02 | 0.58 | -0.37 | 2.76 | 0.92 | 0.89 | -1.13 |
1 | A | 1.85 | -0.66 | 0.70 | 3.69 | 1.50 | 2.42 | 2.57 | 4.62 | 2.07 | ... | 3.12 | 2.01 | 1.43 | 2.00 | 3.06 | 1.39 | 2.79 | 0.34 | 0.54 | 0.64 |
2 | A | -1.37 | -0.45 | -1.35 | 2.12 | -0.15 | 1.36 | 0.27 | -0.26 | -1.19 | ... | 1.41 | 2.65 | 3.10 | 4.49 | 3.96 | 3.65 | 2.26 | 1.81 | 1.04 | -0.41 |
3 | A | -0.29 | -0.28 | -1.24 | 1.65 | 0.94 | 1.75 | 4.58 | 0.29 | 3.33 | ... | 2.29 | 2.32 | 1.82 | 0.71 | 2.71 | 2.61 | 2.43 | 0.58 | 1.66 | -0.28 |
4 | A | -1.16 | 1.11 | 1.39 | 3.09 | 1.83 | 4.76 | 3.01 | 3.93 | 2.57 | ... | 1.59 | 1.21 | 3.39 | 1.64 | 2.84 | -0.03 | 2.11 | 2.11 | 0.37 | 1.02 |
5 rows × 22 columns
#de même pour 'test'
dfTest = df.loc[df.SAMPLE_STATUS == 'test'].drop(columns='SAMPLE_STATUS')
dfTest.shape
(5000, 22)
#préparation des données (bis)
#partition de train en growing et pruning sets
#'pruning set' = on parle aussi de 'validation set' ou 'tunig set' dans certains logiciels
from sklearn.model_selection import train_test_split
dfGrow, dfPrune = train_test_split(dfTrain,test_size=100,random_state=0,stratify=dfTrain.CLASSE)
#distribution dans growing set
dfGrow.CLASSE.value_counts(normalize=True)
A 0.365 B 0.340 C 0.295 Name: CLASSE, dtype: float64
#et pour le prune
dfPrune.CLASSE.value_counts(normalize=True)
A 0.37 B 0.34 C 0.29 Name: CLASSE, dtype: float64
#import de la classe arbre de décision
from sklearn.tree import DecisionTreeClassifier
#instanciation avec les paramètres par défaut
#ccp_alpha = 0 notamment (pas de post-élagage)
arbre = DecisionTreeClassifier(random_state=0)
#apprentissage
arbre.fit(dfGrow[dfGrow.columns[1:]],dfGrow.CLASSE)
#complexité - nombre de feuilles
arbre.get_n_leaves()
30
#affichage
import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(5,5))
plot_tree(arbre,feature_names=dfGrow.columns[1:],filled=True)
plt.show()
#taux d'erreur en resubstitution (sur les 200 growing set)
#on a un arbre "pur"
#dans le sens où toutes les règles sont sans contre-exemples
1-arbre.score(dfGrow[dfGrow.columns[1:]],dfGrow.CLASSE)
0.0
#performances en test - taux d'erreur
#vrai reflet des performances en généralisation
err_default = 1-arbre.score(dfTest[dfTest.columns[1:]],dfTest.CLASSE)
print(err_default)
0.3096
#intervalle de confiance à 95%
from statsmodels.stats.proportion import proportion_confint
proportion_confint(count=err_default*dfTest.shape[0],nobs=dfTest.shape[0],alpha=0.05)
(0.2967851373368864, 0.3224148626631136)
#chemin de post-élagage en fonction de ccp_alpha
path =arbre.cost_complexity_pruning_path(dfGrow[dfGrow.columns[1:]],dfGrow.CLASSE)
print(path)
{'ccp_alphas': array([0. , 0.00484848, 0.00666667, 0.0075 , 0.008 , 0.00857143, 0.00875 , 0.00875 , 0.00942068, 0.00944444, 0.00944444, 0.00981481, 0.0125 , 0.01375926, 0.01520531, 0.016 , 0.01727124, 0.01795322, 0.0200119 , 0.02482051, 0.02851282, 0.02942205, 0.03877273, 0.06455013, 0.09808853, 0.13281383]), 'impurities': array([0. , 0.00969697, 0.01636364, 0.02386364, 0.03186364, 0.04043506, 0.04918506, 0.05793506, 0.06735574, 0.07680019, 0.09568908, 0.10550389, 0.11800389, 0.14552241, 0.17593304, 0.19193304, 0.20920428, 0.2271575 , 0.2471694 , 0.27198991, 0.30050273, 0.32992478, 0.36869751, 0.43324763, 0.53133617, 0.66415 ])}
#construire arbre pour chaque valeur de ccp_alphas
#receuillir le nombre de feuilles, taux d'erreur en growing, en pruning
Hazos = {'modele':[],'nb_feuilles':[],'err_grow':[],'err_prune':[]}
#go...
for ccp in path['ccp_alphas']:
#instanciation et entraînement
cedre = DecisionTreeClassifier(ccp_alpha=ccp,random_state=0)
cedre.fit(dfGrow[dfGrow.columns[1:]],dfGrow.CLASSE)
#récupération des infos
Hazos['modele'].append(cedre)
Hazos['nb_feuilles'].append(cedre.get_n_leaves())
Hazos['err_grow'].append(1-cedre.score(dfGrow[dfGrow.columns[1:]],dfGrow.CLASSE))
#utilisation du 'pruning set' pour la première fois
Hazos['err_prune'].append(1-cedre.score(dfPrune[dfPrune.columns[1:]],dfPrune.CLASSE))
#nombre d'arbres qui ont été construits
print(len(Hazos['modele']))
26
#graphique à la Tanagra
#mettant en relation le nombre de feuilles
#avec les taux d'erreur en Growing et Pruning
plt.plot(Hazos['nb_feuilles'],Hazos['err_grow'],c='red',marker='.',label='Growing Set')
plt.plot(Hazos['nb_feuilles'],Hazos['err_prune'],c='green',marker='.',label='Pruning Set')
plt.title("Taux d'erreur en fonction du nombre de feuilles")
plt.xlabel('Nombre de feuilles')
plt.ylabel("Taux d'erreur")
plt.legend()
plt.show()
#indice de l'arbre le plus performant en pruning
import numpy
idMin = numpy.argmin(Hazos['err_prune'])
print(idMin)
13
#valeur du ccp_alpha corresp.
path['ccp_alphas'][idMin]
0.01375925925925927
#son nombre de feuilles
Hazos['nb_feuilles'][idMin]
14
#vérifions même info à partir de l'arbre "optimal"
arbre_optim = Hazos['modele'][idMin]
arbre_optim.get_n_leaves()
14
#afficher l'arbre
plt.figure(figsize=(5,5))
plot_tree(arbre_optim,feature_names=dfGrow.columns[1:],filled=True)
plt.show()
#performance en test
1-arbre_optim.score(dfTest[dfTest.columns[1:]],dfTest.CLASSE)
0.2942