{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Training FineNet\n", "Code for FineNet in paper \"Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge\" at ICB 2018: https://arxiv.org/pdf/1712.09401.pdf\n", "\n", "If you use whole or partial function in this code, please cite paper:\n", "\n", " @inproceedings{Nguyen_MinutiaeNet,\n", "\tauthor = {Dinh-Luan Nguyen and Kai Cao and Anil K. Jain},\n", "\ttitle = {Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge},\n", "\tbooktitle = {The 11th International Conference on Biometrics, 2018},\n", "\tyear = {2018},\n", "\t}\n", "\n", "Prepare your data as follows:\n", "- Prepare minutiae and non-minutiae image patches with any sizes. I suggest to use `44x44` size\n", "- Put all images in corresponding folers (`minu`, `non_minu`) in \n", " - `Dataset/train`,\n", " - `Dataset/test`,\n", " - `Dataset/validate`.\n", "- Run following code\n", "\n", "Beside running in this notebook, you can run via command line with file [FineNet_train.py](../FineNet/FineNet_train.py)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import sys,os\n", "sys.path.append(os.path.realpath('../FineNet'))\n", "\n", "from keras.optimizers import Adam\n", "from keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard\n", "from keras.callbacks import ReduceLROnPlateau\n", "from keras.preprocessing.image import ImageDataGenerator\n", "from FineNet_model import FineNetmodel, plot_confusion_matrix\n", "\n", "import numpy as np\n", "import os\n", "from sklearn.metrics import confusion_matrix\n", "from datetime import datetime\n", "\n", "\n", "os.environ[\"CUDA_VISIBLE_DEVICES\"] = '2'\n", "os.environ['KERAS_BACKEND'] = 'tensorflow'\n", "\n", "\n", "output_dir = '../output_FineNet/'+datetime.now().strftime('%Y%m%d-%H%M%S')\n", "\n", "# Prepare model model saving directory.\n", "save_dir = os.path.join(os.getcwd(), output_dir)\n", "log_dir = os.path.join(os.getcwd(), output_dir + '/logs')\n", "\n", "# Training parameters\n", "batch_size = 32\n", "epochs = 200\n", "num_classes = 2\n", "\n", "# Subtracting pixel mean improves accuracy\n", "subtract_pixel_mean = True\n", "\n", "# Model size, patch\n", "model_type = 'patch224batch32'\n", "\n", "\n", "# =============== DATA loading ========================\n", "\n", "train_path = '../Dataset/train/'\n", "test_path = '../Dataset/validate/'\n", "\n", "input_shape = (224, 224, 3)\n", "\n", "# Using data augmentation technique for training\n", "datagen = ImageDataGenerator(\n", " # set input mean to 0 over the dataset\n", " featurewise_center=False,\n", " # set each sample mean to 0\n", " samplewise_center=False,\n", " # divide inputs by std of dataset\n", " featurewise_std_normalization=False,\n", " # divide each input by its std\n", " samplewise_std_normalization=False,\n", " # apply ZCA whitening\n", " zca_whitening=False,\n", " # randomly rotate images in the range (deg 0 to 180)\n", " rotation_range=180,\n", " # randomly shift images horizontally\n", " width_shift_range=0.5,\n", " # randomly shift images vertically\n", " height_shift_range=0.5,\n", " # randomly flip images\n", " horizontal_flip=True,\n", " # randomly flip images\n", " vertical_flip=True)\n", "\n", "train_batches = datagen.flow_from_directory(train_path, target_size=(input_shape[0], input_shape[1]), classes=['minu', 'non_minu'], batch_size=batch_size)\n", "# Feed data from directory into batches\n", "test_gen = ImageDataGenerator()\n", "test_batches = test_gen.flow_from_directory(test_path, target_size=(input_shape[0], input_shape[1]), classes=['minu', 'non_minu'], batch_size=batch_size)\n", "\n", "\n", "# =============== end DATA loading ========================\n", "\n", "\n", "\n", "def lr_schedule(epoch):\n", " \"\"\"Learning Rate Schedule\n", " \"\"\"\n", " lr = 0.5e-2\n", " if epoch > 180:\n", " lr *= 0.5e-3\n", " elif epoch > 150:\n", " lr *= 1e-3\n", " elif epoch > 60:\n", " lr *= 5e-2\n", " elif epoch > 30:\n", " lr *= 5e-1\n", " print('Learning rate: ', lr)\n", " return lr\n", "\n", "\n", "\n", "\n", "#============== Define model ==================\n", "\n", "model = FineNetmodel(num_classes = num_classes,\n", " pretrained_path = '../Models/FineNet.h5',\n", " input_shape=input_shape)\n", "\n", "# Save model architecture\n", "#plot_model(model, to_file='./modelFineNet.pdf',show_shapes=True)\n", "\n", "model.compile(loss='categorical_crossentropy',\n", " optimizer=Adam(lr=lr_schedule(0)),\n", " metrics=['accuracy'])\n", "#model.summary()\n", "\n", "#============== End define model ==============\n", "\n", "\n", "#============== Other stuffs for loging and parameters ==================\n", "model_name = 'FineNet_%s_model.{epoch:03d}.h5' % model_type\n", "if not os.path.isdir(save_dir):\n", " os.makedirs(save_dir)\n", "if not os.path.isdir(log_dir):\n", " os.makedirs(log_dir)\n", "\n", "filepath = os.path.join(save_dir, model_name)\n", "\n", "\n", "# Show in tensorboard\n", "tensorboard = TensorBoard(log_dir=log_dir, histogram_freq=0, write_graph=True, write_images=False)\n", "\n", "# Prepare callbacks for model saving and for learning rate adjustment.\n", "checkpoint = ModelCheckpoint(filepath=filepath,\n", " monitor='val_acc',\n", " verbose=1,\n", " save_best_only=True)\n", "\n", "lr_scheduler = LearningRateScheduler(lr_schedule)\n", "\n", "lr_reducer = ReduceLROnPlateau(factor=np.sqrt(0.1),\n", " cooldown=0,\n", " patience=5,\n", " min_lr=0.5e-6)\n", "\n", "callbacks = [checkpoint, lr_reducer, lr_scheduler, tensorboard]\n", "\n", "#============== End other stuffs ==================\n", "\n", "# Begin training\n", "model.fit_generator(train_batches,\n", " validation_data=test_batches,\n", " epochs=epochs, verbose=1,\n", " callbacks=callbacks)\n", "\n", "\n", "\n", "# Plot confusion matrix\n", "score = model.evaluate_generator(test_batches)\n", "print 'Test accuracy:', score[1]\n", "predictions = model.predict_generator(test_batches)\n", "test_labels = test_batches.classes[test_batches.index_array]\n", "\n", "cm = confusion_matrix(test_labels, np.argmax(predictions,axis=1))\n", "cm_plot_labels = ['minu','non_minu']\n", "plot_confusion_matrix(cm, cm_plot_labels, title='Confusion Matrix')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.14" } }, "nbformat": 4, "nbformat_minor": 2 }