Discrétisation avec Scikit-Learn
En science des données, la discrétisation désigne le procédé qui consiste à transformer une variable quantitative en une variable qualitative. Pour cela, la variable quantitative est découpée en intervalles (classes) qui deviennent désormais les modalités de la variable qualitative. Elle est communément utilisée comme une méthode de pré-traitement avant la mise en place de différents modèles.
Avant de parcourir les différentes méthodes que Scikit-Learn nous fournit pour faire une discrétisation, notons qu’il y a deux principales questions à se poser avant de faire une discrétisation :
-
- Combien de classes devons nous construire ?
- Comment choisir les bornes de ces classes ?
Pour répondre à ces deux questions, plusieurs formules ou méthodes classiques que nous détaillerons pas dans cet article sont utilisées. Cependant on peut classer ces méthodes en deux groupes.
Discrétisation non supervisée
La discrétisation non supervisée consiste à répondre aux deux questions définies ci-dessus en se basant uniquement sur la structure de la variable. En effet, si on observe la figure 1, on se rend compte qu’une segmentation à 3 classes est à envisager avec les extrémités de chaque classe. Mais on a souvent du mal à trouver une représentation adéquate qui nous permet de deviner visuellement le nombre et les bornes des classes adéquates. Dans ce cas pour trouver le nombre de classe, il existe des formules classiques telles que la formule de Sturges ou celle de Freedman-Diaconis. En ce qui concerne, le choix des bornes plusieurs méthodes existent également dont certaines sont implémentées dans Scikit-Learn. C’est difficile de savoir laquelle des méthodes utilisées pour avoir une “bonne” discrétisation.
Discrétisation supervisée
Ici, l’objectif est clair, on cherche à effectuer une discrétisation qui discrimine plus ou moins bien une autre variable qui est qualitative. En d’autre termes, on veut trouver le nombre d’intervalles et leurs bornes de telles sortes qu’on regroupe les individus qui appartiennent à un groupe bien précis (figure 2). Malheureusement les méthodes de discrétisation supervisée ( ChiMerge, MDLPC) ne sont pas encore disponible dans Scikit-Learn.
Pourquoi faire une discrétisation ?
La discrétisation n’est pas une méthode de pré-traitement indispensable, cependant, elle s’avère utile pour plusieurs raisons :
-
- Rendre les algorithmes d’apprentissage plus performants
En discrétisant une variable, on la regroupe en classe, donc on perd évidemment en informations sur elle. Mais les informations perdues peuvent être bénéfique pour certains modèles. En effet, la discrétisation peut permettre d’atténuer le poids des valeurs aberrantes et de corriger des distributions asymétriques et ainsi rendre les algorithmes plus performant.
-
- Rendre homogène un jeu de donnée hétérogène
On est souvent emmener à travailler qu’avec des variables qualitatives parce qu’on veut soit utiliser des modèles qui n’utilise que ces types de données (règles d’association) ou soit pour effectuer un pré-prétraitement des données en utilisant une analyse des composantes multiples (ACM).
-
- Tarification en assurance non vie
En assurance non vie, les variables continues sont généralement discrétisées pour mettre en place un modèle de tarification pour plusieurs raisons techniques mais en outre parce que cela permet de mieux interpréter les modèles.
Discrétisation avec Scikit-learn
Scikit-Learn nous fournit une classe nous permettant de faire des discrétisations : la classe KBinsDiscretizer. Cette classe implémente 3 stratégie de discrétisation non supervisée :
-
-
- La stratégie « uniforme » : Classes de valeurs d’amplitudes constantes
- La stratégie « quantile » : Classes contenant le même nombre d’éléments
- La stratégie « kmeans » : Classes basées sur un Algorithme de k-means
-
-
- Importation des données
import pandas as pd data=data=pd.read_csv(r"https://raw.githubusercontent.com/lucayapi/Article_Alliage/master/BASE_DEF.csv") #2 variables à discrétiser data_to_discretize=data[["age","duree_permis"]] #Nombre de classes bins=5
On doit choisir au préalable un nombre de classe avant l’application des différentes stratégies. Nous choisissons donc de faire une discrétisation en 5 classes.
-
- La stratégie « uniforme »
from sklearn.preprocessing import KBinsDiscretizer Discretizor=KBinsDiscretizer(n_bins=bins,encode="ordinal",strategy="uniform") Discretizor.fit_transform(data_to_discretize) df_disc_uni=pd.DataFrame(Discretizor.fit_transform(data_to_discretize),columns=data_to_discretize.columns,dtype="int") df_disc_uni.head()
-
- La stratégie « quantile »
from sklearn.preprocessing import KBinsDiscretizer Discretizor=KBinsDiscretizer(n_bins=bins,encode="ordinal",strategy="quantile") Discretizor.fit_transform(data_to_discretize) #meilleur vue du résultat df_disc_qt=pd.DataFrame(Discretizor.fit_transform(data_to_discretize),columns=data_to_discretize.columns,dtype="int") df_disc_qt.head()
-
- La stratégie « kmeans »
from sklearn.preprocessing import KBinsDiscretizer Discretizor=KBinsDiscretizer(n_bins=bins,encode="ordinal",strategy="kmeans") Discretizor.fit_transform(data_to_discretize) #meilleur vue du résultat df_disc_kmeans=pd.DataFrame(Discretizor.fit_transform(data_to_discretize),columns=data_to_discretize.columns,dtype="int") df_disc_kmeans.head()
Remarquons que nous avons configuré le paramètre encode avec la valeur ordinal car on voulait obtenir les différentes classes recordées de de 0 à 4 (5 classes).D’autres types de configuration sont disponible telles que onehot, onehot-dense.
On peut également décider de faire une discrétisation customisée c’est à dire en choisissant nous-même, les intervalles et les noms des classes. Pour cela on s’aide de la fonction pd.cut() de pandas et de la classe FunctionTransFormer de Scikit-learn.
from sklearn.preprocessing import FunctionTransformer #intervalles des classes et noms bins_age= [18,20,30,50,60,np.inf] bins_duree_permis= [0,15,22,30,np.inf] labels_age = ['18-20', '20-30','30-50','50-60', '60-plus'] labels_duree_permis = ['0-15', '15-22','22-30','30-plus'] bins=[bins_age,bins_duree_permis] labels=[labels_age,labels_duree_permis] df_disc=data_to_discretize.copy() #copie du tableau à discrétiser var_to_discretize=data_to_discretize.columns for bins,labels,var in zip(bins,labels,var_to_discretize): transformer = FunctionTransformer( pd.cut, kw_args={'bins': bins , 'labels': labels , 'retbins': False}) df_disc[var]=transformer.fit_transform(df_disc[var]) #Affichage des 5 premières lignes df_disc.head()
3 commentaires