Transformation de la cible pour la régression linéaire

Machine LearningMachine LearningBeginner
Pratiquer maintenant

This tutorial is from open-source community. Access the source code

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, nous allons apprendre à utiliser le TransformedTargetRegressor de la bibliothèque scikit-learn. Nous l'appliquerons à deux jeux de données différents pour observer les avantages de la transformation des valeurs cibles avant la formation d'un modèle de régression linéaire. Nous utiliserons des données synthétiques et l'ensemble de données sur les logements d'Ames pour illustrer l'impact de la transformation des valeurs cibles.

Conseils sur la machine virtuelle

Une fois le démarrage de la machine virtuelle terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Carnet de notes pour accéder au carnet Jupyter pour pratiquer.

Parfois, vous devrez peut-être attendre quelques secondes pour que le carnet Jupyter ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du carnet Jupyter.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/linear_model("Linear Models") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/preprocessing("Preprocessing and Normalization") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/metrics("Metrics") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/compose("Composite Estimators") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/linear_model -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} sklearn/preprocessing -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} sklearn/model_selection -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} sklearn/metrics -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} sklearn/compose -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} sklearn/datasets -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} ml/sklearn -.-> lab-49321{{"Transformation de la cible pour la régression linéaire"}} end

Importez les bibliothèques nécessaires et chargez des données synthétiques

Nous commençons par importer les bibliothèques nécessaires et charger des données synthétiques. Nous générons un ensemble de données de régression aléatoire synthétique et modifions les cibles en translatant toutes les cibles de manière à ce que toutes les entrées soient non négatives et en appliquant une fonction exponentielle pour obtenir des cibles non linéaires qui ne peuvent pas être ajustées à l'aide d'un modèle linéaire simple. Nous utilisons ensuite une fonction logarithmique (np.log1p) et une fonction exponentielle (np.expm1) pour transformer les cibles avant d'entraîner un modèle de régression linéaire et de l'utiliser pour la prédiction.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.compose import TransformedTargetRegressor
from sklearn.linear_model import RidgeCV
from sklearn.metrics import median_absolute_error, r2_score, PredictionErrorDisplay

## Générez des données synthétiques
X, y = make_regression(n_samples=10_000, noise=100, random_state=0)

## Modifiez les cibles
y = np.expm1((y + abs(y.min())) / 200)
y_trans = np.log1p(y)

Tracez les distributions des cibles

Nous traçons les fonctions de densité de probabilité de la cible avant et après avoir appliqué les fonctions logarithmiques.

f, (ax0, ax1) = plt.subplots(1, 2)

ax0.hist(y, bins=100, density=True)
ax0.set_xlim([0, 2000])
ax0.set_ylabel("Probabilité")
ax0.set_xlabel("Cible")
ax0.set_title("Distribution de la cible")

ax1.hist(y_trans, bins=100, density=True)
ax1.set_ylabel("Probabilité")
ax1.set_xlabel("Cible")
ax1.set_title("Distribution de la cible transformée")

f.suptitle("Données synthétiques", y=1.05)
plt.tight_layout()

Entraînez et évaluez un modèle de régression linéaire sur les cibles originales

Nous entraînons et évaluons un modèle de régression linéaire sur les cibles originales. En raison de la non linéarité, le modèle entraîné ne sera pas précis lors de la prédiction.

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

ridge_cv = RidgeCV().fit(X_train, y_train)
y_pred_ridge = ridge_cv.predict(X_test)

score = {
    "R2": f"{r2_score(y_test, y_pred_ridge):.3f}",
    "MedAE": f"{median_absolute_error(y_test, y_pred_ridge):.3f}",
}

print("Régression linéaire sur les cibles originales:")
for key, val in score.items():
    print(f"{key}: {val}")

Entraînez et évaluez un modèle de régression linéaire sur les cibles transformées

Nous entraînons et évaluons un modèle de régression linéaire sur les cibles transformées en utilisant TransformedTargetRegressor. La fonction logarithmique linearise les cibles, permettant une meilleure prédiction même avec un modèle linéaire similaire, comme le montre l'erreur absolue médiane (MedAE).

ridge_cv_with_trans_target = TransformedTargetRegressor(
    regressor=RidgeCV(), func=np.log1p, inverse_func=np.expm1
).fit(X_train, y_train)
y_pred_ridge_with_trans_target = ridge_cv_with_trans_target.predict(X_test)

score = {
    "R2": f"{r2_score(y_test, y_pred_ridge_with_trans_target):.3f}",
    "MedAE": f"{median_absolute_error(y_test, y_pred_ridge_with_trans_target):.3f}",
}

print("\nRégression linéaire sur les cibles transformées:")
for key, val in score.items():
    print(f"{key}: {val}")

Tracez les valeurs réelles versus les valeurs prédites pour les deux modèles

Nous traçons les valeurs réelles versus les valeurs prédites pour les deux modèles et ajoutons le score dans la légende de chaque axe.

f, (ax0, ax1) = plt.subplots(1, 2, sharey=True)

PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge,
    kind="actual_vs_predicted",
    ax=ax0,
    scatter_kwargs={"alpha": 0.5},
)
PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge_with_trans_target,
    kind="actual_vs_predicted",
    ax=ax1,
    scatter_kwargs={"alpha": 0.5},
)

for ax, y_pred in zip([ax0, ax1], [y_pred_ridge, y_pred_ridge_with_trans_target]):
    for name, score in score.items():
        ax.plot([], [], " ", label=f"{name}={score}")
    ax.legend(loc="upper left")

ax0.set_title("Régression Ridge \n sans transformation de la cible")
ax1.set_title("Régression Ridge \n avec transformation de la cible")
f.suptitle("Données synthétiques", y=1.05)
plt.tight_layout()

Chargez et prétraitez les données sur le logement d'Ames

Nous chargeons l'ensemble de données sur le logement d'Ames et le prétraitons en ne conservant que les colonnes numériques et en supprimant les colonnes avec des valeurs NaN ou Inf. La cible à prédire est le prix de vente de chaque maison.

from sklearn.datasets import fetch_openml
from sklearn.preprocessing import quantile_transform

ames = fetch_openml(name="house_prices", as_frame=True, parser="pandas")

## Conservez seulement les colonnes numériques
X = ames.data.select_dtypes(np.number)

## Supprimez les colonnes avec des valeurs NaN ou Inf
X = X.drop(columns=["LotFrontage", "GarageYrBlt", "MasVnrArea"])

## Rendez le prix en k$
y = ames.target / 1000
y_trans = quantile_transform(
    y.to_frame(), n_quantiles=900, output_distribution="normal", copy=True
).squeeze()

Tracez les distributions de la cible pour les données sur le logement d'Ames

Nous traçons les fonctions de densité de probabilité de la cible avant et après l'application du QuantileTransformer.

f, (ax0, ax1) = plt.subplots(1, 2)

ax0.hist(y, bins=100, density=True)
ax0.set_ylabel("Probabilité")
ax0.set_xlabel("Cible")
ax0.set_title("Distribution de la cible")

ax1.hist(y_trans, bins=100, density=True)
ax1.set_ylabel("Probabilité")
ax1.set_xlabel("Cible")
ax1.set_title("Distribution de la cible transformée")

f.suptitle("Données sur le logement d'Ames: prix de vente", y=1.05)
plt.tight_layout()

Entraînez et évaluez un modèle de régression linéaire sur les cibles originales pour les données sur le logement d'Ames

Nous entraînons et évaluons un modèle de régression linéaire sur les cibles originales pour les données sur le logement d'Ames.

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)

ridge_cv = RidgeCV().fit(X_train, y_train)
y_pred_ridge = ridge_cv.predict(X_test)

score = {
    "R2": f"{r2_score(y_test, y_pred_ridge):.3f}",
    "MedAE": f"{median_absolute_error(y_test, y_pred_ridge):.3f}",
}

print("\nRégression linéaire sur les cibles originales:")
for key, val in score.items():
    print(f"{key}: {val}")

Entraînez et évaluez un modèle de régression linéaire sur les cibles transformées pour les données sur le logement d'Ames

Nous entraînons et évaluons un modèle de régression linéaire sur les cibles transformées en utilisant TransformedTargetRegressor pour les données sur le logement d'Ames.

ridge_cv_with_trans_target = TransformedTargetRegressor(
    regressor=RidgeCV(),
    transformer=QuantileTransformer(n_quantiles=900, output_distribution="normal"),
).fit(X_train, y_train)
y_pred_ridge_with_trans_target = ridge_cv_with_trans_target.predict(X_test)

score = {
    "R2": f"{r2_score(y_test, y_pred_ridge_with_trans_target):.3f}",
    "MedAE": f"{median_absolute_error(y_test, y_pred_ridge_with_trans_target):.3f}",
}

print("\nRégression linéaire sur les cibles transformées:")
for key, val in score.items():
    print(f"{key}: {val}")

Tracez les valeurs réelles contre les valeurs prédites et les résidus contre les valeurs prédites pour les deux modèles

Nous traçons les valeurs réelles contre les valeurs prédites et les résidus contre les valeurs prédites pour les deux modèles et ajoutons le score dans la légende de chaque axe.

f, (ax0, ax1) = plt.subplots(2, 2, sharey="row", figsize=(6.5, 8))

PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge,
    kind="actual_vs_predicted",
    ax=ax0[0],
    scatter_kwargs={"alpha": 0.5},
)
PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge_with_trans_target,
    kind="actual_vs_predicted",
    ax=ax0[1],
    scatter_kwargs={"alpha": 0.5},
)

for ax, y_pred in zip([ax0[0], ax0[1]], [y_pred_ridge, y_pred_ridge_with_trans_target]):
    for name, score in score.items():
        ax.plot([], [], " ", label=f"{name}={score}")
    ax.legend(loc="upper left")

ax0[0].set_title("Régression Ridge \n sans transformation de la cible")
ax0[1].set_title("Régression Ridge \n avec transformation de la cible")

PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge,
    kind="residual_vs_predicted",
    ax=ax1[0],
    scatter_kwargs={"alpha": 0.5},
)
PredictionErrorDisplay.from_predictions(
    y_test,
    y_pred_ridge_with_trans_target,
    kind="residual_vs_predicted",
    ax=ax1[1],
    scatter_kwargs={"alpha": 0.5},
)
ax1[0].set_title("Régression Ridge \n sans transformation de la cible")
ax1[1].set_title("Régression Ridge \n avec transformation de la cible")

f.suptitle("Données sur le logement d'Ames: prix de vente", y=1.05)
plt.tight_layout()
plt.show()

Sommaire

Dans ce laboratoire, nous avons appris à utiliser le TransformedTargetRegressor de la bibliothèque scikit - learn. Nous l'avons appliqué à deux jeux de données différents pour observer les avantages de la transformation des valeurs de la cible avant la formation d'un modèle de régression linéaire. Nous avons utilisé des données synthétiques et l'ensemble de données sur le logement d'Ames pour illustrer l'impact de la transformation des valeurs de la cible. Nous avons observé que la fonction logarithmique a linéarisé les cibles, permettant une meilleure prédiction même avec un modèle linéaire similaire, comme le montre l'erreur absolue médiane (MedAE). Nous avons également observé que l'effet du transformateur était moins marqué pour l'ensemble de données sur le logement d'Ames, mais a tout de même entraîné une augmentation de R2 et une forte diminution de l'MedAE.