From 7b6b20bdc8d8c72d0204355d004bf06726ad87f3 Mon Sep 17 00:00:00 2001 From: Rauf Yagfarov Date: Mon, 17 Feb 2020 15:48:00 +0300 Subject: [PATCH] create new dataloader and generators --- configs/bengali.yml | 46 ++-- embedding_net/datagenerators.py | 103 +++++++-- embedding_net/model_new.py | 397 +++++++++++++++----------------- embedding_net/utils.py | 85 ++++--- 4 files changed, 335 insertions(+), 296 deletions(-) diff --git a/configs/bengali.yml b/configs/bengali.yml index 4d8336a..9ec7362 100644 --- a/configs/bengali.yml +++ b/configs/bengali.yml @@ -8,11 +8,24 @@ MODEL: freeze_backbone : False embeddings_normalization: True -TRAIN: +DATALOADER: + dataset_path : '/home/rauf/datasets/bengali/pngs/train/' + csv_file : '/home/rauf/datasets/bengali/train_new.csv' + image_id_column : 'image_id' + label_column : 'label' + validate : True + val_ratio : 0.2 + +GENERATOR: + negatives_selection_mode : 'semihard' + mining_n_classes: 5 + mining_n_samples: 3 margin: 0.5 batch_size : 8 + n_batches : 200 augmentation_type : 'default' +TRAIN: # optimizer parameters optimizer : 'radam' learning_rate : 0.0001 @@ -21,29 +34,24 @@ TRAIN: # embeddings learning training parameters n_epochs : 1000 - n_batches : 200 - val_batch_size : 8 - val_steps : 200 - negatives_selection_mode : 'semihard' - mining_n_classes: 5 - mining_n_samples: 3 + + # plot training history + plot_history : True +SOFTMAX_PRETRAINING: # softmax pretraining parameters - softmax_pretraining : True - softmax_batch_size : 8 - softmax_val_steps : 200 - softmax_steps_per_epoch : 500 - softmax_epochs : 20 + optimizer : 'radam' + learning_rate : 0.0001 + decay_factor : 0.99 + step_size : 1 - # plot training history - plot_history : True + batch_size : 8 + val_steps : 200 + steps_per_epoch : 500 + n_epochs : 20 -PATHS: +SAVE_PATHS: work_dir : 'work_dirs/road_signs_resnet18/' - dataset_path : '/home/rauf/datasets/bengali/pngs/train/' - csv_file : '/home/rauf/datasets/bengali/train.csv' - image_id_column : 'image_id' - label_column : 'label' encodings_path : 'encodings/' model_save_name : 'best_model_resnet18.h5' encodings_save_name: 'encodings_resnet18.pkl' diff --git a/embedding_net/datagenerators.py b/embedding_net/datagenerators.py index 2a032ce..86ab1c3 100644 --- a/embedding_net/datagenerators.py +++ b/embedding_net/datagenerators.py @@ -12,7 +12,9 @@ class ENDataLoader(): def __init__(self, dataset_path, csv_file=None, image_id_column = 'image_id', - label_column = 'label'): + label_column = 'label', + validate = True, + val_ratio = 0.1): self.dataset_path = dataset_path self.class_files_paths = {} @@ -26,6 +28,15 @@ def __init__(self, dataset_path, self.n_classes = len(self.class_names) self.n_samples = {k: len(v) for k, v in self.class_files_paths.items()} + self.validate = validate + self.val_ratio = val_ratio + + if self.validate: + self.train_data, self.val_data = self.split_train_val(self.val_ratio) + else: + self.train_data = self.class_files_paths + self.val_data = {} + def split_train_val(self, val_ratio): train_data = {} val_data = {} @@ -33,7 +44,7 @@ def split_train_val(self, val_ratio): train_d, val_d = train_test_split(v, test_size=val_ratio, random_state=42) train_data[k] = train_d val_data[k] = val_d - return train_data, val_data, self.class_names + return train_data, val_data def _load_from_dataframe(self, csv_file, image_id_column, label_column): dataframe = pd.read_csv(csv_file) @@ -110,20 +121,22 @@ def _get_images_set(self, clsss, idxs, with_aug=True): class TripletsDataGenerator(ENDataGenerator): def __init__(self, embedding_model, - dataset_path, + class_files_paths, + class_names, n_batches = 10, input_shape=None, batch_size = 32, - csv_file=None, - image_id_column = 'image_id', - label_column = 'label', augmentations=None, k_classes=5, k_samples=5, margin=0.5, negative_selection_mode='semihard'): - super().__init__(dataset_path, input_shape, batch_size, n_batches, csv_file, - image_id_column,label_column, augmentations) + super().__init__(class_files_paths=class_files_paths, + clas_names=class_names, + input_shape=input_shape, + batch_size=batch_size, + n_batches=n_batches, + augmentations=augmentations) modes = {'semihard' : self.semihard_negative, 'hardest': self.hardest_negative, 'random_hard': self.random_hard_negative} @@ -210,16 +223,18 @@ def __getitem__(self, index): class SimpleTripletsDataGenerator(ENDataGenerator): - def __init__(self, dataset_path, + def __init__(self, class_files_paths, + class_names, input_shape=None, batch_size = 32, - n_batches = 10, - csv_file=None, - image_id_column = 'image_id', - label_column = 'label', + n_batches = 10, augmentations=None): - super().__init__(dataset_path, input_shape, batch_size, n_batches, csv_file, - image_id_column,label_column, augmentations) + super().__init__(class_files_paths=class_files_paths, + clas_names=class_names, + input_shape=input_shape, + batch_size=batch_size, + n_batches=n_batches, + augmentations=augmentations) def get_batch_triplets(self): triplets = [np.zeros((self.batch_size, self.input_shape[0], self.input_shape[1], 3)), @@ -261,17 +276,19 @@ def __getitem__(self, index): class SiameseDataGenerator(ENDataGenerator): - def __init__(self, dataset_path, + def __init__(self, class_files_paths, + class_names, input_shape=None, batch_size = 32, - n_batches = 10, - csv_file=None, - image_id_column = 'image_id', - label_column = 'label', + n_batches = 10, augmentations=None): - super().__init__(dataset_path, input_shape, batch_size, n_batches, dataframe, - image_id_column,label_column, augmentations) + super().__init__(class_files_paths=class_files_paths, + clas_names=class_names, + input_shape=input_shape, + batch_size=batch_size, + n_batches=n_batches, + augmentations=augmentations) def get_batch_pairs(self): pairs = [np.zeros((self.batch_size, self.input_shape[0], self.input_shape[1], 3)), np.zeros( @@ -317,4 +334,44 @@ def get_batch_pairs(self): return pairs, targets def __getitem__(self, index): - return self.get_batch_pairs() \ No newline at end of file + return self.get_batch_pairs() + + +class SimpleDataGenerator(ENDataGenerator): + def __init__(self, class_files_paths, + class_names, + input_shape=None, + batch_size = 32, + n_batches = 10, + augmentations=None): + + super().__init__(class_files_paths=class_files_paths, + clas_names=class_names, + input_shape=input_shape, + batch_size=batch_size, + n_batches=n_batches, + augmentations=augmentations) + + def get_batch(self): + images = [ + np.zeros((self.batch_size, self.input_shape[0], self.input_shape[1], 3))] + targets = np.zeros((self.batch_size, self.n_classes)) + + count = 0 + with_aug = self.augmentations + for i in range(self.batch_size): + selected_class_idx = random.randrange(0, self.n_classes) + selected_class = self.class_names[selected_class_idx] + selected_class_n_elements = len(self.class_files_paths[selected_class]) + + indx = random.randrange(0, selected_class_n_elements) + + img = self._get_images_set([selected_class], [indx], with_aug=with_aug) + images[0][count, :, :, :] = img[0] + targets[i][selected_class_idx] = 1 + count += 1 + + return images, targets + + def __getitem__(self, index): + return self.get_batch() diff --git a/embedding_net/model_new.py b/embedding_net/model_new.py index bb36efb..2e75c01 100644 --- a/embedding_net/model_new.py +++ b/embedding_net/model_new.py @@ -8,7 +8,8 @@ from tensorflow.keras import optimizers from tensorflow.keras.layers import Dense, Input, Lambda, concatenate, GlobalAveragePooling2D import pickle -from .utils import load_encodings, parse_net_params +from .utils import load_encodings, parse_params +from .datagenerators import ENDataLoader, SimpleDataGenerator, TripletsDataGenerator, SimpleTripletsDataGenerator, SiameseDataGenerator from .backbones import get_backbone from . import losses_and_accuracies as lac import matplotlib.pyplot as plt @@ -16,100 +17,77 @@ from tensorflow.keras.callbacks import TensorBoard, LearningRateScheduler from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint -# TODO -# [] - implement magnet loss -# [] - finalize settings with l1 and l2 losses +class EmbeddingNet: + def __init__(self, cfg): + self.params_backbone = cfg['backbone'] + self.params_dataloader = cfg['dataloader'] + self.params_generator = cfg['generator'] + self.params_save_paths = cfg['save_paths'] + self.params_train = cfg['train'] + if 'SOFTMAX_PRETRAINING' in cfg: + self.params_softmax = cfg['softmax'] -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_path, training = True): - params = parse_net_params(cfg_path) - 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.base_model = {} + self.backbone_model = {} self.encoded_training_data = {} - - if cfg_params['softmax_pretraining'] and training: - self.pretrain_backbone_softmax() + self.data_loader = {} 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 + + optimizer = self.params_softmax['optimizer'] + learning_rate = self.params_softmax['learning_rate'] + decay_factor = self.params_softmax['decay_factor'] + step_size = self.params_softmax['step_size'] + + input_shape = self.params_softmax['input_shape'] + batch_size = self.params_softmax['batch_size'] + val_steps = self.params_softmax['val_steps'] + steps_per_epoch = self.params_softmax['steps_per_epoch'] + n_epochs = self.params_softmax['n_epochs'] + augmentations = self.params_softmax['augmentations'] + + n_classes = self.data_loader.n_classes x = GlobalAveragePooling2D()(self.backbone_model.output) - if is_binary: - output = Dense(1, activation='softmax')(x) - else: - output = Dense(n_classes, activation='softmax')(x) + + output = Dense(n_classes, activation='softmax')(x) model = 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") + model.compile(optimizer=optimizer, + loss='categorical_crossentropy', + metrics=['accuracy']) + + train_generator = SimpleDataGenerator(self.data_loader.train_data, + self.class_names, + input_shape=input_shape, + batch_size = batch_size, + n_batches = steps_per_epoch, + augmentations=augmentations) + + if self.data_loader.validate: + val_generator = SimpleDataGenerator(self.data_loader.val_data, + self.class_names, + input_shape=input_shape, + batch_size = batch_size, + n_batches = steps_per_epoch, + augmentations=augmentations) 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/') + self.params_save_paths['work_dir'], 'tf_log/pretraining_model/') weights_save_file = os.path.join( - self.cfg_params['work_dir'], + self.params_save_paths['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'] + self.params_save_paths['model_save_name']) callbacks = [ - LearningRateScheduler(lambda x: initial_lr * + LearningRateScheduler(lambda x: learning_rate * decay_factor ** np.floor(x/step_size)), ReduceLROnPlateau(monitor=checkpoint_callback_monitor, factor=0.1, patience=20, verbose=1), @@ -126,157 +104,30 @@ def pretrain_backbone_softmax(self): history = model.fit_generator(train_generator, steps_per_epoch=steps_per_epoch, - epochs=epochs, + epochs=n_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() + def _create_base_model(self, params_backbone): + self.base_model, self.backbone_model = get_backbone(**params_backbone) - print('Whole model summary') - self.model.summary() + def _create_dataloader(self, dataloader_params): + return ENDataLoader(**dataloader_params) - self.model.compile(loss=lac.contrastive_loss, metrics=[metric], - optimizer=self.optimizer) + def _create_generators(self): + pass + + def train_generator(self, callbacks=[], verbose=1): + history = self.model.fit_generator(self.train_generator, + validation_data=self.val_generator, + epochs=self.params_train['n_epoch'], + callbacks=callbacks, + verbose=verbose) - 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_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: @@ -284,7 +135,11 @@ def _generate_encoding(self, img_path): 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): + 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 = {} @@ -402,4 +257,112 @@ def calculate_prediction_accuracy(self): class TripletNet(EmbeddingNet): - pass \ No newline at end of file + + def __init__(self, cfg, training=False): + super().__init__(cfg) + self._create_base_model() + self.base_model._make_predict_function() + + self.model = self._create_model_triplet() + + if training: + self.dataloader = {} + self.train_generator = {} + self.val_generator = {} + self._create_generators() + + def _create_generators(self): + self.train_generator = TripletsDataGenerator(embedding_model=self.base_model, + self.data_loader.train_data, + self.data_loader.class_names, + **self.params_generator) + if self.data_loader.validate: + self.val_generator = SimpleTripletsDataGenerator(self.data_loader.val_data, + self.data_loader.class_names, + **self.params_generator) + else: + self.val_generator = None + + 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) + + 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) + + +class SiameseNet(EmbeddingNet): + + def __init__(self, cfg, training): + super().__init__(cfg) + self.model = self._create_model_siamese() + if training: + self.dataloader = {} + self.train_generator = {} + self.val_generator = {} + self.train_generator = TripletsDataGenerator(**train_generator_params) + self.val_generator = TripletsDataGenerator(**val_generator_params) + + def _create_generators(self): + self.train_generator = TripletsDataGenerator(embedding_model=self.base_model, + self.data_loader.train_data, + self.data_loader.class_names, + **self.params_generator) + if self.data_loader.validate: + self.val_generator = TripletsDataGenerator(embedding_model=self.base_model, + self.data_loader.val_data, + self.data_loader.class_names, + **self.params_generator) + + def _create_model_siamese(self): + + input_image_1 = Input(self.input_shape) + input_image_2 = Input(self.input_shape) + + 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) \ No newline at end of file diff --git a/embedding_net/utils.py b/embedding_net/utils.py index e1daf7e..1749e86 100644 --- a/embedding_net/utils.py +++ b/embedding_net/utils.py @@ -8,7 +8,10 @@ from tensorflow.keras import optimizers from .augmentations import get_aug from .data_loader import EmbeddingNetImageLoader -from .datagenerators import TripletsDataGenerator, SiameseDataGenerator, SimpleTripletsDataGenerator +from .datagenerators import ENDataLoader, + TripletsDataGenerator, + SiameseDataGenerator, + SimpleTripletsDataGenerator def load_encodings(path_to_encodings): @@ -123,51 +126,59 @@ def plot_batch(data, targets): plt.show() -def parse_net_params(filename='configs/road_signs.yml'): - params = {} - with open(filename, 'r') as ymlfile: - cfg = yaml.safe_load(ymlfile) - - params_model = cfg['MODEL'] - params_train = cfg['TRAIN'] - params_paths = cfg['PATHS'] - - if 'augmentations_type' in cfg: - augmentations = get_aug(cfg['augmentation_type'], cfg['input_shape']) - else: - augmentations = None - - train_generator_parameters = {'dataset_path' : params_paths['dataset_path'], - 'input_shape' : params_model['input_shape'], - 'batch_size' : params_train['batch_size'], - 'n_batches' : params_train['n_batches'], - 'csv_file' : params_paths['csv_file'], - 'image_id_column' : params_paths['image_id'], - 'label_column' : params_paths['label'], - 'augmentations' : augmentations} - - learning_rate = cfg['learning_rate'] - if cfg['optimizer'] == 'adam': +def get_optimizer(name, learning_rate): + if name == 'adam': optimizer = optimizers.Adam(lr=learning_rate) - elif cfg['optimizer'] == 'rms_prop': + elif name == 'rms_prop': optimizer = optimizers.RMSprop(lr=learning_rate) - elif cfg['optimizer'] == 'radam': + elif name == 'radam': from keras_radam import RAdam optimizer = RAdam(learning_rate) else: optimizer = optimizers.SGD(lr=learning_rate) + return optimizer - params = {k: v for k, v in cfg.items() if k not in ['optimizer']} +def parse_params(filename='configs/road_signs.yml'): + with open(filename, 'r') as ymlfile: + cfg = yaml.safe_load(ymlfile) + + if 'augmentations_type' in cfg['GENERATOR']: + augmentations = get_aug(cfg['GENERATOR']['augmentation_type'], + cfg['MODEL']['input_shape']) + else: + augmentations = None - if 'dataset_path' in cfg: - params['loader'] = EmbeddingNetImageLoader(cfg['dataset_path'], - input_shape=cfg['input_shape'], - min_n_obj_per_class=cfg['min_n_obj_per_class'], - select_max_n_obj_per_class = cfg['select_max_n_obj_per_class'], - max_n_obj_per_class=cfg['max_n_obj_per_class'], - augmentations=augmentations) + optimizer = get_optimizer(cfg['TRAIN']['optimizer'], + cfg['TRAIN']['learning_rate']) + + params_dataloader = cfg['DATALOADER'] + params_generator = cfg['GENERATOR'] + params_model = cfg['MODEL'] + params_train = cfg['TRAIN'] + params_save_paths = cfg['SAVE_PATHS'] + params_encodings = cfg['ENCODINGS'] + + params_generator['input_shape'] = params_model['input_shape'] + params_train['optimizer'] = optimizer + params_model['augmentations'] = augmentations + + params = {'dataloader' : params_dataloader, + 'generator' : params_generator, + 'model' : params_model, + 'train' : params_train, + 'save_paths': params_save_paths, + 'encodings' : params_encodings} + + if 'SOFTMAX_PRETRAINING' in cfg: + params_softmax = cfg['SOFTMAX_PRETRAINING'] + params_softmax['augmentations'] = augmentations + params_softmax['input_shape'] = params_model['input_shape'] + softmax_optimizer = get_optimizer(cfg['SOFTMAX_PRETRAINING']['optimizer'], + cfg['SOFTMAX_PRETRAINING']['learning_rate']) + params_softmax['optimizer'] = softmax_optimizer + params['softmax'] = params_softmax + - params['optimizer'] = optimizer return params