222 lines
7.8 KiB
Plaintext
222 lines
7.8 KiB
Plaintext
{
|
|
"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
|
|
}
|