Dans ce carnet, nous allons effectuer une recherche par grille sur les méthodes d’imputation disponibles dans Scikit-learn afin de déterminer quelle technique d’imputation fonctionne le mieux pour cet ensemble de données et le modèle d’apprentissage machine de choix.
Nous formerons également un modèle d’apprentissage machine très simple dans le cadre d’un petit pipeline.
import pandas as pd
import numpy as np
# import classes for imputation
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
# import extra classes for modelling
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LogisticRegression
np.random.seed(0)
data = pd.read_csv('../exportfeature.csv',parse_dates=['date'],infer_datetime_format=True,dayfirst=True,sep=";",encoding='ANSI')
# On supprime la colonne rapport
data.drop(['rapport','date','id','rPoids','idOeillere'], axis=1, inplace=True)
data.head()
place M1 M2 M3 M4 allocation Hippodrome nbPartants idHippodrome nDistance nAllocation idFerrure idJockey nbPartants.1 iCote
0 1 3a 3m Da 3a 90000.0 Vincennes 17 Vincennes 2100 95000 0 18 17 12.0
1 1 3a 9Da 5a 4a 70000.0 Vincennes 18 Vincennes 2700 58000 1 30 18 12.0
2 0 1a Da Da 1a 44000.0 Vincennes 12 Vincennes 2850 37000 0 53 10 9.0
3 1 Da 7a 4a 2a 40000.0 Vincennes 11 Vincennes 2200 38000 2 143 13 4.0
4 0 1a 7a 10a 11a 40000.0 Vincennes 16 Vincennes 2700 34000 0 50 17 8.0
# Variable de type catégorie
features_categorical = [c for c in data.columns if data[c].dtypes=='O']
# Variables de type numérique et qui n'est pas place
features_numerical = [c for c in data.columns if data[c].dtypes!='O' and c !='place']
# Variable de type catégorie
data[features_categorical].head()
M1 M2 M3 M4 Hippodrome idHippodrome
0 3a 3m Da 3a Vincennes Vincennes
1 3a 9Da 5a 4a Vincennes Vincennes
2 1a Da Da 1a Vincennes Vincennes
3 Da 7a 4a 2a Vincennes Vincennes
4 1a 7a 10a 11a Vincennes Vincennes
# Variable de type numérique
data[features_numerical].head()
allocation nbPartants nDistance nAllocation idFerrure idJockey nbPartants.1 iCote
0 90000.0 17 2100 95000 0 18 17 12.0
1 70000.0 18 2700 58000 1 30 18 12.0
2 44000.0 12 2850 37000 0 53 10 9.0
3 40000.0 11 2200 38000 2 143 13 4.0
4 40000.0 16 2700 34000 0 50 17 8.0
# Injectons des données absentes
# 1% dans M2
data.loc[data.sample(frac=0.01).index, 'M2'] = np.nan
# 3% dans M4
data.loc[data.sample(frac=0.01).index, 'M2'] = np.nan
# 5% dans allocation
data.loc[data.sample(frac=0.05).index, 'allocation'] = np.nan
# 15% dans idJockey
data.loc[data.sample(frac=0.15).index, 'idJockey'] = np.nan
# 0.06 % dans Hippodrome
data.loc[data.sample(frac=0.06).index, 'Hippodrome'] = np.nan
# 0.65 % dans nbPartants.1
data.loc[data.sample(frac=0.65).index, 'nbPartants.1'] = np.nan
# Création du jeu d'entrainement et de test
X_train, X_test, y_train, y_test = train_test_split(
data.drop('place', axis=1),
data['place'],
test_size=0.3,
random_state=0)
X_train.shape, X_test.shape
((14352, 14), (6152, 14))
# Nous créons les pipelines de prétraitement pour les deux
# données numériques et catégorielles
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('onehot', OneHotEncoder(handle_unknown='ignore'))])
preprocessor = ColumnTransformer(
transformers=[
('numerical', numeric_transformer, features_numerical),
('categorical', categorical_transformer, features_categorical)])
# Notez que pour initialiser le pipeline, je passe n'importe quel argument aux transformateurs.
# Ceux-ci seront modifiés lors de la recherche de réseau ci-dessous.
# Ajouter le classificateur au pipeline de prétraitement.
# Nous avons maintenant un pipeline de prédiction complet.
clf = Pipeline(steps=[('preprocessor', preprocessor),
('classifier', LogisticRegression())])
# maintenant nous créons la grille avec tous les paramètres que nous voudrions tester
param_grid = {
'preprocessor__numerical__imputer__strategy': ['mean', 'median'],
'preprocessor__categorical__imputer__strategy': ['most_frequent', 'constant'],
'classifier__penalty' : ['l1', 'l2'],
'classifier__C' : np.logspace(-4, 4, 20),
'classifier__solver' : ['liblinear']
}
grid_search = GridSearchCV(clf, param_grid, cv=5, iid=False, n_jobs=-1, scoring='precision')
# cv=3 est la validation croisée
# no_jobs =-1 indique d'utiliser tous les cpus disponibles
# scoring='r2' indique qu'il faut évaluer en utilisant le r au carré
# pour plus de détails dans la visite des paramètres de la grille :
#https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
Lors de la définition des paramètres de la grille, c’est ainsi que nous indiquons les paramètres :
préprocesseur__numérique__imputer__stratégie’ : [“moyenne”, “médiane”],
la ligne de code ci-dessus indique que je souhaite tester la moyenne et la médiane dans l’étape d’imputation du processeur numérique.
préprocesseur__catégorie__imputer__stratégie’ : [most_frequent’, ‘constant’]
la ligne de code ci-dessus indique que je souhaite tester la valeur la plus fréquente ou une valeur constante dans l’étape d’imputation du processeur catégorique
classificateur__alpha’ : [0.1, 1.0, 0.5]
la ligne de code ci-dessus indique que je veux tester ces 3 valeurs pour le paramètre alpha du Lasso. Notez que le Lasso est l’étape ‘classificateur’ de notre dernier pipeline
# et maintenant nous nous entraînons sur toutes les combinaisons possibles des paramètres ci-dessus
grid_search.fit(X_train, y_train)
# et nous imprimons le meilleur score sur le train
print(("Meilleur résultat: %.3f"
% grid_search.score(X_train, y_train)))
Meilleur résultat: 0.587
C’est très loin d’être top comme résultat mais bon… On verra un peu plus loin les différentes mesures pour juger de la qualité d’un modèle
# impression des meilleurs paramétres
grid_search.best_estimator_
Pipeline(steps=[('preprocessor',
ColumnTransformer(transformers=[('numerical',
Pipeline(steps=[('imputer',
SimpleImputer()),
('scaler',
StandardScaler())]),
['allocation', 'nbPartants',
'nDistance', 'nAllocation',
'idFerrure', 'idJockey',
'nbPartants.1', 'iCote']),
('categorical',
Pipeline(steps=[('imputer',
SimpleImputer(fill_value='missing',
strategy='most_frequent')),
('onehot',
OneHotEncoder(handle_unknown='ignore'))]),
['M1', 'M2', 'M3', 'M4',
'Hippodrome',
'idHippodrome'])])),
('classifier',
LogisticRegression(C=0.0018329807108324356, penalty='l1',
solver='liblinear'))])
# impression des meilleurs paramètres
grid_search.best_params_
{'classifier__C': 0.0018329807108324356,
'classifier__penalty': 'l1',
'classifier__solver': 'liblinear',
'preprocessor__categorical__imputer__strategy': 'most_frequent',
'preprocessor__numerical__imputer__strategy': 'mean'}
# On peut voir les différentes évaluations du modèle
grid_search.cv_results_['params']
[{'classifier__C': 0.0001,
'classifier__penalty': 'l1',
'classifier__solver': 'liblinear',
'preprocessor__categorical__imputer__strategy': 'most_frequent',
'preprocessor__numerical__imputer__strategy': 'mean'},
{'classifier__C': 0.0001,
'classifier__penalty': 'l1',
'classifier__solver': 'liblinear',
'preprocessor__categorical__imputer__strategy': 'most_frequent',
'preprocessor__numerical__imputer__strategy': 'median'},
{'classifier__C': 0.0001,
'classifier__penalty': 'l1',
'classifier__solver': 'liblinear',
'preprocessor__categorical__imputer__strategy': 'constant',
'preprocessor__numerical__imputer__strategy': 'mean'},
{'classifier__C': 0.0001,
'classifier__penalty': 'l1',
'classifier__solver': 'liblinear',
'preprocessor__categorical__imputer__strategy': 'constant',
'preprocessor__numerical__imputer__strategy': 'median'},....
# et ici les scores pour chacune des combinaisons ci-dessus
grid_search.cv_results_['mean_test_score']
array([0. , 0. , 0. , 0. , 0.56679338,
0.5668684 , 0.56695844, 0.56660933, 0. , 0. ,
0. , 0. , 0.57151022, 0.57117435, 0.57161545,
0.57124668, 0. , 0. , 0. , 0. ,
0.57909272, 0.57943362, 0.57867718, 0.57871535, 0.61039731,
0.61039731, 0.61039731, 0.61039731, 0.5852586 , 0.58528091,
0.58469451, 0.58500554, 0.5751882 , 0.57535101, 0.57562511,
0.57605211, 0.58884431, 0.58947411, 0.58875039, 0.58898246,
0.58482377, 0.58467612, 0.58424666, 0.58397768, 0.59030059,
0.59035226, 0.5900326 , 0.58923194, 0.58951257, 0.58951087,
0.58964938, 0.58936819, 0.59040801, 0.58965257, 0.5897056 ,
0.59006782, 0.59174457, 0.59235731, 0.59182597, 0.5920027 ,
0.58829259, 0.58881793, 0.58863632, 0.58817874, 0.59137442,
0.59148842, 0.59159803, 0.5919712 , 0.58710895, 0.58720342,
0.58639316, 0.58684826, 0.58861476, 0.5882917 , 0.58870254,
0.58857949, 0.58627164, 0.58586007, 0.58639199, 0.58640217,
0.58486008, 0.58544157, 0.58553539, 0.58554887, 0.58541298,
0.58430234, 0.58513069, 0.58463359, 0.58484934, 0.58451143,
0.58420025, 0.58434182, 0.58424058, 0.58469323, 0.58435426,
0.58460992, 0.58530962, 0.58506749, 0.58505442, 0.58531816,
0.5848534 , 0.58467124, 0.5851044 , 0.58482227, 0.58532472,
0.58475155, 0.58527607, 0.58442178, 0.58510619, 0.58475485,
0.58453388, 0.58479622, 0.58456439, 0.58466107, 0.58456553,
0.5842657 , 0.58467692, 0.58460191, 0.58480617, 0.58470849,
0.58446818, 0.58402489, 0.58418728, 0.58400863, 0.58434936,
0.58431142, 0.58443888, 0.58413899, 0.58423765, 0.58372824,
0.58405325, 0.58386498, 0.58455694, 0.58409238, 0.58438478,
0.5841755 , 0.58423386, 0.58391666, 0.58418072, 0.58387934,
0.58451976, 0.58405258, 0.58435159, 0.5840078 , 0.58412938,
0.58366507, 0.58403193, 0.58357109, 0.58447239, 0.58400769,
0.58439593, 0.5840678 , 0.58428171, 0.58385738, 0.58401521,
0.58386736, 0.58442809, 0.58388154, 0.58433256, 0.58400448])
# et enfin, vérifions les performances par rapport à l'ensemble des tests
print(("Meilleur modele: %.3f"
% grid_search.score(X_test, y_test)))
Meilleur modele: 0.582
Ce qui est intéressant ici c’est de voir qu’il y a peu de différence entre la phase d’apprentissage et celle de test.
Je télécharge mon guide gratuit
Thank you!
You have successfully joined our subscriber list.
Vous recevrez votre guide par email sans aucun engagement de votre part.