Newer
Older
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<img width=\"800px\" src=\"../fidle/img/00-Fidle-header-01.svg\"></img>\n",
"# <!-- TITLE --> [GTS4] - CNN with GTSRB dataset - Data augmentation \n",
"<!-- DESC --> Episode 4: Improving the results with data augmentation\n",
"<!-- AUTHOR : Jean-Luc Parouty (CNRS/SIMaP) -->\n",
"\n",
"## Objectives :\n",
" - Trying to improve training by **enhancing the data**\n",
" - Using Keras' **data augmentation utilities**, finding their limits...\n",
" \n",
"The German Traffic Sign Recognition Benchmark (GTSRB) is a dataset with more than 50,000 photos of road signs from about 40 classes. \n",
"The final aim is to recognise them ! \n",
"Description is available there : http://benchmark.ini.rub.de/?section=gtsrb&subsection=dataset\n",
"## What we're going to do :\n",
" - Increase and improve the training dataset\n",
" - Identify the limits of these tools\n",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from tensorflow import keras\n",
"from tensorflow.keras.callbacks import TensorBoard\n",
"\n",
"import numpy as np\n",
"import h5py\n",
"\n",
"from sklearn.metrics import confusion_matrix\n",
"\n",
"import seaborn as sn\n",
"sys.path.append('..')\n",
"import fidle.pwk as ooo\n",
"\n",
"ooo.init()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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",
"execution_count": null,
"metadata": {},
"outputs": [],
"def read_dataset(name):\n",
" '''Reads h5 dataset from ./data\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",
"\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"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now build a model and train it...\n",
"\n",
"This is my model ;-) "
]
},
{
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": [
"# A basic model\n",
"def get_model_v1(lx,ly,lz):\n",
" \n",
" model = keras.models.Sequential()\n",
" \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"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We prepare 2 kind callbacks : TensorBoard and Model backup"
"execution_count": null,
"metadata": {},
"outputs": [],
"%%bash\n",
"# To clean old logs and saved model, run this cell\n",
"#\n",
"/bin/rm -r ./run/logs 2>/dev/null\n",
"/bin/rm -r ./run/models 2>/dev/null\n",
"/bin/mkdir -p -m 755 ./run/logs\n",
"/bin/mkdir -p -m 755 ./run/models\n",
"echo -e \"Reset directories : ./run/logs and ./run/models .\""
]
},
{
"cell_type": "code",
"metadata": {},
"outputs": [],
"source": [
"# ---- Callback tensorboard\n",
"log_dir = \"./run/logs/tb_\" + ooo.tag_now()\n",
"tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\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": [
"## Step 5 - Load and prepare dataset\n",
"### 5.1 - Load"
"execution_count": null,
"metadata": {},
"outputs": [],
"x_train,y_train,x_test,y_test = read_dataset('set-48x48-L-LHE')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"datagen = keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,\n",
" featurewise_std_normalization=False,\n",
" width_shift_range=0.1,\n",
" height_shift_range=0.1,\n",
" zoom_range=0.2,\n",
" shear_range=0.1,\n",
" rotation_range=10.)\n",
"datagen.fit(x_train)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Get the shape of my data :**"
"execution_count": null,
"metadata": {},
"outputs": [],
"(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 :**"
"model = get_model_v3(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` "
"execution_count": null,
"metadata": {},
"outputs": [],
"batch_size = 64\n",
"epochs = 30\n",
"\n",
"#x_train,y_train=ooo.shuffle_np_dataset(x_train,y_train)\n",
"history = model.fit( datagen.flow(x_train, y_train, batch_size=batch_size),\n",
" steps_per_epoch = int(x_train.shape[0]/batch_size),\n",
" validation_data=(x_test, y_test),\n",
" callbacks=[tensorboard_callback, bestmodel_callback, savemodel_callback] )\n",
"model.save('./run/models/last-model.h5')"
]
},
{
"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": [
"The return of model.fit() returns us the learning history"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ooo.plot_history(history)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"loaded_model = tf.keras.models.load_model('./run/models/best-model.h5')\n",
"# best_model.summary()\n",
"print(\"Loaded.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"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": [
"**Plot confusion matrix**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"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": [
"---\n",
"<img width=\"80px\" src=\"../fidle/img/00-Fidle-logo-01.svg\"></img>"
]
}
],
"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",
}
},
"nbformat": 4,
"nbformat_minor": 4
}