Files
ArtStudies/M2/Deep Learning/TP2/TP2 - Starter.ipynb

679 lines
115 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Séance 2 - Réseau de neurones convolutionnel\n",
"\n",
"On se propose de classifier les chiffres manuscrit du dataset [FashionMNIST](https://github.com/zalandoresearch/fashion-mnist) en définissant ses propres réseaux de neurones convolutionnel. L'objectif est de découvrir la manière d'entraîner ces algorithmes et observer en pratique les bases théoriques discutées en cours.\n",
"\n",
"## Exploration des données\n",
"\n",
"Commençons par importer les données."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"%matplotlib inline\n",
"import matplotlib.pyplot as plt\n",
"import seaborn as sns\n",
"\n",
"sns.set(style='whitegrid')\n",
"\n",
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"\n",
"(X_train_full, y_train_full), (X_test, y_test) = (keras.datasets.fashion_mnist.load_data())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : À l'aide de la fonction [`train_test_split`](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html), séparer le jeu d'entraînement complet en un dataset d'entraînement et un dataset de validation. Afficher les tailles des datasets respectifs."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(48000, 28, 28) (48000,)\n",
"(12000, 28, 28) (12000,)\n"
]
}
],
"source": [
"from sklearn.model_selection import train_test_split\n",
"\n",
"X_train, X_valid, y_train, y_valid = train_test_split(\n",
" X_train_full, y_train_full, test_size=0.2, random_state=42\n",
")\n",
"print(X_train.shape, y_train.shape)\n",
"print(X_valid.shape, y_valid.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Les classes sont encore des nombres, mais ils correspondent à une catégorie. Pour mieux visualiser, nous allons faire un dictionnaire."
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"label_map = {\n",
" 0: \"t-shirt/top\",\n",
" 1: \"trouser\",\n",
" 2: \"pullover\",\n",
" 3: \"dress\",\n",
" 4: \"coat\",\n",
" 5: \"sandal\",\n",
" 6: \"shirt\",\n",
" 7: \"sneaker\",\n",
" 8: \"bag\",\n",
" 9: \"ankle boot\",\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Afficher plusieurs images du dataset d'entraînement aléatoirement. On pourra utiliser la fonction [`imshow`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.imshow.html) et le dictionnaire."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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AAAApI6MBlDC1PpeVWBKFfhZv3594rrjyZMnB62ldl9TvR6AwvTEE09kPd5vv/28bbp16+a1LV26NHH9e69evYLW6Sv77rtv1uNLL700qKDjiBEjvDY337HLLrt42zRp0sRru/vuuxPX5auswCWXXBIVOlU4cf78+XkVmb3wwgvzOr6qXILKP6oshLv/qvifen6Vvxg8eHDiZ0D9XEjmRJ0bqEzLmjVrotLGFQ0AAAAAqWOiAQAAACB1TDQAAAAApI6JBgAAAIDUEQYHSpgqDKSKXKkQmFv0RwUVP/nkE6/tpZde8trcglJuwalcAbmyKPADoHT1798/6/E999zjbfPuu+96bTvttFNieHXZsmXeNqpgqCrsV79+/azHc+fODQqkq6Btq1atErdRN8k45phjEgulqiKsRxxxRFToWrRokViEMdfNB0KoY2lIsFxp06ZNVB5VC/h99t9//6CCfe3bt49KG1c0AAAAAKSOiQYAAACA1DHRAAAAAJC6rYrUomzH119/Ha/drlKlSvp7gArJCuLY2v2dd965xF+rovc/tRZ5+fLlQWtN3TXEahv1/Kooj5vJCC0yVOj9rzL0QaSrEPqfKgC2bt06r00VMMtnmy352dAcmVvcLXS/1BjrPtd2223nbVOvXr2o0I/BqticysG4p6KhBR3x/6xYsSJyqf6tclDqvCLN/hd0VkEYFKpPlFa/qOj9T33YVeXuNJ+/sg/Spdn/Mq8HFFL/q127dlAbykZFOQarCZhqw5apW7duVF77X9AVDQAAAADYHGQ0AAAAAKSOiQYAAACA1DHRAAAAAJA6JhoAAABACSgq8Cg0E40U7bffftGVV15Z1ruBCuLFF1+MOnfuHM2ZM6esdwVIjY2BNhaW9M+gcuC4ifImZDwKPX4/99xz0d/+9reokDHRAAAAAALts88+0f/+97+ocePGm9zu/vvvlzUuCknFqM4FAAAAlAP169eP/4cCuKIxduzY6JRTTol22WWXaKeddopOPfXUaNSoURsvf9njF154IRo4cGDUvXv36PDDD4+GDh2a9Rzz5s2LLr300mi33XaLevXqFT/fuHHjsraxy2OXX3551L9//6hbt27RHnvsET9WFZ4znn/++ahLly7Rfffdt7Ft0qRJ0TnnnBNXU7T//e53v4tmz5698d+//PLL+HLcM888E+27777xNp999lmKfzGUBass+89//jP+FsT62Pnnnx+tXLly47//4x//iA488MDo3nvvjfuh9bPMv9ul10MOOSTuv/bztm3xqrTLli2LLrvssmjPPfeMevToEffxl19+Oeu177zzzvhSsD2H/ff222+XFVtROWxqXMz0qSOPPDLq3bt31LNnz7jPvPXWW1nLAnbcccdo9OjR0bHHHhv3KxuPHn744azXsT561VVXxX22T58+0W233eZVUba++uCDD0aHHnpo/Fr2mscdd1w0bNiwUvhLoCKwseimm26K+9Cuu+4aXXHFFfG4FtpfzTfffBOdcMIJ8TY2Tj722GNxv2dZFvIZIzPjoJ072vh32GGHRR9//HHOpVPWz+z5rrvuuvi87eCDD44GDBgQzZ07N3rppZcKepl0hb6i8f3330dnnnlmtPvuu8cnX1YS3S5TnXHGGdFHH320sTMtWrQouuiii6KaNWtGd999d3ThhRfGk406derEg5kd9KpVqxZdc8018X9tgLIByyYKHTp0iNatWxedfPLJUb169eJOZFWXbVCzk8KqVatGN9xwg7dvb775Zvx8dkJpkwkzffr0+LXat28fr9n76aef4v09/vjjo1deeSWrWrQ995/+9Kdo/fr18YcAFZudgD3++OPReeedF0807CBpJ/vuhNcGMpsU2KVW658PPPBA/PjEE0+MT+jGjx8f9/X58+dHN998c/xzf/jDH6KlS5dGf/7zn+M+bn3JDtRNmzaNPxv//ve/o6effjpua9WqVXzyaM9p1Vntc4HKJWlcfPXVV+OTOhsH7SBrkwXrI7///e/jscb6jbEJw//93//FB2D7r42Ht956a7TDDjtEe+21V/zv9jp2ILW+ZZVpH3rooWjMmDFZywn+/ve/x/3PJsN2sF24cGH85cvFF18c74+NuShsNh7auHjLLbfEx2TrM1OmTImeffbZ+Eu3pP46derUuJ/aFyl33HFH/AWg/XfVqlXxlzTA5p472jHWviCxcap69erxMdOOlx988EHWuVpxX331VbT99tvH49vatWujZs2aRWeffXb8pY2dCyYts6qsKvREwwYiG1BsEmAzSGMn8bZubs2aNfHj1atXxzPP1q1bx4+tw9hJm32bZjNVm1TYSZ0dCFu0aBFvs/fee8ezUZuU3HPPPdGMGTPiwcwmB3aiZqyD2gnb8OHDvf368MMP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9ssvv5z12nfeeWfc3+057L/2ufrxxx9L+a+AskL/Qz44BnMMLkv0v/sqRf/bNirHLr/88uirr76K3+zWrVtHM2fOjO6+++74oPbGG29sLH8+duzY+I276KKLopo1a8bbXHjhhXFHq1OnTtZzrlmzJjrrrLPijvbEE09EzZs399bt2YHzuOOOi6pVqxZdc8018X8fe+yx6IQTToief/75qEOHDpvc76uvvjrelxYtWkSPPvpo/HpPP/103FmWLFkSd6rtt98+uuSSS6J69erFHeR3v/tddOutt0aHHXZYHO4599xzo1GjRkUXXHBB1KVLl+jLL7+M7rrrrmj27NnRjTfeGJ8o2H5ax7eTA/v7oPy67bbboscffzw677zz4kHrrbfeigdQd2D7+OOP45OyFStWxH33gQceiB+feOKJ8cBkA6yd6M2fPz+6+eab45/7wx/+EC1dujT685//HPf/V155Jbriiiuipk2bRrvvvnv073//O+5/1taqVato9OjR8XNut912cT9F5Uf/Qz44BnMMLkv0v1GVo/8VlVMbNmwoOv3004veeOONrPZHHnmkaIcddihatGhR/PiKK66IH8+cOXPjNsOHD4/b3n777fjxCy+8ED+eMmVK0UknnVQ0YMCAolmzZm3cfvbs2fG/23bmjjvuKOrRo0fRnDlzsvZn//33L7rwwgtz7vM999wTP89bb721sW39+vVFe+6558afu/XWW4u6deuW9dzmlFNOibf7+eefiz766KP4eV5//fWsbe677764fdKkSRt/93333Xez/q4ofStXrozf89tuuy2r/YwzzojfT+t/mb4zYsSIjf++atWqop49exZde+21WT/37LPPZvWD7t27F91///0b/9360C233FI0cuTI+LF9jk477bSs53jiiSeKXn755RL5fVG+0P+QD47BHIPLEv1vh0rT/8rt0qkqVapEDz/8cHTwwQdHCxcujIYNGxY988wz0Ycffhj/+w8//LBx2/r162fN5uybNLNu3TpvdmyzQpvp2jdrudhlrq5du0ZNmjSJfvrpp/h/W2+9dbT33ntHn3/++Sb3276ls0tcGTZrtZ8bMWJE/Hj48OHRTjvtFM90i7NZ7OLFi6Np06bF22y77bbxJTN3m8xzoOKwbyVsmci+++6b1T548GBvW+t3Gd9880186dgu72b6of3PHpvP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UDE0atTIa5swYUJQDmHp0qWJGQp1vqcyGu54p7Idodld97i8JUWbNzjjstoH9fzqGO+2qb+pKtinijvPnz8/Kklc0QAAAACQOiYaAAAAAFLHRAMAAABA6phoAAAAACjsMPgtt9zitY0fP95rW758eWIxElUYT4WPQoquqCBsSPGUNWvWeNt07NgxKCDuFl8755xzvG0IfofbfffdEwP4Ktyqbirw2muvJb5e586do4qia9euiUV/mjVrVop7hCS77rpr4jipbhahCjaG6NOnT1DY3B1P6TdA5XHGGWd4bR06dPDaRo8e7bW5wWj3HCdXuFmdf7nnd+4NgtTr5QpduzesCA2pK9s5+69+H3XTGRVmd8/v1Dbqb6jOaY888sioJHFFAwAAAEDqmGgAAAAASB0TDQAAAACp26pIVTtxWDE420wVpitrquCTu4ZOralTbepPEbL2LuBPGPxzas2e2gc37xH6c2n+3e35d95556iklUb/cwszqrWa6vVVFqeyCfmMqXWfIfmmitD/yvsYqKxatWqT/Xtz+m69evUSt1F5DDXGuq9Zu3btUh230kL/Q1mrKMdglaFQxxT3fCh0fFLnUe7xO/QcTW2X7/mdspUztqmxLt+2kPPEXNwccMgYvDn9L+hMoDwP/Ay8ZcP6RGn1i9J4nZCQVqEqj5+x0ux/mderSNQJfEmqU6dOVEjofyhrFeUY7FbpztWGytv/gq5oAAAAAMDmqPzrPgAAAACUOiYaAAAAAFLHRAMAAABA6phoAEAlQuwOAFBeFPRE48UXX4w6d+4czZkzp6x3BQXuH//4R9wXM/bbb7/oyiuvLNN9QsUzZMiQ6Iorrijr3QDKBOMmNhd9puSV3I3uAQCl6tFHHy3rXQAAYKOCvqIBAAAAoGQUzETDqtT+85//jPbZZ5+oV69e0fnnn59VzdaWrhx44IHRvffeG+22225R//79N/77c889Fx1yyCFR9+7d45+3bYtXnly2bFl02WWXRXvuuWfUo0eP6PDDD49efvnlrNe+884740t09hz239tvv11W60XFY++nvb8333xz1KdPn6hv377R5ZdfHq1YsSL+95NOOin+X3FffvllvFTK/hti9erV0V//+tfogAMOiPvYoYceGj3//PMb//2aa66J+59bEfUvf/lLvD+ZvjZp0qTonHPOiat52v9+97vfRbNn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MVvDbM9jOTgLQ9pVE/s3+2/S+ImKzSamdrJlY5N982v9w66o2nKmgw46KGics7v12KTC/nv66afHx10bv+yOP9ZPjX2ZYldJbGyzCa0tu7Pwrn2LbP1WsYyGXdWwJcw2sbYsEWMgFJso2woTW2ZnGSA7flvWyHK8dkXWluDZeZ6NrzahsCu3xXNGtlzU+qyNd9aH7UtkG+dsvN3q/786XNCKCsjjjz9etP/++xd179696KSTTip66qmninbYYYei2bNnF91zzz3x/688+eSTRQcffHBRt27divr161d02WWXFc2dO3fjvy9atKjoyiuvLOrfv3+8zQEHHFB0//33F/3888/xv//444/x81u7vfYee+xRdPXVVxctW7as1H53lJx999236NJLLy26/vrri3r37h33kZtvvrlo3bp18b//9NNPRbfddlvc3rNnz6IzzjijaOTIkXF/GzZsWLyN2//sOa+44oqNj5cuXVr0xz/+sWj33XeP+9Bhhx1W9Nxzz8n9Oeecc+JtVqxY4f3b2LFj49ffaaed4n39zW9+U/T+++9v/Hfbn+L7hYrliy++KNpnn33icejVV1/N+V6+/fbbRUcccUS8Xd++fYt+//vfF82bNy9rm5deeqnooIMOirex/vbpp58WDRw4MO6rGa+99lr8PNaXrE+deeaZRRMmTNis8dP6ufV3VEyjR48uOv3004t22223oh49ehQdeeSRRe+++27O99aOt9YvX3jhhY1tM2fOLLrooouK+vTpE4+R7vj2yy+/FN19991Fe++9d/wadiy98cYbi/73v//FzzVlyhQ5btox+Oijj47HzczxljEQxVmfueWWW+JzMusP1o/tWL5mzZr438ePH1904oknbvy33/72t0VDhw4tGjRoUNxnM0aMGFF0zDHHxMfeAQMGxOeXe+21V9xPC91W9n/KerIDVGR2lcKuTtm3bQAAoHBkguKZ0gjGrmrYEvrLL788XulQyApi6RQAAACQNrulsi29s2Wpdvc0C5dn6modeuihUaFjogEAAADkwXIZdjMYyxFZns1ujWyrHCznVp8cbsTSKQAAAACpK4jb2wIAAAAoXUw0AAAAAKSOiQYAAACAsgmDWwEoi3LY7bsAY8W5rBCNFSAsafQ/lGX/M/RBFEf/Q1njGIyK0v+CJhrWwciMb56ff/7Za9tmm22iyqI0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69Y1+uq7776LmoNdc20p8hYpx96yF2SF6z366KNmrdC2bVtjY5EXbKVKZBIbdMuoUaOMfUQvokv279+f/H2bjnO/jw1u166dWV/yfuYeP348+b3Y63vvvddp1qyZkVVsdKQ+PXHihDNs2DCz5uQa/MvaFtufCGTpjMYDDzzgfPPNN2bBX758eee3335zRowYYR7orFmzko8/R2GxeL/zzjtNJI45d9xxh3E2zjjjjKhrHjp0yLntttuMs/H22287Z555pk/5IDRJSUnO6aef7jzyyCPmXxZuLOSmTJniVK5cOdX7HjhwoLmXMmXKmNICft67775rBHDXrl3GsciTJ49z9913O4ULFzYK8/bbb3eef/55o0xpXGOhgNLt27evc8455xgjPnz4cOePP/5wBg8ebD4k3CfODx8M/j4ie4LTgOJ79tlnzTN94YUXnA0bNpiSk0mTJhknBHnGIKP4xo4d69x3333GOJcqVcqUz2GkUWBDhw419fH8i4yjHEV8wALq/vvvT/6/rawJg9azZ09TToI+yZUrl/PWW285vXv3NnJWoUKF5LmDBg1y7rrrLjMXmWKhhq7hK6XgCws9DOa+ffvMws12P6tWrTJGGPksV66cs23bNqM3KXNBXoPoNxcCMOjIhx9+2PxuGGccEPQ/ellkT/766y+ne/fuTpMmTcyi7ciRI6bE6dZbbzUOMGzdutU4n/369XPy5s1r5A67+vnnnztFixa1Xpf1ArYVJ/bw4cNO6dKlTR8j/ULYzFhlViJ+GTJkSLIuxN6iD9Enqek41o+vvfaaed25c2cTICbQjcwin08//bR5H3pw9+7dzuOPP27WoB999JEJGKLvmjRpYvQra0DG0Inff/+9uWbu3LmNTMc7WdbRQPHgFGBgiEwAXiYKigUZC/bixYub8YMHD5rFurvYRikhFMuWLTPREBeiaAgZDYo4GWXLlrX+bJwKhAzBwFkAonPcB07MSy+9lOq9I2xE6uD88893LrroIiNovO+NN94wi8m5c+cmX5uoCwtFFgZXXHGFqW/+8ssvzWLRXSjiKZ922mnm5990001O1apVTdr4v//97ymVOIjMh4XUuHHjjNy6r3E8cZRZeGF8MZIuyA0ZDjYDQD5QhAUKFHBef/315MXXWWedZZxlET+wkMeIQUqfeYzdxo0bjby4pUtkwQhGoFMjwYFF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",
"text/plain": [
"<Figure size 1000x1000 with 25 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(10, 10))\n",
"for i in range(25):\n",
" plt.subplot(5, 5, i + 1)\n",
" plt.xticks([])\n",
" plt.yticks([])\n",
" plt.grid(False)\n",
" plt.imshow(X_train[i], cmap=plt.cm.binary)\n",
" plt.xlabel(label_map[y_train[i]])\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Standardiser les données en utilisant la classe [`StandardScaler`](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html). On commencera par applatir les images en utilisant la méthode [`reshape`](https://numpy.org/doc/stable/reference/generated/numpy.reshape.html), puis on applique le pré-processing et on termine par reformer la matrice."
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.preprocessing import StandardScaler\n",
"\n",
"scaler = StandardScaler()\n",
"X_train_flat = X_train.reshape(X_train.shape[0], -1).astype(np.float32)\n",
"X_valid_flat = X_valid.reshape(X_valid.shape[0], -1).astype(np.float32)\n",
"X_test_flat = X_test.reshape(X_test.shape[0], -1).astype(np.float32)\n",
"\n",
"X_train = scaler.fit_transform(X_train_flat).reshape(X_train.shape)\n",
"X_valid = scaler.transform(X_valid_flat).reshape(X_valid.shape)\n",
"X_test = scaler.transform(X_test_flat).reshape(X_test.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Modélisation\n",
"\n",
"On veut définir le réseau suivant:\n",
"* Deux convolutions avec 32 filtres 3x3 en conservant la taille. On utilisera la couche [`Conv2D`](https://keras.io/api/layers/convolution_layers/convolution2d/)\n",
"* Une couche max pooling avec un filtre 2x2 et 2 de stride. On utilisera la couche [`MaxPool2D`](https://keras.io/api/layers/pooling_layers/max_pooling2d/)\n",
"* Une couche [`Flatten`](https://keras.io/api/layers/reshaping_layers/flatten/) puis un réseau dense de 64 neurones\n",
"* Une couche de sortie à 10 neurones\n",
"\n",
"**Consigne** : Définir le réseau souhaité. On sélectionnera la fonction d'activation et la distribution initiale des poids adaptées."
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"model = keras.models.Sequential(\n",
" [\n",
" keras.layers.Input(shape=(28, 28, 1)),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.MaxPooling2D(pool_size=2, strides=2),\n",
" keras.layers.Flatten(),\n",
" keras.layers.Dense(units=64, activation=\"relu\"),\n",
" keras.layers.Dense(units=10, activation=\"softmax\"),\n",
" ]\n",
")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Calculer le nombre de paramètre du réseau de neurones à la main, puis vérifier avec la méthode [`summary`](https://keras.io/api/models/model/#summary-method)."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential_10\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential_10\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_16 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">320</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ conv2d_17 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">9,248</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ max_pooling2d_10 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_10 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Flatten</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">6272</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_20 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">401,472</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_21 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">650</span> │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"</pre>\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_16 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m320\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ conv2d_17 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m9,248\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ max_pooling2d_10 (\u001b[38;5;33mMaxPooling2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_10 (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m6272\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_20 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m401,472\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_21 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m) │ \u001b[38;5;34m650\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">411,690</span> (1.57 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m411,690\u001b[0m (1.57 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">411,690</span> (1.57 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m411,690\u001b[0m (1.57 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Lancer l'entraînement avec les paramètres adaptés sur quelques époque pour vérifier son fonctionnement."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"750/750 - 17s - 22ms/step - accuracy: 0.8602 - loss: 0.3948 - val_accuracy: 0.8903 - val_loss: 0.2993\n",
"Epoch 2/5\n",
"750/750 - 15s - 20ms/step - accuracy: 0.9103 - loss: 0.2474 - val_accuracy: 0.9101 - val_loss: 0.2474\n",
"Epoch 3/5\n",
"750/750 - 15s - 20ms/step - accuracy: 0.9290 - loss: 0.1945 - val_accuracy: 0.9115 - val_loss: 0.2397\n",
"Epoch 4/5\n",
"750/750 - 17s - 23ms/step - accuracy: 0.9442 - loss: 0.1528 - val_accuracy: 0.9158 - val_loss: 0.2382\n",
"Epoch 5/5\n",
"750/750 - 17s - 22ms/step - accuracy: 0.9566 - loss: 0.1183 - val_accuracy: 0.9103 - val_loss: 0.2720\n"
]
}
],
"source": [
"model.compile(\n",
" optimizer=keras.optimizers.Adam(learning_rate=1e-3),\n",
" loss=\"sparse_categorical_crossentropy\",\n",
" metrics=[\"accuracy\"],\n",
")\n",
"\n",
"history = model.fit(\n",
" X_train,\n",
" y_train,\n",
" epochs=5,\n",
" batch_size=64,\n",
" validation_data=(X_valid, y_valid),\n",
" verbose=2,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Couche BatchNormalization\n",
"\n",
"On souhaite mesurer l'apport de la couche [`BatchNormalization`](https://keras.io/api/layers/normalization_layers/batch_normalization/) à un réseau de neurone. Pour cela, on se propose de faire une étude comparative sur le modèle que nous venons de définir. Nous nous proposons de placer la couche BatchNormalization uniquement entre les deux couches de convolution.\n",
"\n",
"**Consigne** : Définir une fonction `get_model` qui prend en paramètre:\n",
"* *normalization*: un booléen indiquant si la couche [`BatchNormalization`](https://keras.io/api/layers/normalization_layers/batch_normalization/) doit être présente dans le modèle\n",
"* *learning_rate*: un flottant correspondant au learning rate souhaité\n",
"\n",
"La fonction renvoie un modèle compilé."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"def get_model(normalization: bool, learning_rate: float) -> keras.Model:\n",
" if normalization:\n",
" model = keras.models.Sequential(\n",
" [\n",
" keras.layers.Input(shape=(28, 28, 1)),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.BatchNormalization(),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.MaxPooling2D(pool_size=2, strides=2),\n",
" keras.layers.Flatten(),\n",
" keras.layers.Dense(units=64, activation=\"relu\"),\n",
" keras.layers.Dense(units=10, activation=\"softmax\"),\n",
" ]\n",
" )\n",
" else:\n",
" model = keras.models.Sequential(\n",
" [\n",
" keras.layers.Input(shape=(28, 28, 1)),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.Conv2D(\n",
" filters=32, kernel_size=3, activation=\"relu\", padding=\"same\"\n",
" ),\n",
" keras.layers.MaxPooling2D(pool_size=2, strides=2),\n",
" keras.layers.Flatten(),\n",
" keras.layers.Dense(units=64, activation=\"relu\"),\n",
" keras.layers.Dense(units=10, activation=\"softmax\"),\n",
" ]\n",
" )\n",
"\n",
" model.compile(\n",
" optimizer=keras.optimizers.Adam(learning_rate=learning_rate),\n",
" loss=\"sparse_categorical_crossentropy\",\n",
" metrics=[\"accuracy\"],\n",
" )\n",
" return model"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Combien de paramètre un modèle avec la couche de [`BatchNormalization`](https://keras.io/api/layers/normalization_layers/batch_normalization/) a-t-il ? Est-ce équivalent à un modèle sans [`BatchNormalization`](https://keras.io/api/layers/normalization_layers/batch_normalization/) ? "
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential_11\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential_11\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_18 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">320</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ batch_normalization_3 │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span> │\n",
"│ (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">BatchNormalization</span>) │ │ │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ conv2d_19 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">28</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">9,248</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ max_pooling2d_11 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">MaxPooling2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">14</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">32</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_11 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Flatten</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">6272</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_22 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">64</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">401,472</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_23 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">650</span> │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"</pre>\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_18 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m320\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ batch_normalization_3 │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m128\u001b[0m │\n",
"│ (\u001b[38;5;33mBatchNormalization\u001b[0m) │ │ │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ conv2d_19 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m28\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m9,248\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ max_pooling2d_11 (\u001b[38;5;33mMaxPooling2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m14\u001b[0m, \u001b[38;5;34m32\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_11 (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m6272\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_22 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m64\u001b[0m) │ \u001b[38;5;34m401,472\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_23 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m) │ \u001b[38;5;34m650\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">411,818</span> (1.57 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m411,818\u001b[0m (1.57 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">411,754</span> (1.57 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m411,754\u001b[0m (1.57 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">64</span> (256.00 B)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m64\u001b[0m (256.00 B)\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"model_normalized = get_model(normalization=True, learning_rate=1e-3)\n",
"\n",
"model_normalized.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pour s'affranchir un peu de l'aléatoire, nous proposons de lancer trois fois les deux types de modèles pour les comparer.\n",
"\n",
"**Consigne** : Écrire une boucle d'entraînement qui va stocker dans une liste les courbes d'apprentissage. Chaque élément de la liste correspondra à un dictionnaire avec pour clé:\n",
"* *type*: le type du réseau (avec ou sans BatchNormalization)\n",
"* *history*: l'historique d'apprentissage"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 25ms/step - accuracy: 0.8519 - loss: 0.4220 - val_accuracy: 0.8890 - val_loss: 0.3176\n",
"Epoch 2/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 25ms/step - accuracy: 0.9057 - loss: 0.2612 - val_accuracy: 0.9048 - val_loss: 0.2682\n",
"Epoch 3/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 25ms/step - accuracy: 0.9229 - loss: 0.2076 - val_accuracy: 0.9071 - val_loss: 0.2575\n",
"Epoch 4/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9386 - loss: 0.1689 - val_accuracy: 0.9178 - val_loss: 0.2389\n",
"Epoch 5/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9499 - loss: 0.1365 - val_accuracy: 0.9142 - val_loss: 0.2515\n",
"Epoch 1/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 25ms/step - accuracy: 0.8575 - loss: 0.4019 - val_accuracy: 0.8900 - val_loss: 0.2951\n",
"Epoch 2/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9098 - loss: 0.2486 - val_accuracy: 0.9018 - val_loss: 0.2785\n",
"Epoch 3/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9287 - loss: 0.1943 - val_accuracy: 0.9118 - val_loss: 0.2507\n",
"Epoch 4/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 23ms/step - accuracy: 0.9410 - loss: 0.1596 - val_accuracy: 0.9111 - val_loss: 0.2514\n",
"Epoch 5/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m20s\u001b[0m 27ms/step - accuracy: 0.9524 - loss: 0.1258 - val_accuracy: 0.9097 - val_loss: 0.2765\n",
"Epoch 1/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m21s\u001b[0m 26ms/step - accuracy: 0.8556 - loss: 0.4125 - val_accuracy: 0.8885 - val_loss: 0.3105\n",
"Epoch 2/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9057 - loss: 0.2611 - val_accuracy: 0.9078 - val_loss: 0.2556\n",
"Epoch 3/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m18s\u001b[0m 24ms/step - accuracy: 0.9241 - loss: 0.2071 - val_accuracy: 0.9078 - val_loss: 0.2501\n",
"Epoch 4/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 26ms/step - accuracy: 0.9381 - loss: 0.1680 - val_accuracy: 0.9144 - val_loss: 0.2460\n",
"Epoch 5/5\n",
"\u001b[1m750/750\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m19s\u001b[0m 25ms/step - accuracy: 0.9491 - loss: 0.1378 - val_accuracy: 0.9134 - val_loss: 0.2607\n",
"Epoch 1/5\n"
]
}
],
"source": [
"training_curves = []\n",
"\n",
"num_trainings = 3\n",
"epochs = 5\n",
"batch_size = 64\n",
"\n",
"for normalized in [True, False]:\n",
" for _ in range(num_trainings):\n",
" model = get_model(normalization=normalized, learning_rate=1e-3)\n",
" history = model.fit(\n",
" X_train,\n",
" y_train,\n",
" epochs=epochs,\n",
" batch_size=batch_size,\n",
" validation_data=(X_valid, y_valid),\n",
" )\n",
" training_curves.append({\n",
" 'history': history,\n",
" 'normalization': normalized\n",
" })"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Il faut maintenant visualiser les résultats. Commençons par préparer les données.\n",
"\n",
"**Consigne** : Définir une fonction `agregate_result` qui prend en paramètre:\n",
"* *results*: le dictionnaire de résultat, au format décrit précédemment\n",
"* *network_type*: chaîne de caractère identifiant le type de réseau\n",
"* *metric_name*: le nom de la métrique d'intérêt\n",
"\n",
"La fonction renverra deux matrices de tailles (nombre de comparaisons, nombre d'époque) : une pour le dataset d'entraînement et une pour le dataset de validation. On concatène donc les différentes courbes d'apprentissage."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Visualiser les courbes d'apprentissage en faisant apparaître des intervals de confiance. On prendra exemple sur la fonction `show_results` du TP précédent. Commenter."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pour continuer\n",
"\n",
"Choisir une ou plusieurs pistes de recherche parmi les suivantes. Il est possible de choisir une autre direction, mais elle doit être validé auparavant.\n",
"\n",
"1. Nous avons utilisé la couche [`MaxPool2D`](https://keras.io/api/layers/pooling_layers/max_pooling2d/), mais on peut se poser la question de l'utilisation de la couche [`AveragePooling2D`](https://keras.io/api/layers/pooling_layers/average_pooling2d/) voire l'absence de couche de pooling.\n",
"2. Nous avons vu en cours qu'une agencement particulier de couches permet d'avoir les meilleurs performance pour la compétition ImageNet: les ResNet. Comment écrire un réseau résiduel à la main ?\n",
"3. Dans un [billet de blog](https://www.rpisoni.dev/posts/cossim-convolution/) est proposée une alternative à la couche convolutionnelle traditionnelle. On se propose de l'implémenter et d'explorer ses capacités."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "studies",
"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.13.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}