Nous avons vu précédemment dans cet article comment réaliser une régression linéaire avec un seul facteur. L’étape suivante consiste à réaliser l’entrainement d’un modèle de régression linéaire multiple, toujours avec la librairie Scikit-Learn en Python. Nous introduirons également la notion d’interactions entre les facteurs. Celle-ci n’est pas forcément prise en compte dans les modèles de régression classique.
En effet, les différents systèmes réels comportent dans la majeure partie du temps plusieurs facteurs. La librairie Scikit-Learn en Python propose des outils de régression linéaire pour plusieurs facteurs. Dans cet article, nous allons ensemble voir la méthode pas à pas avec un exemple concret.

Etape 1 : Importer les librairies utiles pour la régression linéaire multi facteurs
Tout comme pour la régression linéaire à un seul facteur, nous allons importer les librairies qui nous serviront à étudier notre système.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import max_error, mean_absolute_error
PythonLes deux premières librairies, Numpy et Pandas, permettent de manipuler les données. La suivante, Matplotlib permet de visualiser les données et les résultats. Voici un article qui la présente si vous ne la connaissez pas.
Les lignes suivantes concernent les modules de la librairie Scikit-Learn. Pipeline est un module qui permet de réaliser plusieurs étapes de pré-traitement sur les données avant de réaliser l’entrainement du modèle. PolynomialFeatures est un module permet d’introduire automatiquement les interactions entre les facteurs dans le modèle. Le module LinearRegression, comme son nom l’indique, est le modèle de régression linéaire.
Enfin, on trouve également le module train_test_split pour diviser le jeu de données en deux sets distincts. Le premier servira à entrainer le modèle et le second à le tester. Les modules max_error et mean_absolute_error seront utilisés pour mesurer la performance du modèle.
Etape 2 : Préparer des données pour la régression linéaire multiple avec Scikit-Learn
Une fois que les librairies sont toutes importées, nous allons pouvoir commencer à travailler sur les données. L’exemple présenté ici consiste à prédire le prix d’un appartement en fonction de ses caractéristiques. La première chose à faire est de créer le jeu de données. Pour réaliser cela, un dictionnaire est crée avec toutes les données. Celui-ci sera donné comme donnée d’entrée pour généré un tableau structuré avec la librairie Pandas.
# Exemple de données
data = {
'superficie': [120, 85, 100, 150, 95, 130, 100, 75, 110, 90],
'chambres': [3, 2, 2, 4, 2, 3, 2, 1, 3, 2],
'transport': [1, 0, 1, 1, 0, 1, 0, 1, 1, 0],
'prix': [300000, 200000, 250000, 400000, 220000, 350000, 240000, 180000, 280000, 210000]
}
# Création du DataFrame
df = pd.DataFrame(data)
# Diviser les données en variables indépendantes (X) et dépendantes (y)
X = df[['superficie', 'chambres', 'transport']]
y = df['prix']
PythonLes facteurs du système sont la superficie, le nombre de chambre et la proximité des transports. A partir du tableau structuré, les données des facteurs sont affectées à la variable X. La réponse du système est ici le prix. Il est affecté à la variable y.
Etape 3 : Entrainement du modèle de régression linéaire multiple en Python
Dans un problème de régression linéaire multiple en python, il n’est pas rare d’avoir des interactions fortes entre les variables. Ainsi, il est donc nécessaire de les prendre en compte pour l’entrainement du modèle. Vous pourriez alors créer de nouvelles colonnes dans la matrice des facteurs pour prendre en compte ces interactions. Sinon, avec le module PolynomialFeatures de la librairie Scikit-Learn, vous pouvez facilement et automatiquement déterminer le degré de la régression linéaire. Celui-ci se fait par l’argument degree.
Ensuite, un second argument est disponible avec le module PolynomialFeatures. Il s’agit de interaction_only. Sa valeur par défaut est False. Avec cette valeur, vous aurez alors toutes les interactions à l’ordre indiqué dans l’argument degree ainsi que les facteurs au degré indiqué. Par exemple, si vous donnez comme argument degree=2 et interaction_only=False, vous aurez dans votre modèle les interactions d’ordre 2 (X1X2, X1X3, …) ainsi que les termes quadratiques des facteurs (X1², X2², …). En changeant la valeur de interaction_only à True, seules les interactions sont conservées. Vous n’aurez donc pas les termes quadratiques.
# Création du modèle
model = Pipeline([
('poly', PolynomialFeatures(degree=2,interaction_only=True)),
('linear', LinearRegression(fit_intercept=False))
])
# Entrainement du modèle
model.fit(X_train, y_train)
PythonUne fois le modèle défini avec les opérations de pré-traitement, l’entrainement est lancé avec la commande fit. L’entrainement est réalisé sur les données d’entrainement (avec le suffixe _train).
Etape 4 : Validation de la performance du modèle
Le modèle est maintenant prêt. Il peut donc être utilisé pour réaliser les prédictions de prix. Pour réaliser cette étape, nous utiliserons donc le jeu de test pour estimer la performance du modèle.
# Faire des prédictions sur l'ensemble de test
y_pred = model.predict(X_test)
y_pred_train = model.predict(X_train)
# Évaluation du modèle
mae_train = mean_absolute_error(y_train, y_pred_train)
mae_test = mean_absolute_error(y_test, y_pred)
r2_train = model.score(X_train, y_train)
r2_test = r2_score(y_test, y_pred)
print(f"MAE Train : {mae_train:.0f}")
print(f"MAE Test : {mae_test:.0f}")
print(f"R² Train : {r2_train:.4f}")
print(f"R² Test : {r2_test:.2f}")
PythonMAE Train : 1156
MAE Test : 18575
R² Train : 0.9995
R² Test : 0.70
PythonDeux constats peuvent être faits de ces résultats. Tout d’abord, le modèle est excellent sur les données d’entrainement. Le coefficient R² est très proche de 1. De plus, l’erreur moyenne est de l’ordre de 1000€. Cela représente environ 0.5% de la moyenne des prix des appartements.
Ensuite, le second constat est le suivant. Le modèle est tout de suite beaucoup moins fiable sur les données de test. Le coefficient R² descend à 70% et l’erreur moyenne du modèle est de quasiment 20.000€. Cette somme représente environ 7% de la moyenne des prix des appartements. C’est pour cela qu’il est très important de bien séparer les données d’entrainements des données de test. C’est en travaillant sur des données indépendantes qu’il est possible de mesurer correctement la performance d’un modèle de régression.
Performance de la prédiction sur les données disponibles
Afin de visualiser la performance du modèle, un graphe simple mais efficace est créer dans un premier temps. Il s’agit d’une droite d’équation y = x où x sont les données réelles et y la réponse prédite. Avec cette droite, nous affichons également un nuage de points où comme dit précédemment, nous avons les données réelles en abscisse et les données prédites en ordonnées. Pour analyser ce graphique, si un point tombe sur la droite c’est que le modèle prédit parfaitement la réponse. Si un écart est visible, la distance entre les deux représente l’erreur.
plt.scatter(y_train, y_pred_train, c="blue", label="Données d'entrainement")
plt.scatter(y_test, y_pred, c="orange", label="Données de test")
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'k--', lw=1)
plt.xlabel('Prix réel')
plt.ylabel('Prix prédit')
plt.title('Prédictions des prix')
plt.legend()
plt.show()
Python
On retrouve visuellement que le modèle est excellent pour prédire le prix de l’appartement sur les données d’entrainement. La conclusion n’est pas la même sur les données de test où l’erreur est bien plus conséquente.
Etape 5 : Visualisation des résultats de la régression linéaire multiple en Python
Et enfin, pour finaliser notre étude, la visualisation graphique permet d’interpréter les résultats d’une autre manière. La répartition des données et les tendances sur les graphiques permettent de sentir le comportement des données. Cette analyse s’ajoute à l’étape précédente pour la validation du modèle. Cette étape nécessite tout d’abord une préparation des données. Viendra ensuite la visualisation à proprement dit.
Préparation des données pour la visualisation
Le but de cette étape est donc de construire la base de données qui sera utilisées pour visualiser le modèle via ses prédictions. Voici un exemple de code permettant de préparer les données pour la prédiction.
# Valeur fixe pour le facteur "transport"
fixed_transport_value = 1
# Plages pour les facteurs "superficie" et "chambres"
superficie_range = np.linspace(df['superficie'].min(), df['superficie'].max(), 20)
chambres_range = np.linspace(df['chambres'].min(), df['chambres'].max(), 20)
# Création de la grille des facteurs pour la surface de réponse
superficie_grid, chambres_grid = np.meshgrid(superficie_range, chambres_range)
transport_grid = np.full_like(superficie_grid, fixed_transport_value)
# Préparation des données pour la prédiction
data_surface = pd.DataFrame({'superficie': superficie_grid.flatten(),
'chambres': chambres_grid.flatten(),
'transport': transport_grid.flatten()})
# Prédiction des prix pour la surface de réponse
prices_surface = model.predict(data_surface)
PythonComme nous allons construire une surface de réponse, il faut donc choisir deux paramètres et en fixer un. Ici, nous fixerons le paramètre sur la proximité des transports qui sera égal à un.
Ensuite, pour créer une surface de réponse, nous avons besoin d’une répartition 2D des paramètres, en d’autres termes une grille avec la valeur de chaque paramètre. Pour réaliser cette opération, nous créons premièrement un vecteur uniformément réparti avec la fonction linspace de la librairie Numpy (je la présente dans cet article). A partir de ces vecteurs, la grille de paramètres est générée via la fonction meshgrid de la même librairie. Ensuite, la fonction full_like permet de créer une matrice de la même forme qu’une autre variable avec une valeur déterminée.
A ce stade nous avons nos grilles 2D avec les valeurs des paramètres linéairement réparties. Pour réaliser les prédictions sur chaque point, nous avons besoin de mettre tout ce petit monde sous forme de colonne (vecteurs) et insérer les informations dans un Dataframe. On appliquera alors la fonction flatten qui permet de réaliser cette opération.
Et enfin, la prédiction peut être faite sur tous les points du domaine d’étude. Place maintenant à la visualisation à proprement parlé.
Création de la visualisation
Maintenant que nous avons toutes nos données dans le bon format, nous allons pouvoir tracer la surface de réponses avec le nuage de points des données réelles.
# Création de la surface de réponse en 3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# ax = fig.add_subplot(111)
ax.scatter(X['superficie'], X['chambres'], y, c='blue', label='Données réelles')
ax.plot_surface(superficie_grid, chambres_grid, prices_surface.reshape(superficie_grid.shape), alpha=0.5, cmap='viridis', label='Surface de réponse')
# ax.contourf(superficie_grid, chambres_grid, prices_surface.reshape(superficie_grid.shape), alpha=0.5, cmap='viridis', label='Surface de réponse')
ax.set_xlabel('Superficie')
ax.set_ylabel('Chambres')
ax.set_zlabel('Prix')
ax.set_title('Surface de réponse')
ax.azim = 100
ax.elev = 20
plt.show()
PythonLà-dessus, pour afficher les données réelles, une visualisation en nuage de points est bien adaptée. La fonction scatter permet de réaliser ceci. Puis l’étape suivante consiste à tracer la surface de réponse. Pour se faire, nous utiliserons la fonction plot_surface avec les grilles 2D déjà créés. Ensuite, il faut redimensionner le vecteur réponse issu du modèle de prédiction. En effet, celui-ci est sous la forme d’une colonne et nous devons retrouver une grille 2D. La fonction reshape avec le format d’une des deux grilles préalablement créé fonctionnera à merveille.

La visualisation des données montre deux choses. La répartition des données n’est pas optimale afin de couvrir tout le domaine d’études. Ensuite, la tendance de la surface de réponse est surprenante quand la superficie est grande mais que le nombre de chambre diminue.
Pour conclure et aller plus loin
Dans cet article, nous avons vu comment mettre en place une régression linéaire avec de multiples facteurs. De plus, la librairie Scikit-Learn nous offre des outils permettant de prendre en compte les interactions entre les facteurs très facilement. Pour plus d’informations sur le pré-traitement des données avec la librairie Scikit-Learn, je vous invite à visiter la rubrique dédiée sur leur site dont voici le lien. Outre la faculté de prendre en compte les interactions, vous pourrez normaliser vos valeurs avec plusieurs méthodes.
Afin d’avoir un modèle performant et fiable, la qualité des données d’entrée est primordiale. Vous devrez donc apporter un soin tout particulier au traitement de celle-ci. En effet, nous avons vu dans l’exemple de cet article que l’étendue des données n’étaient pas suffisante.
Pour terminer cette conclusion, j’attire votre attention sur un thème très important dans l’apprentissage machine qui le sur-apprentissage ou l’overfit. Il y a également le sous-apprentissage ou underfit mais nous verrons cela plus tard. Concernant l’overfit, ce phénomène traduit que le modèle est trop bien entrainé mais qu’il n’est pas capable de prédire certaines variations du système. Dans notre cas, le modèle est vraiment excellent sur les données d’entrainement mais l’erreur sur les données de test est grande. Cela est typique de l’overfit. Néanmoins, dans l’exemple présenté, cela aurait pu être corrigé en modifiant le set d’entrainement et de test mais rien n’est sûr.
Merci de m’avoir lu, n’hésitez pas à laisser un commentaire,
A bientôt,
Benjamin