Création de Pipelines avec Sklearn#
Un pipeline en machine learning est un outil structurant permettant d’automatiser et de simplifier le flux de traitement des données et de modélisation. Il consiste en une séquence ordonnée d’étapes, où chaque étape correspond à une transformation spécifique (prétraitement, sélection de caractéristiques, etc.) ou à un modèle d’apprentissage. L’objectif principal d’un pipeline est de garantir un traitement cohérent des données, depuis leur préparation jusqu’à l’entraînement et la prédiction, en minimisant le risque d’erreurs manuelles. En encapsulant toutes les étapes dans une seule entité, un pipeline favorise la réplicabilité, améliore la lisibilité du code et facilite la validation croisée sur des processus complets. Il est donc crucial en machine learning pour développer des modèles robustes et maintenables, surtout dans des environnements où la préparation des données et l’entraînement des modèles nécessitent une grande cohérence et rigueur.
Dans ce notebook, je présente tour à tour les étapes de construction d’un pipeline simple de traitement transofrmation, traitement de données.
Importation des librairies#
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler, MaxAbsScaler
from sklearn.linear_model import SGDClassifier
import seaborn as sns
from sklearn.impute import KNNImputer,SimpleImputer
from sklearn.preprocessing import (LabelEncoder, OrdinalEncoder, OneHotEncoder,
LabelBinarizer, MultiLabelBinarizer)
from sklearn.compose import make_column_transformer
from sklearn.compose import make_column_selector
Separation des types de variables#
numeric = make_column_selector(dtype_include=np.number)
categorical = make_column_selector(dtype_exclude=np.number)
Definition des transformer pour chaque type de variable#
pipe_numeric = make_pipeline(SimpleImputer(),
StandardScaler())
pipeline_cat = make_pipeline(SimpleImputer(strategy='most_frequent'),
OneHotEncoder())
Application des transformers sur chaque type de variable#
transformer_app = make_column_transformer(
(pipe_numeric, numeric),
(pipeline_cat, categorical)
)
Creation du pipeline#
traitement = make_pipeline(
transformer_app
)
Application a un jeu de données#
Vous pouvez utiliser n’importe quel jeu de données.
df = pd.read_csv('tips.csv')
y = df['total_bill']
X = df.drop('total_bill', axis=1)
traitement.fit(X, y)
Pipeline(steps=[('columntransformer',
ColumnTransformer(transformers=[('pipeline-1',
Pipeline(steps=[('simpleimputer',
SimpleImputer()),
('standardscaler',
StandardScaler())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x00000172520E1BB0>),
('pipeline-2',
Pipeline(steps=[('simpleimputer',
SimpleImputer(strategy='most_frequent')),
('onehotencoder',
OneHotEncoder())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x0000017264881670>)]))])In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
Pipeline(steps=[('columntransformer',
ColumnTransformer(transformers=[('pipeline-1',
Pipeline(steps=[('simpleimputer',
SimpleImputer()),
('standardscaler',
StandardScaler())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x00000172520E1BB0>),
('pipeline-2',
Pipeline(steps=[('simpleimputer',
SimpleImputer(strategy='most_frequent')),
('onehotencoder',
OneHotEncoder())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x0000017264881670>)]))])ColumnTransformer(transformers=[('pipeline-1',
Pipeline(steps=[('simpleimputer',
SimpleImputer()),
('standardscaler',
StandardScaler())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x00000172520E1BB0>),
('pipeline-2',
Pipeline(steps=[('simpleimputer',
SimpleImputer(strategy='most_frequent')),
('onehotencoder',
OneHotEncoder())]),
<sklearn.compose._column_transformer.make_column_selector object at 0x0000017264881670>)])<sklearn.compose._column_transformer.make_column_selector object at 0x00000172520E1BB0>
SimpleImputer()
StandardScaler()
<sklearn.compose._column_transformer.make_column_selector object at 0x0000017264881670>
SimpleImputer(strategy='most_frequent')
OneHotEncoder()
Data viz avec plotly#
# Librairies
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
Bar plot empilées#
import plotly.graph_objects as go
# Données factices (chaque valeur est en pourcentage, donc entre 0 et 100)
years = ["2014", "2015", "2016", "2017", "2018", "2019"]
seed_angel = [60, 58, 55, 50, 40, 30]
series_a = [20, 25, 30, 35, 30, 25]
series_b = [10, 8, 7, 6, 5, 10]
series_c = [5, 5, 4, 5, 10, 15]
series_d = [3, 2, 3, 2, 5, 8]
series_e_plus = [1, 1, 1, 2, 5, 8]
other = [1, 1, 0, 0, 5, 4]
# Création du graphique avec des barres empilées
fig = go.Figure()
# Ajout des barres pour chaque étape de financement
fig.add_trace(go.Bar(name='Seed / Angel', x=years, y=[v/100 for v in seed_angel], marker_color='#4CAFDB'))
fig.add_trace(go.Bar(name='Series A', x=years, y=[v/100 for v in series_a], marker_color='#B53FA1'))
fig.add_trace(go.Bar(name='Series B', x=years, y=[v/100 for v in series_b], marker_color='#FF5C38'))
fig.add_trace(go.Bar(name='Series C', x=years, y=[v/100 for v in series_c], marker_color='#264277'))
fig.add_trace(go.Bar(name='Series D', x=years, y=[v/100 for v in series_d], marker_color='#15B399'))
fig.add_trace(go.Bar(name='Series E+', x=years, y=[v/100 for v in series_e_plus], marker_color='#F2935A'))
fig.add_trace(go.Bar(name='Other', x=years, y=[v/100 for v in other], marker_color='#D3D3D3'))
# Paramètres de mise en forme pour le mode sombre
fig.update_layout(
barmode='stack',
title="Part des transactions par niveau",
xaxis_title="Années",
yaxis_title="Pourcentage",
yaxis=dict(tickformat=".0%", range=[0, 1]), # Mise à jour de l'axe pour un affichage correct en pourcentage
legend_title="Niveau de financement",
template="plotly_dark", # Mode sombre
width=700, # Largeur du graphique
height=500 # Hauteur du graphique
)
# Affichage du graphique
fig.show()
Barplot#
# Données
data = pd.DataFrame({
'categorie': ['A', 'B', 'A', 'C', 'B', 'A', 'A', 'B', 'C', 'A', 'B', 'C', 'B', 'A', 'C']
})
# Calcul de la fréquence et des pourcentages
frequences = data['categorie'].value_counts(normalize=True) * 100
# On replace les noms des colonnes
frequences_df = frequences.reset_index()
# On récupère les noms des colonnes
frequences_df.columns = ['categorie', 'pourcentage']
# Création du graphique en barres
fig = px.bar(frequences_df, x='categorie', y='pourcentage', text='pourcentage')
# Etiquettes de pourcentage
fig.update_traces(texttemplate='%{text:.2f}%', textposition='outside', width=0.5)
# Affichage du graphique
fig.update_layout(
title="Répartition des catégories",
xaxis_title="Catégorie",
yaxis_title="Pourcentage",
yaxis_tickformat = ",.2f",
showlegend=False
)
# Afichage
fig.show()
# Données
data = pd.DataFrame({
'annee': ['2017', '2018', '2019', '2020', '2021', '2022'],
'PIB': [2500, 2650, 2800, 2900, 3050, 3200]
})
# Graphique en barres
fig = px.bar(data, x='annee', y='PIB', text='PIB', color_discrete_sequence=['#003DA5'])
# Personnalisation des étiquettes
fig.update_traces(
texttemplate='%{text:.0f} M$', # Format des étiquettes en millions de dollars
textposition='outside', # Position au milieu des barres
textfont=dict(color="black"), # Couleur blanche pour les étiquettes
width=0.6
)
# Configuration du layout pour le graphique
fig.update_layout(
title="Évolution du PIB en millions de dollars (2017-2022)",
xaxis_title="Année",
yaxis_title="PIB (millions de dollars)",
yaxis_tickformat=",.0f",
showlegend=False
)
fig.show()
Graphes avec deux axes#
# Données (précipitations, températures minimales et maximales pour chaque mois)
months = ["Jan", "Fév", "Mar", "Avr", "Mai", "Juin", "Juil", "Août", "Sept", "Oct", "Nov", "Déc"]
precipitation = [110, 100, 90, 75, 60, 50, 50, 60, 70, 90, 100, 120] # en mm
temp_min = [20, 18, 16, 14, 11, 8, 7, 9, 12, 15, 18, 20] # en °C
temp_max = [30, 28, 26, 23, 20, 18, 17, 20, 23, 26, 28, 30] # en °C
# Création du graphique à barres pour les précipitations
fig = go.Figure()
fig.add_trace(go.Bar(
x=months,
y=precipitation,
name="Précipitations",
marker_color="green",
yaxis="y2" # On associe l'axe des ordonnées secondaire pour les précipitations
))
# Ajout de la courbe des températures minimales
fig.add_trace(go.Scatter(
x=months,
y=temp_min,
name="Température Min",
mode="lines+markers",
marker_color="blue",
line=dict(width=2)
))
# Courbe pour des températures maximales
fig.add_trace(go.Scatter(
x=months,
y=temp_max,
name="Température Max",
mode="lines+markers",
marker_color="red",
line=dict(width=2)
))
# Mise en forme
fig.update_layout(
title="Graphique climatique",
xaxis=dict(title="Mois"),
yaxis=dict(
title="Température (°C)",
range=[0, 35]
),
yaxis2=dict(
title="Précipitations (mm)",
range=[0, 175],
overlaying="y",
side="right" # Positionne cet axe à droite
),
legend=dict(x=0.1, y=1.1),
template="plotly_white"
)
# Affichage
fig.show()
Graphe à barres empilées vertical#
# Données fictives
data = pd.DataFrame({
'Niveau d\'instruction': ['Primaire', 'Primaire', 'Secondaire', 'Secondaire', 'Supérieur', 'Supérieur'],
'Situation matrimoniale': ['Célibataire', 'Marié', 'Célibataire', 'Marié', 'Célibataire', 'Marié'],
'Nombre': [10, 20, 15, 25, 30, 10]
})
# Calcule des pourcentages
data['Pourcentage'] = (data['Nombre'] / data.groupby('Niveau d\'instruction')['Nombre'].transform('sum') * 100).round(2)
# Création du graphique à barres empilées
fig = px.bar(data,
x='Niveau d\'instruction',
y='Pourcentage',
color='Situation matrimoniale',
text='Pourcentage', # Pourcentages sur les barres
title='Niveau d\'Instruction et Situation Matrimoniale',
labels={'Pourcentage': 'Pourcentage (%)'},
color_discrete_sequence=['#4CAF50', '#2196F3']) # Couleurs
# Personnalisation
fig.update_traces(
texttemplate='%{text:.2f}%', # Format des étiquettes
textposition='inside', # Pourcentages à l'intérieur des barres
textfont_color='white', # Couleur des pourcentages
width=0.4 # Largeur des barres réduite
)
# Configuration du layout pour le graphique
fig.update_layout(
yaxis_title='Pourcentage (%)',
xaxis_title='Niveau d\'instruction',
barmode='stack', # pour empiler
template='plotly_white',
yaxis=dict(gridcolor='LightGray'), # Couleur de la grille
xaxis=dict(gridcolor='LightGray') # Couleur de la grille
)
# Affichage
fig.show()
Graphe à barres groupées#
# Données
data = pd.DataFrame({
'Niveau d\'instruction': ['Primaire', 'Primaire', 'Secondaire', 'Secondaire', 'Supérieur', 'Supérieur'],
'Situation matrimoniale': ['Célibataire', 'Marié', 'Célibataire', 'Marié', 'Célibataire', 'Marié'],
'Nombre': [10, 20, 15, 25, 30, 10]
})
# Calculer des pourcentages
data['Pourcentage'] = (data['Nombre'] / data.groupby('Niveau d\'instruction')['Nombre'].transform('sum') * 100).round(2)
# Graphique à barres groupées
fig = px.bar(data,
x='Niveau d\'instruction',
y='Pourcentage',
color='Situation matrimoniale',
text='Pourcentage',
title='Niveau d\'Instruction et Situation Matrimoniale',
labels={'Pourcentage': 'Pourcentage (%)'},
color_discrete_sequence=px.colors.qualitative.Set2)
# Personnalisation
fig.update_traces(
texttemplate='%{text:.2f}%', # Format des étiquettes en pourcentage avec deux chiffres après la virgule
textposition='outside', # Pourcentages à l'extérieur des barres
width=0.4
)
# Ici tu peux aussi configurer la taille du graphique
fig.update_layout(
yaxis_title='Pourcentage (%)',
xaxis_title='Niveau d\'instruction',
barmode='group', # Utilisation du mode groupé
template='plotly_white'
)
# Affichage
fig.show()
Graphe à barres empilées horizontal#
# Données
data = pd.DataFrame({
'Niveau d\'instruction': ['Primaire', 'Primaire', 'Secondaire', 'Secondaire', 'Supérieur', 'Supérieur', 'Doctorat', 'Doctorat'],
'Situation matrimoniale': ['Célibataire', 'Marié', 'Célibataire', 'Marié', 'Célibataire', 'Marié', 'Célibataire', 'Marié'],
'Nombre': [10, 20, 15, 25, 30, 10, 5, 5]
})
# Calcule des pourcentages
data['Pourcentage'] = (data['Nombre'] / data.groupby('Niveau d\'instruction')['Nombre'].transform('sum') * 100).round(2)
# Graphique à barres empilées horizontal
fig = px.bar(data,
y='Niveau d\'instruction',
x='Pourcentage',
color='Situation matrimoniale',
text='Pourcentage', # Afficher les pourcentages sur les barres
title='Répartition en Pourcentage par Niveau d\'Instruction et Situation Matrimoniale',
labels={'Pourcentage': 'Pourcentage (%)'},
color_discrete_sequence=['purple', '#2196F3'], # Couleurs personnalisées : rose et bleu
orientation='h') # Orientation horizontale
# Personnalisation des étiquettes
fig.update_traces(
texttemplate='%{text:.2f}%', # Format des étiquettes en pourcentage
textposition='inside', # Pourcentages à l'intérieur des barres
textfont_color='white' # Couleur des pourcentages en blanc
)
# Configuration du layout
fig.update_layout(
xaxis_title='Pourcentage (%)',
yaxis_title='Niveau d\'instruction',
barmode='stack', # Utilisation du mode empilé
template='plotly_white'
)
# Affichage
fig.show()
Histogramme#
# Revenus (en milliers de dollars)
np.random.seed(42)
data = pd.DataFrame({
'revenu': np.random.normal(50, 15, 1000) # Moyenne de 50k, écart-type de 15k
})
# Création de l'histogramme
fig = px.histogram(data, x='revenu', nbins=30, # nombre de barres
title="Distribution des revenus",
labels={'revenu': "Revenu (en milliers de dollars)"})
# Personnalisation de l'histogramme
fig.update_layout(
xaxis_title="Revenu (en milliers de dollars)",
yaxis_title="Fréquence",
bargap=0.1, # Espace entre les barres
template="plotly_white" # Fond blanc
)
# Affichage
fig.show()
Box-plot#
# Données
np.random.seed(42)
data = pd.DataFrame({
'revenu': np.random.normal(50, 15, 1000) # Moyenne de 50k, écart-type de 15k
})
# Box-plot
fig = px.box(data, y='revenu',
title="Box-plot des revenus individuels",
labels={'revenu': "Revenu (en milliers de dollars)"})
# Personnalisation
fig.update_layout(
yaxis_title="Revenu (en milliers de dollars)",
template="plotly_white"
)
# Affichage
fig.show()
# Données
np.random.seed(42) # Pour la reproductibilité
n_observations = 50
# Classes du collège au lycée
classes = ['6ème', '5ème', '4ème', '3ème', 'Seconde', 'Première', 'Terminale']
# DataFrame
data = pd.DataFrame({
'Classe': np.random.choice(classes, n_observations),
'Âge': np.random.randint(11, 19, n_observations) # Âges entre 11 et 18
})
# Création du box plot
fig = px.box(data,
x='Classe',
y='Âge',
title='Âges et Classes des élèves',
labels={'Âge': 'Âge (années)', 'Classe': 'Classe'},
color='Classe', # Coloration par classe
template='plotly_white') # Utilisation d'un template blanc
# Configuration du layout
fig.update_layout(
yaxis_title='Âge (années)',
xaxis_title='Classe'
)
# Affichage
fig.show()
Nuage de points#
# Données
np.random.seed(42) # Pour la reproductibilité
data = pd.DataFrame({
'Age': np.random.randint(20, 60, size=50), # Âge entre 20 et 60 ans
'Revenu': np.random.randint(20000, 100000, size=50), # Revenu entre 20 000 et 100 000
'Situation matrimoniale': np.random.choice(['Célibataire', 'Marié', 'Divorcé'], size=50) # Situation matrimoniale
})
# Création du nuage de points
fig = px.scatter(data,
x='Age',
y='Revenu',
color='Situation matrimoniale', # Couleur en fonction de la situation matrimoniale
size='Revenu', # Taille des points proportionnelle au revenu
hover_name=data.index, # Pour Afficher l'index dans les info-bulles
title='Revenu en fonction de l\'Âge',
labels={'Age': 'Âge (ans)', 'Revenu': 'Revenu (en milliers de dollars)'},
template='plotly_white')
# Affichage
fig.show()
Julien Bidias Assala
Ingénieur Statisticien économiste
Contacts :
LinkedIn
GitHub
Gmail