mirror of
https://github.com/ArthurDanjou/ArtStudies.git
synced 2026-01-28 08:56:10 +01:00
147 lines
5.0 KiB
Plaintext
147 lines
5.0 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": null,
|
|
"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; sns.set(style='whitegrid')\n",
|
|
"\n",
|
|
"import tensorflow as tf\n",
|
|
"from tensorflow import keras\n",
|
|
"\n",
|
|
"from sklearn.preprocessing import StandardScaler\n",
|
|
"from sklearn.model_selection import train_test_split\n",
|
|
"\n",
|
|
"(X_train_full, y_train_full), (X_test, y_test) = (keras.datasets.fashion_mnist.load_data())\n",
|
|
"X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full, train_size=0.8)\n",
|
|
"\n",
|
|
"scaler = StandardScaler()\n",
|
|
"X_train = scaler.fit_transform(X_train.astype(np.float32).reshape(-1, 28 * 28)).reshape(-1, 28, 28, 1)\n",
|
|
"X_valid = scaler.transform(X_valid.astype(np.float32).reshape(-1, 28 * 28)).reshape(-1, 28, 28, 1)\n",
|
|
"X_test = scaler.transform(X_test.astype(np.float32).reshape(-1, 28 * 28)).reshape(-1, 28, 28, 1)"
|
|
]
|
|
},
|
|
{
|
|
"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": "Python 3",
|
|
"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.9.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|