From 044e40e40c7498305a3e22f678b2d9912933a4ab Mon Sep 17 00:00:00 2001 From: Rauf Date: Mon, 29 Jun 2020 21:43:58 +0000 Subject: [PATCH] move code to tf 2.0 --- configs/deepfake_siamese.yml | 59 --- configs/paper_resnet18_softmax_only.yml | 48 -- configs/paper_resnet18_test_remaining.yml | 48 -- configs/paper_resnet18_with_softmax.yml | 48 -- configs/paper_resnet18_without_softmax.yml | 48 -- configs/plates.yml | 49 --- configs/plates_resnet18.yml | 51 --- configs/plates_resnext50.yml | 51 --- configs/plates_simple2.yml | 49 --- configs/road_signs.yml | 59 --- .../{deepfake.yml => road_signs_apollo.yml} | 36 +- configs/road_signs_resnet18.yml | 53 --- configs/road_signs_resnet34.yml | 47 -- configs/road_signs_resnext50.yml | 47 -- configs/{bengali.yml => template.yml} | 10 +- embedding_net/backbones.py | 2 +- embedding_net/datagenerators.py | 48 +- embedding_net/model.py | 416 ------------------ embedding_net/{model_new.py => models.py} | 18 +- embedding_net/utils.py | 4 +- .../test_network.ipynb | 0 images/._t-sne.png | Bin 4096 -> 0 bytes images/._t-sne_without_training.png | Bin 4096 -> 0 bytes requirements.txt | 3 +- tools/train.py | 67 ++- 25 files changed, 79 insertions(+), 1182 deletions(-) delete mode 100644 configs/deepfake_siamese.yml delete mode 100644 configs/paper_resnet18_softmax_only.yml delete mode 100644 configs/paper_resnet18_test_remaining.yml delete mode 100644 configs/paper_resnet18_with_softmax.yml delete mode 100644 configs/paper_resnet18_without_softmax.yml delete mode 100644 configs/plates.yml delete mode 100644 configs/plates_resnet18.yml delete mode 100644 configs/plates_resnext50.yml delete mode 100644 configs/plates_simple2.yml delete mode 100644 configs/road_signs.yml rename configs/{deepfake.yml => road_signs_apollo.yml} (61%) delete mode 100644 configs/road_signs_resnet18.yml delete mode 100644 configs/road_signs_resnet34.yml delete mode 100644 configs/road_signs_resnext50.yml rename configs/{bengali.yml => template.yml} (96%) delete mode 100644 embedding_net/model.py rename embedding_net/{model_new.py => models.py} (92%) rename test_network.ipynb => examples/test_network.ipynb (100%) delete mode 100644 images/._t-sne.png delete mode 100644 images/._t-sne_without_training.png diff --git a/configs/deepfake_siamese.yml b/configs/deepfake_siamese.yml deleted file mode 100644 index c1acc6c..0000000 --- a/configs/deepfake_siamese.yml +++ /dev/null @@ -1,59 +0,0 @@ -MODEL: - input_shape : [224, 224, 3] - encodings_len: 256 - mode : 'siamese' - distance_type : 'l1' - backbone_name : 'efficientnet-b3' - backbone_weights : 'noisy-student' - freeze_backbone : False - embeddings_normalization: True - -DATALOADER: - dataset_path : '/home/rauf/datasets/aaaa/deepfake/' - csv_file : - image_id_column : - label_column : - validate : True - val_ratio : 0.2 - -GENERATOR: - batch_size : 5 - n_batches : 5000 - n_batches_val : 500 - augmentations : 'deepfake' - -TRAIN: - # optimizer parameters - optimizer : 'radam' - learning_rate : 0.00016 - decay_factor : 0.95 - step_size : 1 - - # embeddings learning training parameters - n_epochs : 1000 - - # plot training history - plot_history : True - -# SOFTMAX_PRETRAINING: -# # softmax pretraining parameters -# optimizer : 'radam' -# learning_rate : 0.0001 -# decay_factor : 0.99 -# step_size : 1 - -# batch_size : 16 -# val_steps : 200 -# steps_per_epoch : 1000 -# n_epochs : 50 - -SAVE_PATHS: - project_name : 'deepfake_efn_b3' - work_dir : 'work_dirs/' - -ENCODINGS: - # encodings parameters - save_encodings : True - centers_only: False - max_num_samples_of_each_class : 30 - knn_k : 1 \ No newline at end of file diff --git a/configs/paper_resnet18_softmax_only.yml b/configs/paper_resnet18_softmax_only.yml deleted file mode 100644 index dffd1c3..0000000 --- a/configs/paper_resnet18_softmax_only.yml +++ /dev/null @@ -1,48 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 256 -margin: 0.5 -mode : 'softmax_only' -distance_type : 'l1' -backbone : 'resnet18' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'default' -min_n_obj_per_class : 30 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 500 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 8 -softmax_val_steps : 200 -softmax_steps_per_epoch : 800 -softmax_epochs : 200 - -#paths -work_dir : 'work_dirs/paper_resnet18_softmax_only/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -model_save_name : 'best_model_paper_resnet18_softmax_only.h5' -encodings_save_name: 'encodings_paper_resnet18_softmax_only.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/paper_resnet18_test_remaining.yml b/configs/paper_resnet18_test_remaining.yml deleted file mode 100644 index 90bb56b..0000000 --- a/configs/paper_resnet18_test_remaining.yml +++ /dev/null @@ -1,48 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 512 -margin: 0.5 -mode : 'triplet' -distance_type : 'l1' -backbone : 'resnet18' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'default' -min_n_obj_per_class : 0 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 30 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 500 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 8 -softmax_val_steps : 200 -softmax_steps_per_epoch : 800 -softmax_epochs : 2 - -#paths -work_dir : 'work_dirs/paper_resnet18_remaining/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -model_save_name : 'best_model_paper_resnet18_remaining.h5' -encodings_save_name: 'encodings_paper_resnet18_remaining.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/paper_resnet18_with_softmax.yml b/configs/paper_resnet18_with_softmax.yml deleted file mode 100644 index a1ef164..0000000 --- a/configs/paper_resnet18_with_softmax.yml +++ /dev/null @@ -1,48 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 256 -margin: 0.5 -mode : 'triplet' -distance_type : 'l1' -backbone : 'resnet18' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'default' -min_n_obj_per_class : 30 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 500 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 8 -softmax_val_steps : 200 -softmax_steps_per_epoch : 800 -softmax_epochs : 10 - -#paths -work_dir : 'work_dirs/paper_resnet18_with_softmax/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -model_save_name : 'best_model_paper_resnet18_with_softmax.h5' -encodings_save_name: 'encodings_paper_resnet18_with_softmax.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/paper_resnet18_without_softmax.yml b/configs/paper_resnet18_without_softmax.yml deleted file mode 100644 index 09c0b10..0000000 --- a/configs/paper_resnet18_without_softmax.yml +++ /dev/null @@ -1,48 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 256 -margin: 0.5 -mode : 'triplet' -distance_type : 'l1' -backbone : 'resnet18' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'default' -min_n_obj_per_class : 30 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 500 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : False -softmax_batch_size : 8 -softmax_val_steps : 200 -softmax_steps_per_epoch : 800 -softmax_epochs : 20 - -#paths -work_dir : 'work_dirs/paper_resnet18_without_softmax/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -model_save_name : 'best_model_paper_resnet18_without_softmax.h5' -encodings_save_name: 'encodings_paper_resnet18_without_softmax.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/plates.yml b/configs/plates.yml deleted file mode 100644 index 7a13c60..0000000 --- a/configs/plates.yml +++ /dev/null @@ -1,49 +0,0 @@ -input_shape : [128, 128, 3] -encodings_len: 128 -margin: 0.5 -mode : 'triplet' -distance_type : 'l2' -backbone : 'simple2' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'plates' -min_n_obj_per_class : 0 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 10 -negatives_selection_mode : 'semihard' -mining_n_classes: 2 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 8 -softmax_val_steps : 1 -softmax_steps_per_epoch : 500 -softmax_epochs : 5 - -#paths -# paths -work_dir : 'work_dirs/plates/' -dataset_path : '/home/rauf/datasets/plates/plates_splitted/' -plot_history : True -model_save_name : 'best_model_plates_simple2.h5' -encodings_save_name: 'encodings_plates_simple2.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/plates_resnet18.yml b/configs/plates_resnet18.yml deleted file mode 100644 index f601232..0000000 --- a/configs/plates_resnet18.yml +++ /dev/null @@ -1,51 +0,0 @@ -input_shape : [128, 128, 3] -encodings_len: 128 -margin: 0.4 -mode : 'triplet' -distance_type : 'l2' -backbone : 'resnet18' -backbone_weights : 'imagenet' -freeze_backbone : True -augmentation_type : 'plates2' -min_n_obj_per_class : 0 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True -to_validate : False - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99999 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 16 -val_steps : 10 -negatives_selection_mode : 'semihard' -mining_n_classes: 2 -mining_n_samples: 7 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size_train : 32 -softmax_batch_size_val : 16 -softmax_val_steps : 50 -softmax_steps_per_epoch : 100 -softmax_epochs : 100 -softmax_is_binary: True - -# paths -work_dir : 'work_dirs/plates/' -dataset_path : '/home/rauf/datasets/plates/plates_splitted/' -plot_history : True -model_save_name : 'best_model_plates_resnet18.h5' -encodings_save_name: 'encodings_plates_resnet18.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/plates_resnext50.yml b/configs/plates_resnext50.yml deleted file mode 100644 index abb7cbd..0000000 --- a/configs/plates_resnext50.yml +++ /dev/null @@ -1,51 +0,0 @@ -input_shape : [128, 128, 3] -encodings_len: 128 -margin: 0.4 -mode : 'triplet' -distance_type : 'l2' -backbone : 'resnext50' -backbone_weights : 'imagenet' -freeze_backbone : True -augmentation_type : 'plates2' -min_n_obj_per_class : 0 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True -to_validate : False - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99999 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 16 -val_steps : 10 -negatives_selection_mode : 'semihard' -mining_n_classes: 2 -mining_n_samples: 5 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size_train : 8 -softmax_batch_size_val : 4 -softmax_val_steps : 50 -softmax_steps_per_epoch : 200 -softmax_epochs : 100 -softmax_is_binary: True - -# paths -work_dir : 'work_dirs/plates_resnext50/' -dataset_path : '/home/rauf/datasets/plates/plates_splitted/' -plot_history : True -model_save_name : 'best_model_plates_resnext50.h5' -encodings_save_name: 'encodings_plates_resnext50.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/plates_simple2.yml b/configs/plates_simple2.yml deleted file mode 100644 index a49fee0..0000000 --- a/configs/plates_simple2.yml +++ /dev/null @@ -1,49 +0,0 @@ -input_shape : [128, 128, 3] -encodings_len: 64 -margin: 0.4 -mode : 'triplet' -distance_type : 'l1' -backbone : 'simple2' -backbone_weights : 'imagenet' -freeze_backbone : False -augmentation_type : 'plates' -min_n_obj_per_class : 0 -select_max_n_obj_per_class : 30 -max_n_obj_per_class : 10000 -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 10 -negatives_selection_mode : 'semihard' -mining_n_classes: 2 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 16 -softmax_val_steps : 1 -softmax_steps_per_epoch : 100 -softmax_epochs : 20 -softmax_is_binary: True -#paths -# paths -work_dir : 'work_dirs/plates/' -dataset_path : '/home/rauf/datasets/plates/plates_splitted/' -plot_history : True -model_save_name : 'best_model_plates_simple2.h5' -encodings_save_name: 'encodings_plates_simple2.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/road_signs.yml b/configs/road_signs.yml deleted file mode 100644 index f5a3e79..0000000 --- a/configs/road_signs.yml +++ /dev/null @@ -1,59 +0,0 @@ -MODEL: - input_shape : [48, 48, 3] - encodings_len: 256 - mode : 'triplet' - distance_type : 'l1' - backbone_name : 'efficientnet-b0' - backbone_weights : 'imagenet' - freeze_backbone : False - embeddings_normalization: True - -DATALOADER: - dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/train/' - validate : True - val_ratio : 0.2 - -GENERATOR: - negatives_selection_mode : 'semihard' - k_classes: 2 - k_samples: 3 - margin: 0.5 - batch_size : 1 - n_batches : 1 - augmentations : 'none' - -TRAIN: - # optimizer parameters - optimizer : 'adam' - learning_rate : 0.0001 - decay_factor : 0.99 - step_size : 1 - - # embeddings learning training parameters - n_epochs : 1000 - - # plot training history - plot_history : True - -SOFTMAX_PRETRAINING: - # softmax pretraining parameters - optimizer : 'radam' - learning_rate : 0.0001 - decay_factor : 0.99 - step_size : 1 - - batch_size : 8 - val_steps : 200 - steps_per_epoch : 10 - n_epochs : 1 - -SAVE_PATHS: - project_name : 'road_signs_efficientnet' - work_dir : 'work_dirs/' - -ENCODINGS: - # encodings parameters - save_encodings : True - centers_only: False - max_num_samples_of_each_class : 30 - knn_k : 1 \ No newline at end of file diff --git a/configs/deepfake.yml b/configs/road_signs_apollo.yml similarity index 61% rename from configs/deepfake.yml rename to configs/road_signs_apollo.yml index a491a1c..06a56de 100644 --- a/configs/deepfake.yml +++ b/configs/road_signs_apollo.yml @@ -1,34 +1,35 @@ MODEL: - input_shape : [224, 224, 3] + input_shape : [48, 48, 3] encodings_len: 256 mode : 'triplet' - distance_type : 'l2' - backbone_name : 'efficientnet-b3' + distance_type : 'l1' + backbone_name : 'efficientnet-b0' backbone_weights : 'noisy-student' freeze_backbone : False embeddings_normalization: True DATALOADER: - dataset_path : '/home/rauf/datasets/aaaa/deepfake/' - csv_file : - image_id_column : - label_column : + dataset_path : '/home/rauf/datasets/RTSD/' + train_csv_file : '/home/rauf/datasets/RTSD/split_1/train.csv' + val_csv_file : '/home/rauf/datasets/RTSD/split_1/val.csv' + image_id_column : 'file_path' + label_column : 'class_name' validate : True val_ratio : 0.2 GENERATOR: - negatives_selection_mode : 'hardest' - k_classes: 2 + negatives_selection_mode : 'semihard' + k_classes: 10 k_samples: 3 margin: 0.5 batch_size : 8 - n_batches : 7000 - augmentations : 'deepfake' + n_batches : 500 + augmentations : 'none' TRAIN: # optimizer parameters optimizer : 'radam' - learning_rate : 0.000016 + learning_rate : 0.0001 decay_factor : 0.99 step_size : 1 @@ -50,13 +51,14 @@ TRAIN: # steps_per_epoch : 1000 # n_epochs : 50 -SAVE_PATHS: - project_name : 'deepfake_efn_b3' - work_dir : 'work_dirs/' - ENCODINGS: # encodings parameters save_encodings : True centers_only: False max_num_samples_of_each_class : 30 - knn_k : 1 \ No newline at end of file + knn_k : 1 + +GENERAL: + project_name : 'road_signs_efnb0' + work_dir : 'work_dirs/' + tensorboard_callback: False \ No newline at end of file diff --git a/configs/road_signs_resnet18.yml b/configs/road_signs_resnet18.yml deleted file mode 100644 index f6c0a2b..0000000 --- a/configs/road_signs_resnet18.yml +++ /dev/null @@ -1,53 +0,0 @@ -MODEL: - encodings_len: 256 - mode : 'triplet' - distance_type : 'l1' - backbone : 'resnet18' - backbone_weights : 'imagenet' - freeze_backbone : False - embeddings_normalization: True - -TRAIN: - input_shape : [48, 48, 3] - margin: 0.5 - augmentation_type : 'default' - - # optimizer parameters - optimizer : 'radam' - learning_rate : 0.0001 - decay_factor : 0.99 - step_size : 1 - - # embeddings learning training parameters - n_epochs : 1000 - n_steps_per_epoch : 200 - val_batch_size : 8 - val_steps : 200 - negatives_selection_mode : 'semihard' - mining_n_classes: 5 - mining_n_samples: 3 - - # softmax pretraining parameters - softmax_pretraining : True - softmax_batch_size : 8 - softmax_val_steps : 200 - softmax_steps_per_epoch : 500 - softmax_epochs : 20 - - # plot training history - plot_history : True - -PATHS: - work_dir : 'work_dirs/road_signs_resnet18/' - dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' - csv_file : '/home/rauf/datasets/road_signs/road_signs_separated/' - encodings_path : 'encodings/' - model_save_name : 'best_model_resnet18.h5' - encodings_save_name: 'encodings_resnet18.pkl' - -ENCODINGS: - # encodings parameters - save_encodings : True - centers_only: False - max_num_samples_of_each_class : 30 - knn_k : 1 \ No newline at end of file diff --git a/configs/road_signs_resnet34.yml b/configs/road_signs_resnet34.yml deleted file mode 100644 index 5c738f4..0000000 --- a/configs/road_signs_resnet34.yml +++ /dev/null @@ -1,47 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 256 -margin: 0.5 -mode : 'triplet' -distance_type : 'l1' -backbone : 'resnet34' -backbone_weights : 'imagenet' -project_name : 'road_signs/' -freeze_backbone : False -augmentation_type : 'default' -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.0001 -decay_factor : 0.99 -step_size : 1 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 50 -val_batch_size : 8 -val_steps : 200 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 16 -softmax_val_steps : 200 -softmax_steps_per_epoch : 500 -softmax_epochs : 20 - -#paths -work_dir : 'work_dirs/road_signs_resnext34/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -encodings_path : 'encodings/' -model_save_name : 'best_model_resnet34.h5' -encodings_save_name: 'encodings_resnet34.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/road_signs_resnext50.yml b/configs/road_signs_resnext50.yml deleted file mode 100644 index 39db509..0000000 --- a/configs/road_signs_resnext50.yml +++ /dev/null @@ -1,47 +0,0 @@ -input_shape : [48, 48, 3] -encodings_len: 256 -margin: 0.4 -mode : 'triplet' -distance_type : 'l1' -backbone : 'resnext50' -backbone_weights : 'imagenet' -project_name : 'road_signs/' -freeze_backbone : False -augmentation_type : 'default' -embeddings_normalization: True - -# optimizer parameters -optimizer : 'radam' -learning_rate : 0.001 -decay_factor : 0.95 -step_size : 2 - -# embeddings learning training parameters -n_epochs : 1000 -n_steps_per_epoch : 200 -val_batch_size : 8 -val_steps : 200 -negatives_selection_mode : 'semihard' -mining_n_classes: 5 # training batch_size = mining_n_classes * mining_n_samples -mining_n_samples: 3 - -# softmax pretraining parameters -softmax_pretraining : True -softmax_batch_size : 8 -softmax_val_steps : 200 -softmax_steps_per_epoch : 500 -softmax_epochs : 20 - -#paths -work_dir : 'work_dirs/road_signs_resnext50/' -dataset_path : '/home/rauf/datasets/road_signs/road_signs_separated/' -plot_history : True -encodings_path : 'encodings/' -model_save_name : 'best_model_resnext50.h5' -encodings_save_name: 'encodings_resnext50.pkl' - -# encodings parameters -save_encodings : True -centers_only: False -max_num_samples_of_each_class : 30 -knn_k : 1 \ No newline at end of file diff --git a/configs/bengali.yml b/configs/template.yml similarity index 96% rename from configs/bengali.yml rename to configs/template.yml index 8f8e408..1103857 100644 --- a/configs/bengali.yml +++ b/configs/template.yml @@ -50,13 +50,13 @@ TRAIN: # steps_per_epoch : 1000 # n_epochs : 50 -SAVE_PATHS: - project_name : 'bengali_efn_b5' - work_dir : 'work_dirs/' - ENCODINGS: # encodings parameters save_encodings : True centers_only: False max_num_samples_of_each_class : 30 - knn_k : 1 \ No newline at end of file + knn_k : 1 + +GENERAL: + project_name : 'bengali_efn_b5' + work_dir : 'work_dirs/' \ No newline at end of file diff --git a/embedding_net/backbones.py b/embedding_net/backbones.py index 5ef98a1..992f03f 100644 --- a/embedding_net/backbones.py +++ b/embedding_net/backbones.py @@ -120,7 +120,7 @@ def get_backbone(input_shape, base_model = Model( inputs=[backbone_model.input], outputs=[encoded_output]) - base_model._make_predict_function() + # base_model._make_predict_function() return base_model, backbone_model diff --git a/embedding_net/datagenerators.py b/embedding_net/datagenerators.py index 0482171..d91ac4c 100644 --- a/embedding_net/datagenerators.py +++ b/embedding_net/datagenerators.py @@ -13,7 +13,8 @@ class ENDataLoader(): def __init__(self, dataset_path, - csv_file=None, + train_csv_file=None, + val_csv_file=None, image_id_column = 'image_id', label_column = 'label', validate = True, @@ -23,10 +24,10 @@ def __init__(self, dataset_path, self.class_files_paths = {} self.class_names = [] - if csv_file is not None: - self._load_from_dataframe(csv_file, image_id_column, label_column) + if train_csv_file is not None: + self.class_files_paths = self._load_from_dataframe(train_csv_file, image_id_column, label_column) else: - self._load_from_directory() + self.class_files_paths = self._load_from_directory() self.n_classes = len(self.class_names) self.n_samples = {k: len(v) for k, v in self.class_files_paths.items()} @@ -35,7 +36,11 @@ def __init__(self, dataset_path, self.val_ratio = val_ratio if self.validate: - self.train_data, self.val_data = self.split_train_val(self.val_ratio) + if val_csv_file is not None: + self.train_data = self.class_files_paths + self.val_data = self._load_from_dataframe(val_csv_file, image_id_column, label_column) + else: + self.train_data, self.val_data = self.split_train_val(self.val_ratio) else: self.train_data = self.class_files_paths self.val_data = {} @@ -43,8 +48,6 @@ def __init__(self, dataset_path, def split_train_val(self, val_ratio): train_data = {} val_data = {} - print(len(self.class_files_paths['real'])) - print(len(self.class_files_paths['fake'])) for k, v in self.class_files_paths.items(): train_d, val_d = train_test_split(v, test_size=val_ratio, random_state=42) train_data[k] = train_d @@ -52,20 +55,22 @@ def split_train_val(self, val_ratio): return train_data, val_data def _load_from_dataframe(self, csv_file, image_id_column, label_column): + class_files_paths = {} dataframe = pd.read_csv(csv_file) self.class_names = list(dataframe[label_column].unique()) for class_name in self.class_names: image_names = dataframe.loc[dataframe[label_column] == class_name][image_id_column] image_paths = [os.path.join(self.dataset_path, f) for f in image_names] - self.class_files_paths[class_name] = image_paths + class_files_paths[class_name] = image_paths + return class_files_paths def _load_from_directory(self): + class_files_paths = {} self.class_names = [f.name for f in os.scandir(self.dataset_path) if f.is_dir()] class_dir_paths = [f.path for f in os.scandir(self.dataset_path) if f.is_dir()] for class_name, class_dir_path in zip(self.class_names, class_dir_paths): subdirs = [f.path for f in os.scandir(class_dir_path) if f.is_dir()] - # self.class_files_paths[class_name] = [] temp_list = [] print(class_dir_path) if len(subdirs)>0: @@ -81,7 +86,8 @@ def _load_from_directory(self): f.name.endswith('.png') and not f.name.startswith('._'))] temp_list.extend(class_image_paths) - self.class_files_paths[class_name] = temp_list + class_files_paths[class_name] = temp_list + return class_files_paths class ENDataGenerator(Sequence): @@ -157,8 +163,6 @@ def __init__(self, embedding_model, self.k_samples = k_samples self.margin = margin self.negative_selection_fn = modes[negatives_selection_mode] - self.session = K.get_session() - self.graph = tf.get_default_graph() def hardest_negative(self, loss_values, margin=0.5): hard_negative = np.argmax(loss_values) @@ -187,9 +191,7 @@ def get_batch_triplets_mining(self): for idx, cl_img_idxs in enumerate(selected_images): images = self._get_images_set(selected_classes[idx], cl_img_idxs, with_aug=self.augmentations) all_images_list.append(images) - with self.session.as_default(): - with self.graph.as_default(): - embeddings = self.embedding_model.predict(images) + embeddings = self.embedding_model.predict(images) all_embeddings_list.append(embeddings) all_embeddings = np.vstack(all_embeddings_list) @@ -326,12 +328,6 @@ def get_batch_pairs(self): selected_class = self.class_names[selected_class_idx] selected_class_n_elements = self.n_samples[selected_class] - if selected_class == 'real': - t_id = 0 - f_id = 1 - else: - t_id = 1 - f_id = 0 indxs = np.random.randint(selected_class_n_elements, size=self.batch_size) with_aug = self.augmentations @@ -343,8 +339,6 @@ def get_batch_pairs(self): pairs[0][count, :, :, :] = imgs[0] pairs[1][count, :, :, :] = imgs[1] targets[i] = 1 - targets1[i] = t_id - targets2[i] = t_id count += 1 for i in range(n_same_class, self.batch_size): @@ -357,14 +351,8 @@ def get_batch_pairs(self): pairs[0][count, :, :, :] = imgs[0] pairs[1][count, :, :, :] = imgs[1] targets[i] = 0 - targets1[i] = t_id - targets2[i] = f_id count += 1 - return pairs, {'output_siamese' : targets, - 'output_im1' : targets1, - 'output_im2' : targets2} - # 'model_1' : targets1, - # 'model_1_1' : targets2}) + return pairs, targets def __getitem__(self, index): return self.get_batch_pairs() diff --git a/embedding_net/model.py b/embedding_net/model.py deleted file mode 100644 index db4274e..0000000 --- a/embedding_net/model.py +++ /dev/null @@ -1,416 +0,0 @@ -import os -import numpy as np -import keras.backend as K -import cv2 -import random -import keras -from keras.models import Model, load_model -from keras import optimizers -from keras.layers import Dense, Input, Lambda, concatenate -import pickle -from .utils import load_encodings -from .backbones import get_backbone -from . import losses_and_accuracies as lac -import matplotlib.pyplot as plt -from sklearn.neighbors import KNeighborsClassifier -from keras.callbacks import TensorBoard, LearningRateScheduler -from keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint - -# TODO -# [] - implement magnet loss -# [] - finalize settings with l1 and l2 losses - - -class EmbeddingNet: - """ - SiameseNet for image classification - distance_type = 'l1' -> l1_loss - distance_type = 'l2' -> l2_loss - - mode = 'siamese' -> Siamese network - mode = 'triplet' -> Triplen network - """ - - def __init__(self, cfg_params, training = True): - self.input_shape = cfg_params['input_shape'] - self.encodings_len = cfg_params['encodings_len'] - self.backbone = cfg_params['backbone'] - self.backbone_weights = cfg_params['backbone_weights'] - self.distance_type = cfg_params['distance_type'] - self.mode = cfg_params['mode'] - self.optimizer = cfg_params['optimizer'] - self.freeze_backbone = cfg_params['freeze_backbone'] - self.data_loader = cfg_params['loader'] - self.embeddings_normalization = cfg_params['embeddings_normalization'] - self.margin = cfg_params['margin'] - self.cfg_params = cfg_params - - self.model = [] - self.base_model = [] - self.backbone_model = [] - - if self.mode == 'siamese': - self._create_model_siamese() - elif self.mode == 'triplet': - self._create_model_triplet() - else: - self._create_base_model() - - self.encoded_training_data = {} - - if cfg_params['softmax_pretraining'] and training: - self.pretrain_backbone_softmax() - - def pretrain_backbone_softmax(self): - input_shape = self.cfg_params['input_shape'] - dataset_path = self.cfg_params['dataset_path'] - n_classes = self.data_loader.n_classes['train'] - if 'softmax_is_binary' in self.cfg_params: - is_binary = self.cfg_params['softmax_is_binary'] - else: - is_binary = False - - x = keras.layers.GlobalAveragePooling2D()(self.backbone_model.output) - if is_binary: - output = keras.layers.Dense(1, activation='softmax')(x) - else: - output = keras.layers.Dense(n_classes, activation='softmax')(x) - model = keras.models.Model(inputs=[self.backbone_model.input], outputs=[output]) - - # train - mloss = 'binary_crossentropy' if is_binary else 'categorical_crossentropy' - model.compile(optimizer='Adam', - loss=mloss, metrics=['accuracy']) - - batch_size_train = self.cfg_params['softmax_batch_size_train'] - batch_size_val = self.cfg_params['softmax_batch_size_val'] - val_steps = self.cfg_params['softmax_val_steps'] - steps_per_epoch = self.cfg_params['softmax_steps_per_epoch'] - epochs = self.cfg_params['softmax_epochs'] - - train_generator = self.data_loader.generate(batch_size_train,is_binary=is_binary, mode='simple', s="train") - if 'val' in self.data_loader.data_subsets and self.cfg_params['to_validate']: - val_generator = self.data_loader.generate(batch_size_val,is_binary=is_binary, mode='simple', s="val") - checkpoint_callback_monitor = 'val_loss' - else: - val_generator = None - checkpoint_callback_monitor = 'loss' - - tensorboard_save_path = os.path.join( - self.cfg_params['work_dir'], 'tf_log/pretraining_model/') - weights_save_file = os.path.join( - self.cfg_params['work_dir'], - 'weights/pretraining_model/', - self.cfg_params['model_save_name']) - - initial_lr = self.cfg_params['learning_rate'] - decay_factor = self.cfg_params['decay_factor'] - step_size = self.cfg_params['step_size'] - - callbacks = [ - LearningRateScheduler(lambda x: initial_lr * - decay_factor ** np.floor(x/step_size)), - ReduceLROnPlateau(monitor=checkpoint_callback_monitor, factor=0.1, - patience=20, verbose=1), - EarlyStopping(monitor=checkpoint_callback_monitor, - patience=10, - verbose=1, - restore_best_weights=True), - TensorBoard(log_dir=tensorboard_save_path), - ModelCheckpoint(filepath=weights_save_file, - verbose=1, - monitor=checkpoint_callback_monitor, - save_best_only=True) - ] - - history = model.fit_generator(train_generator, - steps_per_epoch=steps_per_epoch, - epochs=epochs, - verbose=1, - validation_data=val_generator, - validation_steps=val_steps, - callbacks=callbacks) - - def _create_base_model(self): - self.base_model, self.backbone_model = get_backbone(input_shape=self.input_shape, - encodings_len=self.encodings_len, - backbone_name=self.backbone, - embeddings_normalization=self.embeddings_normalization, - backbone_weights=self.backbone_weights, - freeze_backbone=self.freeze_backbone) - - def _create_model_siamese(self): - - input_image_1 = Input(self.input_shape) - input_image_2 = Input(self.input_shape) - - self._create_base_model() - self.base_model._make_predict_function() - - image_encoding_1 = self.base_model(input_image_1) - image_encoding_2 = self.base_model(input_image_2) - - if self.distance_type == 'l1': - L1_layer = Lambda( - lambda tensors: K.abs(tensors[0] - tensors[1])) - distance = L1_layer([image_encoding_1, image_encoding_2]) - - prediction = Dense(units=1, activation='sigmoid')(distance) - metric = 'binary_accuracy' - - elif self.distance_type == 'l2': - - L2_layer = Lambda( - lambda tensors: K.sqrt(K.maximum(K.sum(K.square(tensors[0] - tensors[1]), axis=1, keepdims=True), K.epsilon()))) - distance = L2_layer([image_encoding_1, image_encoding_2]) - - prediction = distance - metric = lac.accuracy - - self.model = Model( - inputs=[input_image_1, input_image_2], outputs=prediction) - - print('Base model summary') - self.base_model.summary() - - print('Whole model summary') - self.model.summary() - - self.model.compile(loss=lac.contrastive_loss, metrics=[metric], - optimizer=self.optimizer) - - def _create_model_triplet(self): - input_image_a = Input(self.input_shape) - input_image_p = Input(self.input_shape) - input_image_n = Input(self.input_shape) - - self._create_base_model() - self.base_model._make_predict_function() - image_encoding_a = self.base_model(input_image_a) - image_encoding_p = self.base_model(input_image_p) - image_encoding_n = self.base_model(input_image_n) - - merged_vector = concatenate([image_encoding_a, image_encoding_p, image_encoding_n], - axis=-1, name='merged_layer') - self.model = Model(inputs=[input_image_a, input_image_p, input_image_n], - outputs=merged_vector) - - print('Base model summary') - self.base_model.summary() - - print('Whole model summary') - self.model.summary() - - self.model.compile(loss=lac.triplet_loss( - self.margin), optimizer=self.optimizer) - - def train_on_batch(self, batch_size=8, s="train"): - generator = self.data_loader.generate(batch_size, s=s) - pairs, targets = next(generator) - train_loss, train_accuracy = self.model.train_on_batch( - pairs, targets) - return train_loss, train_accuracy - - def validate_on_batch(self, batch_size=8, s="val"): - generator = self.data_loader.generate(batch_size, s=s) - pairs, targets = next(generator) - val_loss, val_accuracy = self.model.test_on_batch( - pairs, targets) - return val_loss, val_accuracy - - def train_generator(self, - steps_per_epoch, - epochs, - callbacks=[], - val_steps=100, - batch_size=8, - verbose=1): - - train_generator = self.data_loader.generate( - batch_size, mode=self.mode, s="train") - - if 'val' in self.data_loader.data_subsets and self.cfg_params['to_validate']: - val_generator = self.data_loader.generate( - batch_size, mode=self.mode, s="val") - else: - val_generator = None - - history = self.model.fit_generator(train_generator, - steps_per_epoch=steps_per_epoch, - epochs=epochs, - verbose=verbose, - validation_data=val_generator, - validation_steps=val_steps, - callbacks=callbacks) - - return history - - def train_generator_mining(self, - steps_per_epoch, - epochs, - callbacks=[], - val_steps=100, - n_classes=4, - n_samples=4, - val_batch=8, - negative_selection_mode='semihard', - verbose=1): - - train_generator = self.data_loader.generate_mining( - self.base_model, n_classes, n_samples, margin=self.margin, negative_selection_mode=negative_selection_mode, s="train") - - if 'val' in self.data_loader.data_subsets and self.cfg_params['to_validate']: - val_generator = self.data_loader.generate( - val_batch, mode=self.mode, s="val") - else: - val_generator = None - - history = self.model.fit_generator(train_generator, - steps_per_epoch=steps_per_epoch, - epochs=epochs, - verbose=verbose, - validation_data=val_generator, - validation_steps=val_steps, - callbacks=callbacks) - return history - - def validate(self, number_of_comparisons=100, batch_size=4, s="val"): - generator = self.data_loader.generate(batch_size, s=s) - val_accuracies_it = [] - val_losses_it = [] - for _ in range(number_of_comparisons): - pairs, targets = next(generator) - - val_loss_it, val_accuracy_it = self.model.test_on_batch( - pairs, targets) - val_accuracies_it.append(val_accuracy_it) - val_losses_it.append(val_loss_it) - val_loss_epoch = sum(val_losses_it) / len(val_losses_it) - val_accuracy_epoch = sum( - val_accuracies_it) / len(val_accuracies_it) - return val_loss_epoch, val_accuracy_epoch - - - def _generate_encoding(self, img_path): - img = self.data_loader.get_image(img_path) - if img is None: - return None - encoding = self.base_model.predict(np.expand_dims(img, axis=0)) - return encoding - - - def generate_encodings(self, save_file_name='encodings.pkl', only_centers=False, max_num_samples_of_each_class=10, knn_k=1, shuffle=True): - data_paths, data_labels, data_encodings = [], [], [] - classes_counter = {} - classes_encodings = {} - k_val = 1 if only_centers else knn_k - - if shuffle: - c = list(zip( - self.data_loader.images_paths['train'], self.data_loader.images_labels['train'])) - random.shuffle(c) - self.data_loader.images_paths['train'], self.data_loader.images_labels['train'] = zip( - *c) - - for img_path, img_label in zip(self.data_loader.images_paths['train'], - self.data_loader.images_labels['train']): - if only_centers: - if img_label not in classes_encodings: - classes_encodings[img_label] = [] - else: - if img_label not in classes_counter: - classes_counter[img_label] = 0 - if classes_counter[img_label] < max_num_samples_of_each_class: - encod = self._generate_encoding(img_path) - - if encod is not None: - if only_centers: - classes_encodings[img_label].append(encod) - else: - data_paths.append(img_path) - data_labels.append(img_label) - data_encodings.append(encod) - classes_counter[img_label] += 1 - if only_centers: - for class_i, encodings_i in classes_encodings.items(): - encodings_i_np = np.array(encodings_i) - class_encoding = np.mean(encodings_i_np, axis = 0) - data_encodings.append(class_encoding) - data_labels.append(class_i) - self.encoded_training_data['paths'] = data_paths - self.encoded_training_data['labels'] = data_labels - self.encoded_training_data['encodings'] = np.squeeze( - np.array(data_encodings)) - self.encoded_training_data['knn_classifier'] = KNeighborsClassifier( - n_neighbors=k_val) - self.encoded_training_data['knn_classifier'].fit(self.encoded_training_data['encodings'], - self.encoded_training_data['labels']) - with open(save_file_name, "wb") as f: - pickle.dump(self.encoded_training_data, f) - - def load_encodings(self, path_to_encodings): - self.encoded_training_data = load_encodings(path_to_encodings) - - def load_model(self, file_path): - from keras_radam import RAdam - self.model = load_model(file_path, - custom_objects={'contrastive_loss': lac.contrastive_loss, - 'accuracy': lac.accuracy, - 'loss_function': lac.triplet_loss(self.margin), - 'RAdam': RAdam}) - self.input_shape = list(self.model.inputs[0].shape[1:]) - self.base_model = Model(inputs=[self.model.layers[3].get_input_at(0)], - outputs=[self.model.layers[3].layers[-1].output]) - self.base_model._make_predict_function() - - def calculate_distances(self, encoding): - training_encodings = self.encoded_training_data['encodings'] - return np.sqrt( - np.sum((training_encodings - np.array(encoding))**2, axis=1)) - - def predict(self, image): - if type(image) is str: - img = cv2.imread(image) - else: - img = image - img = cv2.resize(img, (self.input_shape[0], self.input_shape[1])) - encoding = self.base_model.predict(np.expand_dims(img, axis=0)) - distances = self.calculate_distances(encoding) - max_element = np.argmin(distances) - predicted_label = self.encoded_training_data['labels'][max_element] - return predicted_label - - def predict_knn(self, image, with_top5=False): - if type(image) is str: - img = cv2.imread(image) - else: - img = image - img = cv2.resize(img, (self.input_shape[0], self.input_shape[1])) - - encoding = self.base_model.predict(np.expand_dims(img, axis=0)) - predicted_label = self.encoded_training_data['knn_classifier'].predict(encoding) - if with_top5: - prediction_top5_idx = self.encoded_training_data['knn_classifier'].kneighbors(encoding, n_neighbors=5) - prediction_top5 = [self.encoded_training_data['labels'][prediction_top5_idx[1][0][i]] for i in range(5)] - return predicted_label, prediction_top5 - else: - return predicted_label - - def calculate_prediction_accuracy(self): - correct_top1 = 0 - correct_top5 = 0 - - accuracies = {'top1':0, - 'top5':0 } - total_n_of_images = len(self.data_loader.images_paths['val']) - for img_path, img_label in zip(self.data_loader.images_paths['val'], - self.data_loader.images_labels['val']): - prediction, prediction_top5 = self.predict_knn(img_path, with_top5=True) - if prediction[0] == img_label: - correct_top1 += 1 - if img_label in prediction_top5: - correct_top5 += 1 - accuracies['top1'] = correct_top1/total_n_of_images - accuracies['top5'] = correct_top5/total_n_of_images - - return accuracies diff --git a/embedding_net/model_new.py b/embedding_net/models.py similarity index 92% rename from embedding_net/model_new.py rename to embedding_net/models.py index 006263d..9b4411d 100644 --- a/embedding_net/model_new.py +++ b/embedding_net/models.py @@ -14,13 +14,18 @@ import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsClassifier + +# TODO +# [] - implement magnet loss +# [] - finalize settings with l1 and l2 losses + class EmbeddingNet: def __init__(self, params): self.params_model = params['model'] self.params_dataloader = params['dataloader'] self.params_generator = params['generator'] - self.params_save_paths = params['save_paths'] + self.params_save_paths = params['general'] self.params_train = params['train'] if 'softmax' in params: self.params_softmax = params['softmax'] @@ -33,9 +38,6 @@ def __init__(self, params): def _create_base_model(self): self.base_model, self.backbone_model = get_backbone(**self.params_model) - - # input_image = Input(self.params_model['input_shape']) - # output_base = self.base_model(input_image) output = Dense(units=1, activation='sigmoid', name='output_img')(self.base_model.layers[-1].output) self.classification_model = Model(inputs=[self.base_model.layers[0].input],outputs=[output]) @@ -85,12 +87,6 @@ def save_encodings(self, encoded_training_data, def load_model(self, file_path): import efficientnet.tfkeras as efn - # from keras_radam import RAdam - # self.model = load_model(file_path, - # custom_objects={'contrastive_loss': lac.contrastive_loss, - # 'accuracy': lac.accuracy, - # 'loss_function': lac.triplet_loss(self.params_generator['margin']), - # 'RAdam': RAdam}) self.model = load_model(file_path, compile=False) self.input_shape = list(self.model.inputs[0].shape[1:]) @@ -154,11 +150,11 @@ class TripletNet(EmbeddingNet): def __init__(self, params, training=False): super().__init__(params) - self._create_base_model() self.training = training if self.training: + self._create_base_model() self._create_model_triplet() diff --git a/embedding_net/utils.py b/embedding_net/utils.py index 30acd11..2ed8510 100644 --- a/embedding_net/utils.py +++ b/embedding_net/utils.py @@ -170,7 +170,7 @@ def parse_params(filename='configs/road_signs.yml'): params_generator = cfg['GENERATOR'] params_model = cfg['MODEL'] params_train = cfg['TRAIN'] - params_save_paths = cfg['SAVE_PATHS'] + params_general = cfg['GENERAL'] params_encodings = cfg['ENCODINGS'] params_generator['input_shape'] = params_model['input_shape'] @@ -181,7 +181,7 @@ def parse_params(filename='configs/road_signs.yml'): 'generator' : params_generator, 'model' : params_model, 'train' : params_train, - 'save_paths': params_save_paths, + 'general': params_general, 'encodings' : params_encodings} if 'SOFTMAX_PRETRAINING' in cfg: diff --git a/test_network.ipynb b/examples/test_network.ipynb similarity index 100% rename from test_network.ipynb rename to examples/test_network.ipynb diff --git a/images/._t-sne.png b/images/._t-sne.png deleted file mode 100644 index 65995994f197c362d2c257835b7ee254e5d802c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vVqlwZ z2GPMV1E|~*O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-Ffgz%v^GsKH%>A&OS5*) zD9X=GwKg_&F>y0BGSxM3b8^--F*P^WwQw`H)O9kpaCWtHb8$6sGC;Fvlsg&%qaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?azX&q*#u!QkPFGkELJE=EzU13N={Ws%P-1S t$jmEA1$I00^AdA%Div~4(@GSQauV~hfqh}9t|3jK`XBBU83wuk{{e-mGpzss diff --git a/images/._t-sne_without_training.png b/images/._t-sne_without_training.png deleted file mode 100644 index 06649881c0f4ab1b8e0065ea7272d3cf3e03da99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZQz6=P>$Vqox1Ojhs@R)|o50+1L3ClDJkFz{^v(m+1nBL)UWIUt(=a103vVo*}M z1<}DU1E|~*O$#HC4;2?p&d=3LEGWoH)hjGbEK1BP$;?Y-Ffgz%v^GsKH%>M&Nws#) zD9X=GwYGFMHFC2wanW@&Hg?f9F>tojwX}4x1hU*r9Sz;w3>=*e&@39|j)uT!2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6m)5CC;HK^P3=LNYRo6^c@e^Gl18Qx($ki?S6m s^GZ^I-Ol{H#GIT;g`Cv15{0Ck#Jp@^Ul^)uNK>f(hkHeaLGJ&50NUR(;{X5v diff --git a/requirements.txt b/requirements.txt index efd4d8b..f979556 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ image-classifiers -tensorflow-gpu==2.1.0 +tensorflow-gpu==2.0.0 matplotlib albumentations scikit-learn opencv-python keras-rectified-adam +efficientnet \ No newline at end of file diff --git a/tools/train.py b/tools/train.py index 52d6d92..dcbb01c 100644 --- a/tools/train.py +++ b/tools/train.py @@ -1,6 +1,12 @@ import os +import sys + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +ROOT_DIR = os.path.dirname(BASE_DIR) +sys.path.append(ROOT_DIR) + import numpy as np -from embedding_net.model_new import EmbeddingNet, TripletNet, SiameseNet +from embedding_net.models import EmbeddingNet, TripletNet, SiameseNet from tensorflow.keras.callbacks import TensorBoard, LearningRateScheduler from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint from embedding_net.datagenerators import ENDataLoader, SimpleDataGenerator, TripletsDataGenerator, SimpleTripletsDataGenerator, SiameseDataGenerator @@ -10,14 +16,12 @@ import argparse from tensorflow import keras import tensorflow as tf -from tensorflow.compat.v1.keras.backend import set_session def parse_args(): parser = argparse.ArgumentParser(description='Train a classificator') parser.add_argument('config', help='model config file path') - parser.add_argument( - '--resume_from', help='the checkpoint file to resume from') + parser.add_argument('--resume_from', help='the checkpoint file to resume from') args = parser.parse_args() @@ -31,7 +35,7 @@ def create_save_folders(params): plots_save_path = os.path.join(work_dir_path, 'plots/') tensorboard_save_path = os.path.join(work_dir_path, 'tf_log/') tensorboard_pretrained_save_path = os.path.join(work_dir_path, 'pretraining_model/tf_log/') - weights_save_file_path = os.path.join(weights_save_path, 'best_' + params['project_name']+'_{epoch:03d}_{loss:03f}' + '.hdf5') + weights_save_file_path = os.path.join(weights_save_path, 'epoch_{epoch:03d}' + '.hdf5') os.makedirs(work_dir_path , exist_ok=True) os.makedirs(weights_save_path, exist_ok=True) @@ -43,19 +47,6 @@ def create_save_folders(params): return tensorboard_save_path, weights_save_file_path, plots_save_path def main(): - config = tf.ConfigProto( - device_count={'GPU': 1}, - intra_op_parallelism_threads=1, - allow_soft_placement=True - ) - - config.gpu_options.allow_growth = True - # config.gpu_options.per_process_gpu_memory_fraction = 1 - - session = tf.Session(config=config) - - set_session(session) - print('LOAD PARAMETERS') args = parse_args() cfg_params = parse_params(args.config) @@ -64,12 +55,11 @@ def main(): params_dataloader = cfg_params['dataloader'] params_generator = cfg_params['generator'] - tensorboard_save_path, weights_save_file_path, plots_save_path = create_save_folders(cfg_params['save_paths']) + tensorboard_save_path, weights_save_file_path, plots_save_path = create_save_folders(cfg_params['general']) - cfg_params['save_paths'] - work_dir_path = os.path.join(cfg_params['save_paths']['work_dir'], - cfg_params['save_paths']['project_name']) + work_dir_path = os.path.join(cfg_params['general']['work_dir'], + cfg_params['general']['project_name']) weights_save_path = os.path.join(work_dir_path, 'weights/') @@ -83,7 +73,6 @@ def main(): callback_monitor = 'loss' print('LOADING COMPLETED') - callbacks = [ LearningRateScheduler(lambda x: initial_lr * decay_factor ** np.floor(x/step_size)), @@ -92,13 +81,15 @@ def main(): EarlyStopping(monitor=callback_monitor, patience=10, verbose=1), - # TensorBoard(log_dir=tensorboard_save_path), ModelCheckpoint(filepath=weights_save_file_path, monitor=callback_monitor, save_best_only=True, verbose=1) ] + if cfg_params['general']['tensorboard_callback']: + callbacks.append(TensorBoard(log_dir=tensorboard_save_path)) + print('CREATE DATALOADER') data_loader = ENDataLoader(**params_dataloader) print('DATALOADER CREATED!') @@ -116,13 +107,8 @@ def main(): class_names=data_loader.class_names, val_gen = True, **params_generator) - losses = {'output_siamese' : contrastive_loss, - 'output_im1' : tf.keras.losses.binary_crossentropy, - 'output_im2' : tf.keras.losses.binary_crossentropy} - - metric = {'output_siamese' : accuracy, - 'output_im1' : 'binary_accuracy', - 'output_im2' : 'binary_accuracy'} + losses = {'output_siamese' : contrastive_loss} + metric = {'output_siamese' : accuracy} else: model = TripletNet(cfg_params, training=True) train_generator = TripletsDataGenerator(embedding_model=model.base_model, @@ -135,15 +121,12 @@ def main(): data_loader.class_names, **params_generator) losses = triplet_loss(params_generator['margin']) - metric = 'accuracy' + metric = ['accuracy'] print('DONE') print('COMPILE MODEL') model.model.compile(loss=losses, - optimizer=params_train['optimizer'], - loss_weights = {'output_siamese' : 1, - 'output_im1' : 1, - 'output_im2' : 1}, + optimizer=params_train['optimizer'], metrics=metric) if args.resume_from is not None: @@ -151,18 +134,18 @@ def main(): if 'softmax' in cfg_params: params_softmax = cfg_params['softmax'] - params_save_paths = cfg_params['save_paths'] + params_save_paths = cfg_params['general'] pretrain_backbone_softmax(model.backbone_model, data_loader, params_softmax, params_save_paths) history = model.model.fit_generator(train_generator, - validation_data=val_generator, - epochs=params_train['n_epochs'], - callbacks=callbacks, - verbose=1, - use_multiprocessing=False) + validation_data=val_generator, + epochs=params_train['n_epochs'], + callbacks=callbacks, + verbose=1, + use_multiprocessing=False) if params_train['plot_history']: plot_grapths(history, plots_save_path)