Newer
Older
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"German Traffic Sign Recognition Benchmark (GTSRB)\n",
"=================================================\n",
"---\n",
"Introduction au Deep Learning (IDLE) - S. Aria, E. Maldonado, JL. Parouty - CNRS/SARI/DEVLOG - 2020\n",
"\n",
"## Episode 3 : Tracking, visualizing and save models\n",
"\n",
"Our main steps:\n",
" - Add recovery points\n",
" - Analyze the results \n",
" - Restore and run recovery pont\n",
"\n",
"## 1/ Import and init"
]
},
{
"cell_type": "code",
"source": [
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"from tensorflow.keras.callbacks import TensorBoard\n",
"\n",
"import numpy as np\n",
"\n",
"from sklearn.metrics import confusion_matrix\n",
"\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import idle.pwk as ooo\n",
"\n",
"ooo.init()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2/ Load dataset\n",
"Dataset is one of the saved dataset: RGB25, RGB35, L25, L35, etc. \n",
"First of all, we're going to use a smart dataset : **set-24x24-L** \n",
"(with a GPU, it only takes 35'' compared to more than 5' with a CPU !)"
]
},
{
"cell_type": "code",
"source": [
"%%time\n",
"\n",
"dataset ='set-24x24-RGB'\n",
"def read_dataset(name):\n",
" '''Reads h5 dataset from ./data\n",
"\n",
" Arguments: dataset name, without .h5\n",
" Returns: x_train,y_train,x_test,y_test data'''\n",
" # ---- Read dataset\n",
" filename='./data/'+name+'.h5'\n",
" with h5py.File(filename) as f:\n",
" x_train = f['x_train'][:]\n",
" y_train = f['y_train'][:]\n",
" x_test = f['x_test'][:]\n",
" y_test = f['y_test'][:]\n",
" # ---- done\n",
" print('Dataset \"{}\" is loaded. ({:.1f} Mo)\\n'.format(name,os.path.getsize(filename)/(1024*1024)))\n",
" return x_train,y_train,x_test,y_test\n",
"\n",
"x_train,y_train,x_test,y_test = read_dataset('set-48x48-L')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3/ Have a look to the dataset\n",
"Note: Data must be reshape for matplotlib"
]
},
{
"cell_type": "code",
"source": [
"print(\"x_train : \", x_train.shape)\n",
"print(\"y_train : \", y_train.shape)\n",
"print(\"x_test : \", x_test.shape)\n",
"print(\"y_test : \", y_test.shape)\n",
"\n",
"ooo.plot_images(x_train, y_train, range(12), columns=6, x_size=2, y_size=2)\n",
"ooo.plot_images(x_train, y_train, range(36), columns=12, x_size=1, y_size=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now build a model and train it...\n",
"\n",
"Some models :"
]
},
{
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": [
"# A basic model\n",
"#\n",
"def get_model_v1(lx,ly,lz):\n",
" \n",
" model = keras.models.Sequential()\n",
" model.add( keras.layers.Conv2D(96, (3,3), activation='relu', input_shape=(lx,ly,lz)))\n",
" model.add( keras.layers.MaxPooling2D((2, 2)))\n",
" model.add( keras.layers.Dropout(0.2))\n",
"\n",
" model.add( keras.layers.Conv2D(192, (3, 3), activation='relu'))\n",
" model.add( keras.layers.MaxPooling2D((2, 2)))\n",
" model.add( keras.layers.Dropout(0.2))\n",
"\n",
" model.add( keras.layers.Flatten()) \n",
" model.add( keras.layers.Dense(1500, activation='relu'))\n",
" model.add( keras.layers.Dropout(0.5))\n",
"\n",
" model.add( keras.layers.Dense(43, activation='softmax'))\n",
" return model\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5/ Prepare callbacks \n",
"We will add 2 callbacks : \n",
" - **TensorBoard** \n",
"Training logs, which can be visualised with Tensorboard. \n",
"`#tensorboard --logdir ./run/logs` \n",
" - **Model backup** \n",
" It is possible to save the model each xx epoch or at each improvement. \n",
" The model can be saved completely or partially (weight). \n",
" For full format, we can use HDF5 format."
"# To clean old logs and saved model, run this cell\n",
"#\n",
"!/bin/rm -r ./run/logs ./run/models 2>/dev/null\n",
"!/bin/ls -l ./run 2>/dev/null"
"ooo.mkdir('./run/models')\n",
"ooo.mkdir('./run/logs')\n",
"\n",
"tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n",
"\n",
"# ---- Callback ModelCheckpoint - Save best model\n",
"save_dir = \"./run/models/best-model.h5\"\n",
"bestmodel_callback = tf.keras.callbacks.ModelCheckpoint(filepath=save_dir, verbose=0, monitor='accuracy', save_best_only=True)\n",
"\n",
"# ---- Callback ModelCheckpoint - Save model each epochs\n",
"save_dir = \"./run/models/model-{epoch:04d}.h5\"\n",
"savemodel_callback = tf.keras.callbacks.ModelCheckpoint(filepath=save_dir, verbose=0, save_freq=2000*5)"
{
"cell_type": "markdown",
"metadata": {},
"source": [
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
"## 5/ Train the model\n",
"**Get the shape of my data :**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"(n,lx,ly,lz) = x_train.shape\n",
"print(\"Images of the dataset have this folowing shape : \",(lx,ly,lz))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Get and compile a model, with the data shape :**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model = get_model_v1(lx,ly,lz)\n",
"\n",
"# model.summary()\n",
"\n",
"model.compile(optimizer='adam',\n",
" loss='sparse_categorical_crossentropy',\n",
" metrics=['accuracy'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Train it :** \n",
"Note : La courbe d'apprentissage est visible en temps réel avec Tensorboard : \n",
"`#tensorboard --logdir ./run/logs` "
]
},
{
"cell_type": "code",
"source": [
"%%time\n",
"\n",
"batch_size = 64\n",
"epochs = 5\n",
"\n",
"# ---- Shuffle train data\n",
"x_train,y_train=ooo.shuffle_np_dataset(x_train,y_train)\n",
"\n",
"# ---- Train\n",
"# Note: To be faster in our example, we take only 2000 values\n",
"# but in the real world, we'd take the whole dataset!\n",
"#\n",
"history = model.fit( x_train[:2000], y_train[:2000],\n",
" batch_size=batch_size,\n",
" epochs=epochs,\n",
" verbose=1,\n",
" validation_data=(x_test[:200], y_test[:200]),\n",
" callbacks=[tensorboard_callback, bestmodel_callback, savemodel_callback] )\n",
"\n",
"model.save('./run/models/last-model.h5')"
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Evaluate it :**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"max_val_accuracy = max(history.history[\"val_accuracy\"])\n",
"print(\"Max validation accuracy is : {:.4f}\".format(max_val_accuracy))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"score = model.evaluate(x_test, y_test, verbose=0)\n",
"\n",
"print('Test loss : {:5.4f}'.format(score[0]))\n",
"print('Test accuracy : {:5.4f}'.format(score[1]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6/ History\n",
"The return of model.fit() returns us the learning history"
]
},
{
"cell_type": "code",
{
"cell_type": "markdown",
"metadata": {},
"source": [
"outputs": [],
"source": [
"reload(ooo)\n",
"y_pred = model.predict_classes(x_test)\n",
"conf_mat = confusion_matrix(y_test,y_pred, normalize=\"true\", labels=range(43))\n",
"\n",
"ooo.plot_confusion_matrix(conf_mat)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8/ Restore and evaluate\n",
"### 8.1/ List saved models :"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
{
"cell_type": "markdown",
"metadata": {},
"source": [
]
},
{
"cell_type": "code",
"loaded_model = tf.keras.models.load_model('./run/models/best-model.h5')\n",
"print(\"Loaded.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"score = loaded_model.evaluate(x_test, y_test, verbose=0)\n",
"\n",
"print('Test loss : {:5.4f}'.format(score[0]))\n",
"print('Test accuracy : {:5.4f}'.format(score[1]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"x,y = x_test[i], y_test[i]\n",
"\n",
"# ---- Do prediction\n",
"#\n",
"predictions = loaded_model.predict( np.array([x]) )\n",
"\n",
"# ---- A prediction is just the output layer\n",
"#\n",
"print(\"\\nOutput layer from model is (x100) :\\n\")\n",
"with np.printoptions(precision=2, suppress=True, linewidth=95):\n",
"\n",
"# ---- Graphic visualisation\n",
"#\n",
"print(\"\\nGraphically :\\n\")\n",
"plt.figure(figsize=(12,2))\n",
"plt.bar(range(43), predictions[0], align='center', alpha=0.5)\n",
"plt.ylabel('Probability')\n",
"plt.ylim((0,1))\n",
"plt.xlabel('Class')\n",
"plt.show()\n",
"\n",
"# ---- Predict class\n",
"#\n",
"p = np.argmax(predictions)\n",
"\n",
"# ---- Show result\n",
"#\n",
"print(\"\\nPrediction on the left, real stuff on the right :\\n\")\n",
"ooo.plot_images([x,x_meta[y]], [p,y], range(2), columns=3, x_size=3, y_size=2)\n",
"\n",
"if p==y:\n",
" print(\"YEEES ! that's right!\")\n",
"else:\n",
" print(\"oups, that's wrong ;-(\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
{
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": [
"!kill $(ps ax | grep 'tensorboard --port 18529' | grep -v grep | awk '{print $1}')"
]
},
{
"cell_type": "code",
]
},
{
"cell_type": "code",
"%tensorboard --host 0.0.0.0 --port 18529 --logdir ./run/logs"
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.7.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}