{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Practical 1 — A first machine-learning workflow\n",
    "\n",
    "By the end of this practical, you should be able to:\n",
    "\n",
    "- inspect a dataset represented by NumPy arrays;\n",
    "- identify samples, features and targets;\n",
    "- use the scikit-learn `fit` / `predict` / `score` interface;\n",
    "- separate training and test data;\n",
    "- tune $k$ without using the test set for model selection;\n",
    "- explain why feature scaling matters for a distance-based method;\n",
    "- prevent preprocessing leakage with a `Pipeline`;\n",
    "- make a simple experiment reproducible.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import sklearn\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Working environment\n",
    "\n",
    "Before starting Jupyter, activate the course environment in a terminal:\n",
    "\n",
    "```bash\n",
    "source /opt/venv/iti-iml/bin/activate\n",
    "python -m ipykernel install --user --name cours-ml --display-name \"Python (cours-ml)\"\n",
    "```\n",
    "\n",
    "Then select the **Python (cours-ml)** kernel in Jupyter. The kernel installation is normally required only once.\n",
    "\n",
    "Useful references: [installing scikit-learn](https://scikit-learn.org/stable/install.html) and the [scikit-learn user guide](https://scikit-learn.org/stable/user_guide.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python used by the jupyter kernel :  /home/bgauzere/work/Cours/IML/Practical/.venv/bin/python\n"
     ]
    }
   ],
   "source": [
    "import sys\n",
    "# Display the python used by the jupyter kernel \n",
    "print(\"Python used by the jupyter kernel : \", sys.executable)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Scikit-learn 101\n",
    "\n",
    "NumPy represents numerical data using multidimensional arrays. In this practical:\n",
    "\n",
    "- `X` will be a two-dimensional array with shape `(n_samples, n_features)`;\n",
    "- `y` will be a one-dimensional array containing one target per sample.\n",
    "\n",
    "Most supervised scikit-learn estimators share the same interface:\n",
    "\n",
    "1. create an estimator, for example `model = SomeClassifier(...)`;\n",
    "2. learn from examples with `model.fit(X, y)`;\n",
    "3. predict with `model.predict(X)`;\n",
    "4. evaluate predictions with a suitable metric.\n",
    "\n",
    "Scikit-learn also provides some built-in datasets. Browse the available [toy datasets](https://scikit-learn.org/stable/datasets/toy_dataset.html) before continuing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "shape: (2, 3)\n",
      "first sample: [  1.  10. 100.]\n",
      "second feature: [10. 20.]\n",
      "feature means: [  1.5  15.  150. ]\n"
     ]
    }
   ],
   "source": [
    "# NumPy reminder: predict the shape and value of each expression before running it.\n",
    "example = np.array([[1.0, 10.0, 100.0], [2.0, 20.0, 200.0]])\n",
    "\n",
    "print(\"shape:\", example.shape)\n",
    "print(\"first sample:\", example[0])\n",
    "print(\"second feature:\", example[:, 1])\n",
    "print(\"feature means:\", example.mean(axis=0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Load the Wine dataset\n",
    "\n",
    "Read the [`load_wine` documentation](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_wine.html).\n",
    "\n",
    "Load the feature matrix into `X` and the target vector into `y` using `return_X_y=True`. Also load the complete `Bunch` object into `wine`, because it contains feature names, class names and a description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.datasets import load_wine\n",
    "\n",
    "# TODO: create wine, X and y.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'> <class 'numpy.ndarray'>\n",
      ".. _wine_dataset:\n"
     ]
    }
   ],
   "source": [
    "wine = load_wine()\n",
    "X, y = load_wine(return_X_y=True)\n",
    "\n",
    "print(type(X), type(y))\n",
    "print(wine.DESCR.splitlines()[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Understand the data\n",
    "\n",
    "Answer the following questions using array attributes and the dataset metadata.\n",
    "\n",
    "1. How many samples and features are there?\n",
    "2. What does one row represent?\n",
    "3. What are the feature names?\n",
    "4. What does `y` represent, and which values can it take?\n",
    "5. Are the classes balanced?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "# TODO: inspect X.shape, y.shape, wine.feature_names, wine.target_names\n",
    "# and count the samples in each class with np.unique(..., return_counts=True).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "Each row describes one wine sample through 13 positive, real-valued chemical measurements. The target is one of three cultivar classes. The classes are not exactly balanced, although no class is extremely rare."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X shape: (178, 13)\n",
      "y shape: (178,)\n",
      "Features: ['alcohol', 'malic_acid', 'ash', 'alcalinity_of_ash', 'magnesium', 'total_phenols', 'flavanoids', 'nonflavanoid_phenols', 'proanthocyanins', 'color_intensity', 'hue', 'od280/od315_of_diluted_wines', 'proline']\n",
      "Target names: ['class_0' 'class_1' 'class_2']\n",
      "Class counts: {np.int64(0): np.int64(59), np.int64(1): np.int64(71), np.int64(2): np.int64(48)}\n"
     ]
    }
   ],
   "source": [
    "\n",
    "print(f\"X shape: {X.shape}\")\n",
    "print(f\"y shape: {y.shape}\")\n",
    "print(\"Features:\", wine.feature_names)\n",
    "print(\"Target names:\", wine.target_names)\n",
    "\n",
    "classes, counts = np.unique(y, return_counts=True)\n",
    "print(\"Class counts:\", dict(zip(classes, counts)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Visualise feature scales\n",
    "\n",
    "Create a boxplot with one box per feature.\n",
    "\n",
    "Before modelling, note whether all variables have comparable numerical ranges. A boxplot is useful here for comparing scales, but it is not a complete exploration of the dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "# TODO: display a boxplot using Matplotlib and identify each feature.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "The variables have very different magnitudes. For example, `proline` is measured on a much larger numerical scale than several other features. This observation will matter because k-NN compares samples through distances."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [
    {
     "data": {
      "image/png": "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JN1jioiIiIiIiIjoS5aWloaQkJACjU1PT0dYWBgqVaoEPT29D453cHCAvr6+ClJ+OixMERERERERERFJJCQkBA0aNPgkxw4KCoKTk9MnObaqsDBFRERERERERCQRBwcHBAUFFWjs/fv34eXlhW3btqFGjRoFOnZxx8IUEREREREREZFE9PX1Cz2rqUaNGsV+JlRBcfNzIiIiIiIiIiKSBAtTREREREREREQkCRamiIiIiIiIiIhIEixMERERERERERGRJFiYIiIiIiIiIiIiSbAwRUREREREREREkmBhioiIiIiIiIiIJMHCFBERERERERERSYKFKSIiIiIiIiIikgQLU0REREREREREJAkWpoiIiIiIiIiISBIsTBERERERERERkSRYmCIiIiIiIiIiIkmwMEVERERERERERJKQvDB16dIlDBo0CE2bNkVwcHCe/vnz56Np06ZKt/79++cZFxgYiN69e8PV1RWjR49GdHR0kcYQEREREREREdHnIWlhavLkyRgzZgxq1KiBy5cvIzk5Oc+YJ0+eQF9fH0uXLlXcfvrpJ6Uxp06dQuvWrWFvb4+JEyciNDQUzZo1Q0pKSqHGEBERERERERHR5yMTQgipnjwpKQkmJiaIiIiAra0tTp06BVdXV6UxI0aMQFxcHAICAt55nGbNmsHW1ha+vr4AgLS0NNjY2GDq1KkYP358gcd8SHJyMkxMTJCUlARjY+OPeOVERERERERERIUTHByMBg0aICgoCE5OTlLHeafC1E8knTFlYmJSoHFXr16Fm5sbunbtisWLFyMrK0vRl5aWhkuXLsHd3V3Rpq+vj6+//hr//PNPgccQEREREREREdHnJfkeUx+ir68PLy8v/Pzzz/Dw8MAff/yBVq1aITc3FwAQHh4OuVyOsmXLKj2ubNmyePbsWYHH5CczMxPJyclKNyIiIiIiIiIiUg0tqQN8yNy5c6Grq6u437x5czg4OMDf3x99+vRBdnY2ACiNAQA9PT1FX0HGvOu5Z8yYodLXQ0RERERERERE/6fYz5j6bzGpatWqqFSpEm7evAkAMDc3BwAkJCQojYuPj0fp0qULPCY/kyZNQlJSkuIWHh6uoldFRERERERERETFvjD1Xzk5OYiLi4OBgQHwZjmetbU1rl69qjTu8uXLqF+/foHH5EdXVxfGxsZKNyIiIiIiIiIiUo1iXZjKysrCvHnzFJud5+Tk4KeffkJaWhq6d++uGDd48GBs2LABkZGRAIBdu3bh3r17GDx4cKHGEBERERERERHR5yPpHlOHDh3Cb7/9pig8fffddzA2NsbQoUMxdOhQaGtrIzU1FWXLloWNjQ2io6NhamqKffv2oUaNGorjTJ06FaGhoahatSpsbW0RERGBlStXolGjRoUaQ0REREREREREn49MCCGkevKXL1/i8ePHedrLly+P8uXLK+5nZWUhNDQUZmZmsLGxgUwmy/d4UVFRiI2NRdWqVWFkZFTkMe+SnJwMExMTJCUlcVkfEREREREREX1WwcHBaNCgAYKCguDk5CR1nHcqTP1E0hlTlpaWsLS0/OA4HR0dODo6fnBc2bJlUbZs2Y8eQ0REREREREREn16x3mOKiIiIiIiIiIhKLhamiIiIiIiIiIhIEixMERERERERERGRJFiYIiIiIiIiIiIiSbAwRUREREREREREkmBhioiIiIiIiIiIJMHCFBERERERERERSYKFKSIiIiIiIiIikgQLU0REREREREREJAkWpoiIiIiIiIiISBIsTBERERERERERkSRYmCIiIiIiIiIiIkmwMEVERERERERERJJgYYqIiIiIiIiIiCTBwhQREREREREREUmChSkiIiIiIiIiIpIEC1NERERERERERCQJFqaIiIiIiIiIiEgSLEwREREREREREZEkJC1MZWVlwdfXF66urrC2tsaFCxfyjLl37x6GDRsGR0dH1K1bFyNHjkRMTIzSmJ9++gnW1tZKN1dX1zzH2r59O5o0aYJKlSrB3d0dd+7c+aSvj4iIiIiIiIiI3q1IhSkhBDZs2ABnZ2dYWVkp2qdMmYKoqKgCH2fy5MnYs2cPvv32W8TGxiIrK0upPzc3F71790bTpk3h7++PjRs34s6dO2jdujXS09MV45KSktCoUSPcuHFDcdu1a5fSsQICAjBo0CAMGzYMhw4dgoWFBVxdXfHixYuinAIiIiIiIiIiIvpIRSpMrVy5EtOnT0fPnj2VCjuVKlXCrFmzCnycefPmwc/PDy1atMi3X1NTE7du3cKQIUNQs2ZNNGzYEBs3bsS9e/dw+fJlpbG6urpKM6ZKly6t1D9r1iwMHDgQQ4cOhaOjI9avXw8NDQ2sXr260K+fiIiIiIiIiIg+XpELU/7+/hg3bpxSe7t27fLMVHrvk2t8+OllMpnS/czMTACAjo6OUvvp06dRpUoV1K9fH99//z3i4+MVfcnJybh58ybatGmjaNPS0kLr1q0RGBhY4LxERERERERERKQ6RSpMhYWFoV69esB/CkdGRkZITExUXbr/EELg559/RrVq1dCoUSNFu5WVFebOnYujR49i8eLFuHz5Mpo1a6ZY7hcZGakY929WVlbvXXqYmZmJ5ORkpRsREREREREREalGkQpTFSpUwI0bN4D/FKb27t2L6tWrqy7df/z4448IDAyEn58ftLW1Fe3Tp0/HsGHDUK1aNbRq1Qr79+/HkydP4OvrC7wpaOHNLKl/09LSQm5u7jufb+7cuTAxMVHcbG1tP9lrIyIiIiIiIiL60hSpMPX9999j4MCB2Lt3LwDg8uXLmDFjBkaOHIkxY8aoOiPwZmP1tWvX4ujRo4rZWm/9d7mflZUVKlasiPv37wMALC0tAQBxcXFK416+fIkyZcq88zknTZqEpKQkxS08PFyFr4iIiIiIiIiI6MumVYAxeYwePRoZGRkYPHgw5HI5mjZtChMTE8yYMQNDhgxRecipU6di+fLlOHr0KJydnT84Pj09HVFRUbCwsADeFKYqVaqEc+fOoUuXLopxZ8+ehaen5zuPo6urC11dXRW9CiIiIiIiIiIi+rcizZgCgIkTJ+Lly5d4+PAhQkJC8PLlS0yYMEG16QDMmDEDS5cuxdGjR+Hi4pKnPzMzE//73//w/PlzAEBCQgIGDx4MDQ0N9OnTRzFu1KhR2LBhA4KCgpCbm4vFixcjIiIC3377rcozExERERERERHRhxVpxtRbmpqasLe3L/Lj/fz8MGbMGMjlcgBAt27doKOjgwkTJmDChAlISEjA9OnTUapUKXTr1k3psYsXL0a/fv2gq6uLhg0b4uuvv0ZMTAyys7Ph4uKCwMBAVKhQQTF+3LhxiI2NRYsWLSCXy2FpaYmAgAA4ODh8xBkgIiIiIiIiIqKikom3O4MXwr9nIuXn7abjH5Keno6kpKQ87YaGhjA0NIQQArGxsfk+1sTEBHp6ekptqampMDAwyLPn1L/l5OQgJSUFpqam7x2Xn+TkZJiYmCApKQnGxsaFeiwRERERERER0ccIDg5GgwYNEBQUBCcnJ6njvFNh6idFmjFlaGiodF8ulyM0NBTnzp1Dr169CnwcPT29PMWlf5PJZLC2ti5yrvxoaWnBzMyswMckIiIiIiIiIqJPo0iFqQ0bNuTbvnjxYjx48OBjMxERERERERER0Rfgo/aY+q8hQ4agZs2aqjwkERERERERERGVUEW+Kl9+nj9/joyMDFUekoiIiIiIiIiISqgizZiaPn16nrZXr17B398fXbt2VUUuIiIiIiIiIiIq4YpUmPrnn3/ytJmZmeGHH37A6NGjVZGLiIiIiIiIiIhKuCIVps6dO6f6JERERERERERE9EVR6R5TREREREREREREBVXgGVODBg0q8EE3b95c1DxERERERERERPSFKHBhKicn59MmISIiIiIiIiKiL0qBC1Pbtm37tEmIiIiIiIiIiOiLwj2miIiIiIiIiIhIEkW6Kh8AZGZmIigoCM+fP8+zzM/Ly0sV2YiIiIiIiIiIqAQrUmHq7t27cHd3R2xsLNLS0mBiYoKkpCQAgJWVFQtTRERERERERET0QUVayjd27Fh07doVKSkpAIDExEQ8ePAATZo0wdixY1WdkYiIiIiIiIiISqAiFaauXr2KSZMmQUNDAzKZDNnZ2ahWrRo2bdqE1atXqz4lERERERERERGVOEUqTCUmJsLCwgIAYGFhgaioKACAra0tYmJiVJuQiIiIiIiIiIhKpI++Kp+LiwtmzJiBGzduYPLkyXBwcFBNMiIiIiIiIiIiKtGKtPn5+PHjFf+eN28ePD09sWnTJlhbW8Pf31+V+YiIiIiIiIiIqIQqUmFq4cKFin9Xr14d9+/fR1JSEoyNjSGTyYoUJCcnB5qamkV+PBERERERERERqZciLeVr3bo1Nm3ahOTkZEWbiYlJoYtK8fHxWLhwIapWrQptbW2cOXMm33ELFixAuXLloK2tjfr16+c7TlVjiIiIiIiIiIjo8yhSYcrOzg7jx4+HlZUVevfujQMHDiA7O7vQx1mxYgWio6Oxfv36d45Zt24dZsyYgY0bNyIuLg4dO3ZEx44dERYWpvIxRERERERERET0+ciEEKIoD8zKysLhw4fx119/4eDBgzAwMEDv3r3h5eUFZ2fnQh0rIiICtra2OHXqFFxdXZX6qlevjvbt22PZsmUAACEEKlSogP79++P3339X6ZgPSU5OhomJiWLZIhERERERERHR5xIcHIwGDRogKCgITk5OUsd5p8LUT4p8VT4dHR14enrC398fsbGxWLBgAc6ePQsXF5eiHjKPhIQEPHz4EC1btlS0yWQyuLq64sKFCyodQ0REREREREREn1eRC1NvvXr1Cn5+ftiyZQvu3LmDatWqqSYZgJiYGACApaWlUnuZMmUQGxur0jH5yczMRHJystKNiIiIiIiIiIhUo0iFqYyMDAQEBKBr166wtrbGr7/+irp16+LSpUt48OCB6lP+h1wu/+BG66oYM3fuXJiYmChutra2Rc5MRERERERERETKtIryICsrK+Tm5sLT0xP79u1DmzZtoKmpqfJwNjY2AIAXL14otb98+RLW1tYqHZOfSZMmYdy4cYr7ycnJLE4RERERERER0QeFhoYiJSVFpce8f/++0n9VxcjICPb29io9ZkEVqTC1evVqeHp6Ql9fX/WJ/sXMzAw1atTAqVOn0L17d+DNpuWnTp3CwIEDVTomP7q6utDV1f2kr5GIiIiIiIiISpbQ0FCVbnX0X15eXio/5sOHDyUpThWpMNWvXz+VPLkQArm5ucjNzQUA5ObmIicnBxoaGtDQ+L9VhhMnTsTIkSPRpk0bODs7Y968eUhOTsb//vc/xXFUNYaIiIiIiIiI6GO9nSm1bds21KhRQ2XHTU9PR1hYGCpVqgQ9PT2VHPP+/fvw8vJS+eyugipSYUpVfHx8MHjwYACApqYm2rVrBwCYOnUqpk6dCgD45ptvkJKSgrFjxyI2Nha1a9fG33//rbSkTlVjiIiIiIiIiIhUpUaNGnByclLpMZs1a6bS40lNJoQQUodQF8nJyTAxMUFSUhKMjY2ljkNERERERERExVBwcDAaNGiAoKAglRemVO1TZC1M/aRIV+UjIiIiIiIiIiL6WCxMERERERERERGRJAq8x1SfPn0KfFBfX9+i5iEiIiIiIiIioi9EgWdMmZqaKm4ymQx+fn4IDg6GTCaDTCZDcHAw/Pz8IJPJPm1iIiIiIiIiIiIqEQo8Y2rNmjWKfw8YMACTJk3C7NmzFYUoIQQmT56MyMjIT5OUiIiIiIiIiIhKlAIXpv7t77//xv3795VmR8lkMkycOBE1a9ZUZT4iIiIiIiIiIiqhirT5eXp6Oh4+fJin/eHDh0hLS1NFLiIiIiIiIiIiKuGKNGOqf//+6NmzJ6ZPn45GjRpBCIFr165h+vTp8Pb2Vn1KIiIiIiIiIiIqcYpUmFq6dCnMzc3xww8/ICUlBQBgZGSEMWPGYOrUqarOSEREREREREREJVCRClM6OjqYNWsWZs6cifDwcACAra0tNDSKtDKQiIiIiIiIiIi+QEUqTL2loaGBihUrqi4NERERERERERF9MYo0xUkIgQ0bNsDZ2RlWVlaK9ilTpiAqKkqV+YiIiIiIiIiIqIQqUmFq5cqVmD59Onr27IkXL14o2itVqoRZs2apMh8REREREREREZVQRS5M+fv7Y9y4cUrt7dq1w65du1SVjYiIiIiIiIiISrAiFabCwsJQr149AIBMJlO0GxkZITExUXXpiIiIiIiIiIioxCpSYapChQq4ceMG8J/C1N69e1G9enXVpSMiIiIiIiIiohKrSFfl+/777zFw4EDMnz8fAHD58mUcPXoU8+fPx/Lly1WdkYiIiIiIiIiISqAiFaZGjx6NjIwMDB48GHK5HE2bNoWJiQlmzJiBIUOGqD4lERERERERERGVOEUqTAHAxIkTMW7cODx58gRyuRxVqlSBtra2atMREREREREREVGJVaTCVOvWreHl5YXu3bvD3t5e9an+5W3h679MTExgaWkJAHj58iWSkpKU+nV1dWFra5vnca9fv8arV69gY2MDTU3NT5iciIiIiIiIiIjep0iFKTs7O4wfPx7fffcdPDw84OXlhfbt23+SGVNdu3bF69evFfdzc3MRFhaGCRMmYMGCBQCAX3/9Fdu2bYO1tbViXLVq1XD48GGlx33//ffYsGEDDAwMoKmpiRUrVqBPnz4qz0xERERERERERB9WpKvyrVu3DjExMdixYwfkcjl69eoFGxsbjBw5EhcvXlRpwJs3b+LRo0eK25IlSwAA/fv3VxrXvn17pXH/LkoBwPz587Fz507cuHEDCQkJmD17Nry8vHDnzh2V5iUiIiIiIiIiooIpUmEKAHR0dODp6Ql/f3/ExsZiwYIFOHv2LFxcXFSb8D82btyIhg0bol69enn6oqKilGZX/dvq1asxdOhQ1KhRAwDw7bffokqVKli3bt0nzUtERERERERERPkrcmHqrVevXsHPzw9btmzBnTt3UK1aNdUky0d0dDSOHDmCYcOG5enbtWsX6tWrB3Nzczg5OeHSpUuKvtjYWISHh8PZ2VnpMc2aNcO1a9c+WV4iIiIiIiIiInq3IhWmMjIyEBAQgK5du8La2hq//vor6tati0uXLuHBgweqT/nG5s2boaenh759+yq1Ozs74969e3jx4gVevXqF+vXro0OHDoiMjAQAxMXFAQBKly6t9DgLCwtFX34yMzORnJysdCMiIiIiIiIiItUoUmHKysoKgwYNgoGBAfbt24fIyEgsW7YMjRs3Vn3Cf/nzzz/Rp08fGBkZKbUPHDhQsURPX18fq1atQk5ODnbv3g0A0ND4v5eZnZ2t9LisrKz3Xplv7ty5MDExUdzyu8ofEREREREREREVTZGuyrd69Wp4enpCX19f9Yne4cyZM3j06BH++uuvD47V1dWFtbU1nj17BgAoX748ACAmJkZpXExMjKIvP5MmTcK4ceMU95OTk1mcIiIiIiIiIiJSkSLNmFqyZMlnLUrhzabnderUyTMrSwiB3NxcpbaIiAiEhYWhatWqAAAjIyM0aNAAx44dU4zJysrCP//8A1dX13c+p66uLoyNjZVuRERERERERESkGkUqTD18+BApKSmqT/MOSUlJCAgIyHfT8+zsbDRp0gTbt2/HzZs3ceDAAXTq1AmVK1eGl5eXYty0adOwbds2LFu2DFeuXMGAAQOgo6ODESNGfLbXQURERERERERE/1+RClNdunTBpk2bVJ/mHf755x9UqFBBqdD0lo6ODrZu3Yp//vkHgwYNwpIlS+Dp6YmgoCAYGhoqxrm7u8Pf3x/79u3DN998AwAIDAzMsyE6ERERERERERF9HkXaY0oul2PMmDHYuXMnatasCR0dHaX+lStXqiofAKB79+7o3r37O/tr1qyJP//884PH8fT0hKenp0qzERERERERERFR0RSpMJWamoouXboAAF68eKHqTERERERERERE9AUoUmFq7969qk9CRERERERERERflCIVpoiIiIiIiIiI6N2sDWXQS3wIRBVpe+/PRi/xIawNZZI9f5EKU0IIbNy4ERs3bsSTJ08QGxsLAJgyZQq+++47lC1bVtU5iYiIiIiIiIjUxvAGOqgROBwIlDrJ+9V4k1UqRSpMrVy5EvPmzcO4ceMwfvx4RXulSpUwa9YsrFq1SpUZiYiIiIiIiIjUytqgLPSeuhk1HBykjvJe90NCsHZRP3hI9PxFLkz5+/vD2dlZqTDVrl07TJ48mYUpIiIiIiIiIvqixaQKpJtWA8rWkzrKe6XHyBGTKiR7/iItdAwLC0O9ev93YmWy/78O0cjICImJiapLR0REREREREREJVaRClMVKlTA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6NChcHBwAACEhIRg/fr10NPTg5+f36fKSkREREREREREJUihClNlypTBpUuXMGHCBCxevBjp6ekAAD09PXTv3h0LFixAmTJlPlVWIiIiIiIiIiIqQQpVmAIAa2trbNu2DVlZWQgPDwcA2NraQkdH51PkIyIiIiIiIiKiEqrQham3dHR0YGdnp9o0RERERERERET0xSjU5udERERERERERESqwsIUERERERERERFJgoUpIiIiIiIiIiKSBAtTREREREREREQkCRamiIiIiIiIiIhIEixMERERERERERGRJFiYIiIiIiIiIiIiSbAwRUREREREREREkmBhioiIiIiIiIiIJMHCFBERERERERERSYKFKSIiIiIiIiIikoSW1AEKIiYmBlevXoWWlhYaNGiAMmXKKPVfvHgRDx48UGozMzNDly5dlNpycnJw9uxZxMbGonbt2nB0dPws+YmIiIiIiIiIKK9iXZgSQmDw4ME4ceIE6tWrh7S0NFy8eBELFy7E//73P8W4LVu24OjRo3B1dVW0lS9fXqkwlZCQgDZt2iAhIQG1atXCmTNnMHjwYCxduvSzvy4iIiIiIiIiIgBIS0tDSEhIgcbev39f6b8f4uDgAH19/Y/K96kV+8JUy5YtsX79emhp/V/UjRs3Yvjw4Wjfvj0qV66sGNuwYUNs3rz5ncf65ZdfkJ6ejtu3b8PQ0BCXL1+Gs7MzOnTogHbt2n2W10NERERERERE9G8hISFo0KBBoR7j5eVVoHFBQUFwcnIqYrLPo1gXpjQ0NDBo0CClNnd3dwwdOhT3799XKkzFx8dj586dMDExgZOTEywtLRV9Qgj4+vpiypQpMDQ0BAA0adIETZo0wfbt21mYIiIiIiIiIiJJODg4ICgoqEBj09PTERYWhkqVKkFPT69Axy7uinVhKj9Hjx6FhoYGatWqpdT+4MED+Pr6IjIyEnfv3sWiRYswfPhwAEB4eDiSkpLy7ClVq1YtBAcHv/O5MjMzkZmZqbifnJys8tdDRERERERERF8ufX39Qs1qatas2SfN87mp1VX5Hj16hLFjx+L7779HhQoVFO3e3t4ICwvD7t27cfnyZSxYsAAjR47EjRs3AABJSUkAAFNTU6XjmZubK/ryM3fuXJiYmChutra2n+y1ERERERERERF9adSmMPX8+XN8/fXXcHV1xYIFC5T6mjVr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pUSahSumiIiIiIiIiN7A0dERx44dw7hx4zB//nysWLECzZs3L3JP5cqVUaNGDWGNRJqIh58TERERERERvYVVq1Zh3bp1cHR0RKtWrRAcHIywsDDo6ekhIyMDDg4OOHToEBwcHESnEmkMDqaIiIiIiIiISig1NRX29vaoXLky2rRpg5MnT6JDhw7YvHmz6DQijcKtfEREREREREQlZG5ujtOnT6Njx464desWvLy8sGHDBtFZRBqHK6aIiIiIiIiIXkOWZaxZswYnTpxAkyZNMGnSJOjr64vOIiozOJgiIiIiIiIieo2vvvoKu3fvRrNmzXDixAk0aNAAERERRZ7QR0T/HrfyEREREREREb1CTEwM9u3bh7i4OBw4cADnz5/HnTt3sGTJkiL3HTlyBDk5OcI6iTQZB1NEREREREREr3Do0CEMHjwYpqamAIAGDRpg2bJl+OWXX/D8+XMAQGZmJtzc3JCXlye4lkgzcTBFRERERERE9ArPnj2Dra1tkWtKpRKmpqb47bffAADbt29H165dYWRkJKiSSLNxMEVERERERET0Cra2tsjIyChyTVtbG9OnT8eKFSuQm5sLSZKgVCqFNRJpOh5+TkRERERERPQaOTk5xZ7Cl5eXB1tbWygUCmzcuBEpKSkoV66csEYiTcYVU0RERERERER/uXfvHg4cOIDCwkIAKDaUAgA9PT18/fXXWLJkCTw8PDiUInoHHEwRERERERER/eXEiRPo27cvLC0tMWXKFFy4cOGV940cORIuLi7cxkf0jriVj4iIiIiIiOh/pKWlwc/PD76+voiOjoaDgwOUSiW8vLxQs2ZN0XlEZQpXTBERERERERH9D1NTU4wfPx6fffYZqlatCj09PSxevBi1atVC586dsXnzZjx//lx0JlGZwMEUERERERER0f8RGBiIw4cPIzExETExMUhPT8fu3buRlJSEoUOHokaNGnjy5InoTCKNx8EUERERERER0f/h5+eHESNGwNjYGACgra2NPn36IDw8HAYGBvD19UXVqlVFZxJpPA6miIiIiIiIiP4PlUqFa9euFbtubW0NGxsb1KtXT0gXUVmjKzqAiIiIiIiIqLQZNWoUevXqBXNzc0yePBn6+voAgEuXLuHOnTuoU6eO6ESiMoFP5SMiIiIiIiJ6BUmSMHHiRABAmzZtoKuri9DQUCxYsABTp04VnUdUJnAwRURERERERPQamZmZkCQJUVFR0NHRgYeHB7p37y46i6jM4GCKiIiIiIiI6H/k5ubi5s2bqFatGszMzETnEJVpPPyciIiIiIiI6C8+Pj4wMzNDw4YNYW5ujmbNmmH37t2is4jKLA6miIiIiIiIiABERkZixowZ+PXXX3Ht2jXs3bsXNjY2cHNzw7Jly0TnEZVJ3MpHREREREREBOCLL75A/fr1MWPGjCLX169fj/Hjx+P+/fswMTER1kdUFnHFFBERERERERGAW7duwdzcvNj1kSNHolq1arh+/bqQLqKyjIMpIiIiIiIiIgBOTk5YunQpHj9+XOT68+fP8fz5c9jY2AhrIyqruJWPiIiIiIiICEB6ejpat26N9PR0jBkzBp06dUJhYSEWL16MKlWqICAgQHQiUZnDwRQRERERERHRX549e4ZFixZh8+bNePDgAbS1tdG/f39s2LABRkZGovOIyhwOpoiIiIiIiIhe4fHjx9DX14eBgYHoFKIyi4MpIiIiIiIiIiISgoefExERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREBxMERERERERERGREP8fyOvo8zuJQxMAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(12, 5))\n",
    "plt.boxplot(X, tick_labels=wine.feature_names)\n",
    "plt.xticks(rotation=70, ha=\"right\")\n",
    "plt.ylabel(\"Observed value\")\n",
    "plt.title(\"Wine features before scaling\")\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. Identify the learning problem and metric\n",
    "\n",
    "Is this supervised or unsupervised learning? Classification or regression? Binary or multiclass?\n",
    "\n",
    "Choose a first metric and justify it. You can consult the [classification metrics documentation](https://scikit-learn.org/stable/modules/model_evaluation.html#classification-metrics)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "# TODO: write your answers as comments, then import your chosen metric.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "This is supervised multiclass classification: every sample has a known class label. Accuracy is a reasonable first metric because the classes are fairly balanced and we have not been given asymmetric error costs. That choice would need revision if some errors were more serious than others."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "print(\"Selected metric: accuracy\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7. A first k-NN model\n",
    "Find the appropriate estimator in the [nearest-neighbours documentation](https://scikit-learn.org/stable/modules/neighbors.html#nearest-neighbors-classification).\n",
    "\n",
    "1. Instantiate the classifier with its default parameters.\n",
    "2. Fit it on `X, y`.\n",
    "3. Predict the labels of `X` and compute accuracy.\n",
    "4. Read the [`KNeighborsClassifier` documentation](https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html): what is the default value of $k$?\n",
    "5. Which fundamental evaluation principle does this experiment violate?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "\n",
    "# TODO: fit a default k-NN on all the data and evaluate it on the same data.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "The default is $k=5$. The resulting accuracy is a **training score**, not evidence of generalisation: the same samples were used for fitting and evaluation. Even a high value would not tell us how the classifier behaves on unseen wines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "knn_on_all_data = KNeighborsClassifier()\n",
    "knn_on_all_data.fit(X, y)\n",
    "predictions_on_training_data = knn_on_all_data.predict(X)\n",
    "\n",
    "print(\"Parameters:\", knn_on_all_data.get_params())\n",
    "print(\"Training accuracy:\", accuracy_score(y, predictions_on_training_data))\n",
    "# it's ok if students compute accuracy on their own."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8. A first train/test protocol\n",
    "\n",
    "Use [`train_test_split`](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html) to reserve 25% of the samples for testing.\n",
    "\n",
    "Requirements:\n",
    "- Even if not relevant here, you can preserve class proportions with `stratify=y`;\n",
    "- for now, do **not** set `random_state`;\n",
    "- fit the default k-NN using the training set **only**;\n",
    "- report both training and test accuracy.\n",
    "\n",
    "Why is the training score still useful, even though it cannot estimate generalisation on its own?\n",
    "\n",
    "> In this practical, we inspect the test score early for teaching purposes. Consequently, a later score on this same test set must be interpreted as illustrative rather than as a perfectly untouched final estimate."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# TODO: create X_train, X_test, y_train and y_test, then evaluate k-NN.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "The test set is not used by `fit`, so its score is a first estimate of performance on unseen samples from the same sampling process. Comparing train and test scores can reveal a generalisation gap, although one split remains uncertain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    X, y, test_size=0.25, stratify=y\n",
    ")\n",
    "\n",
    "knn = KNeighborsClassifier()\n",
    "knn.fit(X_train, y_train)\n",
    "\n",
    "print(f\"Training accuracy: {knn.score(X_train, y_train):.3f}\")\n",
    "print(f\"Test accuracy:     {knn.score(X_test, y_test):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 9. Select the number of neighbours\n",
    "\n",
    "$k$ is a **hyperparameter**: `fit` does not learn it. Testing many values on `X_test` and keeping the best would turn the test set into validation data.\n",
    "\n",
    "Propose a strategy to fit $k$ while avoiding leakage to the test set.\n",
    "\n",
    "What is the best value of $k$ for this validation split?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "# TODO: Fit k !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "# Odd k does not guarantee the absence of ties in multiclass classification,\n",
    "# so we evaluate every integer value in the chosen range.\n",
    "k_values = np.arange(1, 31)\n",
    "print(k_values)\n",
    "\n",
    "# Create a separate validation set from the training data.\n",
    "X_train, X_val, y_train, y_val = train_test_split(\n",
    "    X_train, y_train, test_size=0.25, stratify=y_train\n",
    ")\n",
    "\n",
    "perf_train = []\n",
    "perf_val = []\n",
    "\n",
    "for k in k_values:\n",
    "    knn = KNeighborsClassifier(n_neighbors=k)\n",
    "    knn.fit(X_train, y_train)\n",
    "    perf_train.append(knn.score(X_train, y_train))\n",
    "    perf_val.append(knn.score(X_val, y_val))\n",
    "    print(f\"k={k:2d} | training accuracy: {perf_train[-1]:.3f} | validation accuracy: {perf_val[-1]:.3f}\")  \n",
    "\n",
    "plt.plot(k_values, perf_train, label=\"training accuracy\")\n",
    "plt.plot(k_values, perf_val, label=\"validation accuracy\")\n",
    "plt.xlabel(\"k\")\n",
    "plt.ylabel(\"accuracy\")\n",
    "plt.title(\"k-NN performance on training and validation sets\")\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10. To scale or not to scale?\n",
    "\n",
    "Return to the boxplot. With the default Euclidean distance, which variables are likely to dominate? Propose a preprocessing step.\n",
    "\n",
    "Read the [`StandardScaler` documentation](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html). Then answer:\n",
    "\n",
    "1. Which statistics does the scaler learn?\n",
    "2. Why would calling `scaler.fit(X)` before the train/test split leak information?\n",
    "3. Why is scaling particularly relevant for k-NN?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "# TODO: fit a scaler on X_train only and inspect its mean_ and scale_ attributes.\n",
    "# Do not transform X_test yet.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "`StandardScaler` learns one training-set mean and standard deviation per feature. Fitting it before splitting would let test-set values influence preprocessing. Because k-NN uses distances, a large-scale feature can otherwise dominate several informative small-scale features."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "scaler = StandardScaler().fit(X_train)\n",
    "print(\"Mean of each feature:\", scaler.mean_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 11. Prevent leakage with a pipeline\n",
    "\n",
    "A [`Pipeline`](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html) chains preprocessing and prediction. When the pipeline is fitted on `X_train`, the scaler learns from `X_train` only; the same transformation is then applied to validation and test samples.\n",
    "\n",
    "Build a pipeline with a scaler and k-NN. Jointly compare:\n",
    "\n",
    "- no scaling versus `StandardScaler`;\n",
    "- $k=1,\\ldots,30$.\n",
    "\n",
    "Select the best configuration on the validation set, refit it on the combined training and validation data, then report its performance on the test set. Remember that this score is illustrative because the test set was already inspected in Section 8."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "from sklearn.pipeline import Pipeline\n",
    "\n",
    "# TODO: build the pipeline and search both scaling choices and all k values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "# Manual search on the validation set\n",
    "best_score = -np.inf\n",
    "best_params = None\n",
    "best_model = None\n",
    "\n",
    "for k in k_values:\n",
    "    for scaling in [None, StandardScaler()]:\n",
    "        if scaling is not None:\n",
    "            model = Pipeline([\n",
    "                (\"scaler\", scaling),\n",
    "                (\"knn\", KNeighborsClassifier(n_neighbors=k))\n",
    "            ])\n",
    "        else:\n",
    "            model = Pipeline([\n",
    "                (\"knn\", KNeighborsClassifier(n_neighbors=k))\n",
    "            ])\n",
    "\n",
    "        model.fit(X_train, y_train)\n",
    "        score = model.score(X_val, y_val)\n",
    "\n",
    "        if score > best_score:\n",
    "            best_model = model\n",
    "            best_score = score\n",
    "            best_params = (k, scaling)\n",
    "\n",
    "print(\"Best configuration:\", best_params)\n",
    "print(f\"Validation accuracy: {best_score:.3f}\")\n",
    "\n",
    "\n",
    "# Retrain on X_train + X_val. There are always questions on the need to retrain on the full training set, so let's do it here.\n",
    "# we can argue that we will use more data, but are the best hyperparameters still adapted ? \n",
    "X_train_final = np.concatenate([X_train, X_val])\n",
    "y_train_final = np.concatenate([y_train, y_val])\n",
    "\n",
    "best_model.fit(X_train_final, y_train_final)\n",
    "\n",
    "print(f\"Test accuracy: {best_model.score(X_test, y_test):.3f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 12. Reproducibility\n",
    "\n",
    "Restart the kernel and run the train/test section several times. Are the scores identical? Locate the source of randomness.\n",
    "\n",
    "Modify the protocol so that another person running the notebook obtains the same split.\n",
    "\n",
    "Does setting a seed prove that the conclusion is robust to the choice of split?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "exercise"
    ]
   },
   "outputs": [],
   "source": [
    "# TODO: recreate both random splits using random_state.\n",
    "# Check that rerunning the cells produces the same partitions and scores.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "source": [
    "### Proposed answer\n",
    "\n",
    "Set `random_state` to a fixed value in every stochastic splitting operation. This makes the experiment repeatable, but it does not prove that the conclusion is insensitive to the particular split."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "correction"
    ]
   },
   "outputs": [],
   "source": [
    "RANDOM_STATE = 42\n",
    "\n",
    "X_train_repro, X_test_repro, y_train_repro, y_test_repro = train_test_split(\n",
    "    X, y, test_size=0.25, stratify=y, random_state=RANDOM_STATE\n",
    ")\n",
    "X_train_repro, X_val_repro, y_train_repro, y_val_repro = train_test_split(\n",
    "    X_train_repro,\n",
    "    y_train_repro,\n",
    "    test_size=0.25,\n",
    "    stratify=y_train_repro,\n",
    "    random_state=RANDOM_STATE,\n",
    ")\n",
    "\n",
    "print(\"Train / validation / test sizes:\",\n",
    "      len(X_train_repro), len(X_val_repro), len(X_test_repro))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 13. Conclusions\n",
    "\n",
    "Complete the following statements in your own words:\n",
    "\n",
    "1. Evaluating a model on its training data is misleading because ...\n",
    "2. The test set must remain outside model selection because ...\n",
    "3. Scaling matters for k-NN because ...\n",
    "4. A pipeline prevents leakage by ...\n",
    "5. A fixed seed provides reproducibility, but not ...\n",
    "\n",
    "### Optional extension\n",
    "\n",
    "Compare your final model with a [`DummyClassifier`](https://scikit-learn.org/stable/modules/generated/sklearn.dummy.DummyClassifier.html). A useful model should improve on a simple baseline under the same evaluation protocol."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (cours-ml)",
   "language": "python",
   "name": "cours-ml"
  },
  "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.12.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
