mirror of
https://github.com/ArthurDanjou/ArtStudies.git
synced 2026-01-26 00:53:37 +01:00
- 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.
166 lines
5.1 KiB
Plaintext
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
|
|
}
|