{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8ccb5f92",
   "metadata": {},
   "source": [
    "# TP Vin ; Un sommelier sans dégustation ; jour 1 · exercices\n",
    "\n",
    "**Mission.** Prédire la note sensorielle `quality` à partir de 11 mesures physico-chimiques de vins blancs. Il s'agit d'une **régression** . Toutes les cellules marquées `TODO` sont à compléter.\n",
    "\n",
    "Source : [UCI Wine Quality](https://archive.ics.uci.edu/dataset/186/wine+quality), licence CC BY 4.0."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "030d9dfc",
   "metadata": {},
   "source": [
    "## 1. Charger et cadrer la prédiction\n",
    "\n",
    "La note provient d'une évaluation sensorielle subjective."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f2185885",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "from tempfile import TemporaryDirectory\n",
    "from joblib import dump, load\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "from IPython.display import display\n",
    "from sklearn.dummy import DummyRegressor\n",
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from sklearn.linear_model import Ridge\n",
    "from sklearn.metrics import mean_absolute_error, r2_score\n",
    "from sklearn.model_selection import GridSearchCV, KFold, cross_validate, train_test_split\n",
    "from sklearn.neighbors import KNeighborsRegressor\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.tree import DecisionTreeRegressor\n",
    "\n",
    "DATA_NAME = \"winequality-white.csv\"\n",
    "data_path = next((candidate for candidate in [Path(\"data\") / DATA_NAME, Path(\"../data\") / DATA_NAME] if candidate.exists()), None)\n",
    "assert data_path is not None, \"CSV absent : placer le dossier data à la racine du projet\"\n",
    "df = pd.read_csv(data_path, sep=\";\")\n",
    "print(\"Dimensions :\", df.shape)\n",
    "display(df.head())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "394ceea5",
   "metadata": {},
   "source": [
    "**À faire.** Examiner la distribution des notes et les valeurs manquantes. Quelle erreur ferait un modèle qui prédit toujours la note moyenne ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77c1665f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3728d333",
   "metadata": {},
   "source": [
    "**À faire.** Mettre les 11 mesures dans `X`, la note dans `y`, et réserver 20 % des lignes pour le test (`random_state=42`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89edfb24",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "897c3855",
   "metadata": {},
   "source": [
    "## 2. Premières précautions\n",
    "\n",
    "Bien choisir sa métrique, et faire attention à l'overfitting\n",
    "\n",
    "Une note prévue à 6 au lieu de 7 n'est pas la même erreur qu'une note prévue à 3 au lieu de 7. Nous utilisons l'erreur absolue moyenne (MAE) et `R²`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e97fdd1",
   "metadata": {},
   "source": [
    "**À faire.** Entraîner une baseline qui prédit la moyenne et un arbre sans limite. Comparer MAE d'entraînement et MAE de validation interne. Quelle erreur révèle l'arbre ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e88713bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ad827b8",
   "metadata": {},
   "source": [
    "## 3. Validation croisée et panorama des modèles"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4e1a400",
   "metadata": {},
   "source": [
    "**À faire.** Comparer moyenne, Ridge, k-NN et arbre sur les mêmes cinq plis. Afficher MAE moyenne, écart-type et `R²`. La normalisation des modèles sensibles aux échelles doit rester **dans** le pipeline."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38af3d2c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad0047b9",
   "metadata": {},
   "source": [
    "**À faire.** Mesurer la variation du score d'un Ridge sur trois découpages simples (faire varier la graine du random_state). Pourquoi préfère-t-on la validation croisée pour comparer les modèles ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f6294278",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0978eae6",
   "metadata": {},
   "source": [
    "## 4. Régularisation et complexité"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1169bffa",
   "metadata": {},
   "source": [
    "**À faire.** Faire varier `max_depth` de l'arbre ; comparer MAE d'entraînement et de validation croisée. Tracer les deux courbes. Ici, une profondeur excessive mémorise-t-elle les notes ?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ea760b96",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3281df9",
   "metadata": {},
   "source": [
    "**À faire.** Rechercher le coefficient `alpha` de Ridge parmi `0.1, 1, 10, 100, 1000`. \n",
    "Si `alpha` est grand, alors la régularisation est plus forte.\n",
    "*(ici on va observer peut de variation)*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b7790996",
   "metadata": {},
   "outputs": [],
   "source": [
    "# TODO : écrire votre solution ici"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5b74427",
   "metadata": {},
   "source": [
    "## Fin du jour 1\n",
    "\n",
    "Conserver vos observations. Le notebook du jour 2 recrée le même découpage et un modèle de référence sans dépendre de l'état Jupyter actuel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a71acd1b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
