Files
ArtStudies/M2/Deep Learning/TP2 - Convolution/TP2 - Bonus Starter _ ResNet.ipynb
Arthur DANJOU d5a6bfd339 Refactor code for improved readability and consistency across multiple Jupyter notebooks
- Added missing commas in various print statements and function calls for better syntax.
- Reformatted code to enhance clarity, including breaking long lines and aligning parameters.
- Updated function signatures to use float type for sigma parameters instead of int for better precision.
- Cleaned up comments and documentation strings for clarity and consistency.
- Ensured consistent formatting in plotting functions and data handling.
2025-12-13 23:38:17 +01:00

166 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",
"\n",
"%matplotlib inline\n",
"import seaborn as sns\n",
"\n",
"sns.set(style=\"whitegrid\")\n",
"\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,\n",
" y_train_full,\n",
" 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,\n",
" 28,\n",
" 28,\n",
" 1,\n",
")\n",
"X_valid = scaler.transform(X_valid.astype(np.float32).reshape(-1, 28 * 28)).reshape(\n",
" -1,\n",
" 28,\n",
" 28,\n",
" 1,\n",
")\n",
"X_test = scaler.transform(X_test.astype(np.float32).reshape(-1, 28 * 28)).reshape(\n",
" -1,\n",
" 28,\n",
" 28,\n",
" 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
}