Files
ArtStudies/M2/Deep Learning/TP2 - Convolution/TP2 - Bonus Starter _ ResNet.ipynb
Arthur DANJOU 8400c722a5 Refactor code formatting and improve readability in Jupyter notebooks for TP_4 and TP_5
- Adjusted indentation and line breaks for better clarity in function definitions and import statements.
- Standardized string quotes for consistency across the codebase.
- Enhanced readability of DataFrame creation and manipulation by breaking long lines into multiple lines.
- Cleaned up print statements and comments for improved understanding.
- Ensured consistent use of whitespace around operators and after commas.
2025-11-25 10:46:16 +01:00

158 lines
5.1 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Séance 2 - Bonus : ResNet à la main\n",
"\n",
"Pour poursuivre le travail du TP, on se propose d'explorer une autre manière de définir un réseau de neurones au travers d'une architecture classique de Deep Learning pour la vision : les ResNet. \n",
"\n",
"Commençons par importer et traiter les données."
]
},
{
"cell_type": "code",
"execution_count": 1,
"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 sklearn.model_selection import train_test_split\n",
"from sklearn.preprocessing import StandardScaler\n",
"from tensorflow import keras\n",
"\n",
"(X_train_full, y_train_full), (X_test, y_test) = (\n",
" keras.datasets.fashion_mnist.load_data()\n",
")\n",
"X_train, X_valid, y_train, y_valid = train_test_split(\n",
" X_train_full, y_train_full, train_size=0.8\n",
")\n",
"\n",
"scaler = StandardScaler()\n",
"X_train = scaler.fit_transform(X_train.astype(np.float32).reshape(-1, 28 * 28)).reshape(\n",
" -1, 28, 28, 1\n",
")\n",
"X_valid = scaler.transform(X_valid.astype(np.float32).reshape(-1, 28 * 28)).reshape(\n",
" -1, 28, 28, 1\n",
")\n",
"X_test = scaler.transform(X_test.astype(np.float32).reshape(-1, 28 * 28)).reshape(\n",
" -1, 28, 28, 1\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pour rappel, une architecture ResNet correspond à la succession de ResBlock qui, dans le papier d'origine, ont l'architecture suivante :\n",
"1. Une couche de convolution avec padding pour conserver la taille de l'image\n",
"2. Une couche de BatchNormalization, que l'on explicitera en cours à la séance prochaine\n",
"3. L'activation ReLU, qui ne doit donc pas être présente dans la couche de convolution\n",
"4. Une couche de convolution avec padding pour conserver la taille de l'image\n",
"5. Une couche de BatchNormalization\n",
"6. Un ajout de l'input avant le point 1 et du résultat de la dernière couche de BatchNormalization (point 5)\n",
"7. L'activation ReLU sur l'ajout\n",
"\n",
"On ne peut pas définir cette architecture si l'on utilise la méthode d'instanciation que l'on a utilisé jusqu'ici. Pour y arriver, nous avons besoin d'utiliser la version *fonctionnelle* de Keras. Par exemple avec un modèle dense :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"input = keras.layers.Input(shape=X_train.shape[1:])\n",
"flatten = keras.layers.Flatten()(input)\n",
"dense_1 = keras.layers.Dense(units=64, activation=\"relu\")(flatten)\n",
"dense_2 = keras.layers.Dense(units=64)(dense_1)\n",
"activation = keras.layers.ReLU()(dense_2)\n",
"output = keras.layers.Dense(units=10, activation=\"softmax\")(activation)\n",
"\n",
"model = keras.models.Model(inputs=[input], outputs=[output])\n",
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : En utilisant la version fonctionnelle de Keras, définir une fonction `ResidualBlock` qui prend en paramètre un argument *input* qui correspondra à une couche Keras et en second argument des *kwargs* à passer aux différentes couches de convolutions."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Définir un modèle utilisant deux ResBlock pour résoudre le problème de classification auquel on s'intéresse."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Consigne** : Après avoir compilé le modèle, lancer l'entraînement sur quelque époque pour vérifier qu'il fonctionne."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pour aller plus loin, on pourrait se demander s'il est nécessaire de réaliser ces connexions résiduelles. Pour y répondre, on conseille de construire un réseau de neurones convolutionnel *classique* et comparer les performances pour plusieurs entraînement."
]
}
],
"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
}