From c3db88de5d45ddea58ce1d9a50210e4d5b373318 Mon Sep 17 00:00:00 2001 From: lvapeab Date: Mon, 17 Jul 2017 13:33:02 +0200 Subject: [PATCH] Written some docs/fixed some code flaws --- keras_wrapper/cnn_model.py | 4 +- keras_wrapper/extra/regularize.py | 5 + keras_wrapper/utils.py | 184 ++++++++++++++++++++++-------- 3 files changed, 145 insertions(+), 48 deletions(-) diff --git a/keras_wrapper/cnn_model.py b/keras_wrapper/cnn_model.py index 22467c0..56d6e8c 100644 --- a/keras_wrapper/cnn_model.py +++ b/keras_wrapper/cnn_model.py @@ -3350,7 +3350,7 @@ def conv_layer(self, x, nb_filter, nb_row, nb_col, dim_ordering, dim_ordering=dim_ordering)(x) if padding: - for i in range(padding): + for _ in range(padding): x = ZeroPadding2D(padding=(1, 1), dim_ordering=dim_ordering)(x) return x @@ -3367,8 +3367,6 @@ def GoogLeNet_FunctionalAPI(self, nOutput, input): CONCAT_AXIS = 1 NB_CLASS = nOutput # number of classes (default 1000) DROPOUT = 0.4 - WEIGHT_DECAY = 0.0005 # L2 regularization factor - USE_BN = True # whether to use batch normalization # Theano - 'th' (channels, width, height) # Tensorflow - 'tf' (width, height, channels) DIM_ORDERING = 'th' diff --git a/keras_wrapper/extra/regularize.py b/keras_wrapper/extra/regularize.py index c40ab9f..34ea2df 100644 --- a/keras_wrapper/extra/regularize.py +++ b/keras_wrapper/extra/regularize.py @@ -19,6 +19,11 @@ def Regularize(layer, params, :param params: Params specifying the regularizations to apply :param shared_layers: Boolean indicating if we want to get the used layers for applying to a shared-layers model. :param name: Name prepended to regularizer layer + :param apply_noise: If False, noise won't be applied, independently of params + :param apply_dropout: If False, dropout won't be applied, independently of params + :param apply_prelu: If False, prelu won't be applied, independently of params + :param apply_batch_normalization: If False, batch normalization won't be applied, independently of params + :param apply_l2: If False, l2 normalization won't be applied, independently of params :return: Regularized layer """ shared_layers_list = [] diff --git a/keras_wrapper/utils.py b/keras_wrapper/utils.py index ffa2ae2..c3dfb64 100644 --- a/keras_wrapper/utils.py +++ b/keras_wrapper/utils.py @@ -9,22 +9,34 @@ def bbox(img, mode='max'): - ''' - Returns a bounding box covering all the non-zero area in the image. - "mode" : "width_height" returns width in [2] and height in [3], "max" returns xmax in [2] and ymax in [3] - ''' + """ + Returns a bounding box covering all the non-zero area in the image. + + :param img: Image on which print the bounding box + :param mode: "width_height" returns width in [2] and height in [3], "max" returns xmax in [2] and ymax in [3] + :return: + """ rows = np.any(img, axis=1) cols = np.any(img, axis=0) y, ymax = np.where(rows)[0][[0, -1]] x, xmax = np.where(cols)[0][[0, -1]] - if (mode == 'width_height'): + if mode == 'width_height': return x, y, xmax - x, ymax - y - elif (mode == 'max'): + elif mode == 'max': return x, y, xmax, ymax def build_OneVsOneECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr=0.01, ecoc_version=2): + """ + + :param n_classes_ecoc: + :param input_shape: + :param ds: + :param stage1_lr: + :param ecoc_version: + :return: + """ n_classes = len(ds.classes) labels_list = [str(l) for l in range(n_classes)] @@ -38,17 +50,17 @@ def build_OneVsOneECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr=0.01, ec t = time.time() # Create each one_vs_one classifier of the intermediate stage - if (ecoc_version == 1): + if ecoc_version == 1: s = Stage(nInput=n_classes, nOutput=n_classes_ecoc, input_shape=input_shape, output_shape=[1, 2], type='One_vs_One_Inception', silence=True) - elif (ecoc_version == 2): + elif ecoc_version == 2: s = Stage(nInput=n_classes, nOutput=n_classes_ecoc, input_shape=input_shape, output_shape=[1, 2], type='One_vs_One_Inception_v2', silence=True) # Build input mapping input_mapping = dict() for i in range(n_classes): i_str = str(i) - if (i_str in c): + if i_str in c: input_mapping[i] = c.index(i_str) else: input_mapping[i] = None @@ -70,6 +82,14 @@ def build_OneVsOneECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr=0.01, ec def build_OneVsAllECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr): + """ + + :param n_classes_ecoc: + :param input_shape: + :param ds: + :param stage1_lr: + :return: + """ n_classes = len(ds.classes) stage = list() @@ -85,7 +105,7 @@ def build_OneVsAllECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr): # Build input mapping input_mapping = dict() for i in range(n_classes): - if (i == c): + if i == c: input_mapping[i] = 0 else: input_mapping[i] = 1 @@ -107,6 +127,15 @@ def build_OneVsAllECOC_Stage(n_classes_ecoc, input_shape, ds, stage1_lr): def build_Specific_OneVsOneECOC_Stage(pairs, input_shape, ds, lr, ecoc_version=2): + """ + + :param pairs: + :param input_shape: + :param ds: + :param lr: + :param ecoc_version: + :return: + """ n_classes = len(ds.classes) stage = list() @@ -120,16 +149,16 @@ def build_Specific_OneVsOneECOC_Stage(pairs, input_shape, ds, lr, ecoc_version=2 t = time.time() # Create each one_vs_one classifier of the intermediate stage - if (ecoc_version == 1): + if ecoc_version == 1: s = Stage(nInput=n_classes, nOutput=2, input_shape=input_shape, output_shape=[2], type='One_vs_One_Inception', silence=True) - elif (ecoc_version == 2): + elif ecoc_version == 2: s = Stage(nInput=n_classes, nOutput=2, input_shape=input_shape, output_shape=[2], type='One_vs_One_Inception_v2', silence=True) # Build input mapping input_mapping = dict() for i in range(n_classes): - if (i in c): + if i in c: input_mapping[i] = c.index(i) else: input_mapping[i] = None @@ -151,6 +180,15 @@ def build_Specific_OneVsOneECOC_Stage(pairs, input_shape, ds, lr, ecoc_version=2 def build_Specific_OneVsOneVsRestECOC_Stage(pairs, input_shape, ds, lr, ecoc_version=2): + """ + + :param pairs: + :param input_shape: + :param ds: + :param lr: + :param ecoc_version: + :return: + """ n_classes = len(ds.classes) stage = list() @@ -162,16 +200,16 @@ def build_Specific_OneVsOneVsRestECOC_Stage(pairs, input_shape, ds, lr, ecoc_ver t = time.time() # Create each one_vs_one classifier of the intermediate stage - if (ecoc_version == 1): + if ecoc_version == 1: s = Stage(nInput=n_classes, nOutput=3, input_shape=input_shape, output_shape=[3], type='One_vs_One_Inception', silence=True) - elif (ecoc_version == 2): + elif ecoc_version == 2: s = Stage(nInput=n_classes, nOutput=3, input_shape=input_shape, output_shape=[3], type='One_vs_One_Inception_v2', silence=True) # Build input mapping input_mapping = dict() for i in range(n_classes): - if (i in c): + if i in c: input_mapping[i] = c.index(i) else: input_mapping[i] = 2 @@ -194,8 +232,20 @@ def build_Specific_OneVsOneVsRestECOC_Stage(pairs, input_shape, ds, lr, ecoc_ver def build_Specific_OneVsOneECOC_loss_Stage(net, input, input_shape, classes, ecoc_version=3, pairs=None, functional_api=False, activations=['softmax', 'softmax']): + """ + + :param net: + :param input: + :param input_shape: + :param classes: + :param ecoc_version: + :param pairs: + :param functional_api: + :param activations: + :return: + """ n_classes = len(classes) - if (pairs is None): # generate any possible combination of two classes + if pairs is None: # generate any possible combination of two classes pairs = tuple(itertools.combinations(range(n_classes), 2)) outputs_list = list() @@ -205,28 +255,28 @@ def build_Specific_OneVsOneECOC_loss_Stage(net, input, input_shape, classes, eco logging.info("Building " + str(n_pairs) + " OneVsOne structures...") for i, c in enumerate(pairs): - t = time.time() + # t = time.time() # Insert 1s in the corresponding positions of the ecoc table ecoc_table[c[0], i, 0] = 1 ecoc_table[c[1], i, 1] = 1 # Create each one_vs_one classifier of the intermediate stage - if (functional_api == False): - if (ecoc_version == 1): + if functional_api == False: + if ecoc_version == 1: output_name = net.add_One_vs_One_Inception(input, input_shape, i, nOutput=2, activation=activations[0]) - elif (ecoc_version == 2): + elif ecoc_version == 2: output_name = net.add_One_vs_One_Inception_v2(input, input_shape, i, nOutput=2, activation=activations[0]) else: raise NotImplementedError else: - if (ecoc_version == 1): + if ecoc_version == 1: output_name = net.add_One_vs_One_Inception_Functional(input, input_shape, i, nOutput=2, activation=activations[0]) - elif (ecoc_version == 2): + elif ecoc_version == 2: raise NotImplementedError() - elif (ecoc_version == 3 or ecoc_version == 4 or ecoc_version == 5 or ecoc_version == 6): + elif ecoc_version == 3 or ecoc_version == 4 or ecoc_version == 5 or ecoc_version == 6: if ecoc_version == 3: nkernels = 16 elif ecoc_version == 4: @@ -237,13 +287,13 @@ def build_Specific_OneVsOneECOC_loss_Stage(net, input, input_shape, classes, eco nkernels = 256 else: raise NotImplementedError() - if (i == 0): + if i == 0: in_node = net.model.get_layer(input).output padding_node = ZeroPadding2D(padding=(1, 1), name='3x3/ecoc_padding')(in_node) output_name = net.add_One_vs_One_3x3_Functional(padding_node, input_shape, i, nkernels, nOutput=2, activation=activations[0]) - elif (ecoc_version == 7): - if (i == 0): + elif ecoc_version == 7: + if i == 0: in_node = net.model.get_layer(input).output padding_node = ZeroPadding2D(padding=(1, 1), name='3x3/ecoc_padding')(in_node) output_name = net.add_One_vs_One_3x3_double_Functional(padding_node, input_shape, i, nOutput=2, @@ -252,12 +302,13 @@ def build_Specific_OneVsOneECOC_loss_Stage(net, input, input_shape, classes, eco raise NotImplementedError() outputs_list.append(output_name) - # logging.info('Built model %s/%s for classes %s = %s in %0.5s seconds.'%(str(i+1), str(n_pairs), c, (classes[c[0]], classes[c[1]]), str(time.time()-t))) + # logging.info('Built model %s/%s for classes %s = %s in %0.5s seconds.'%(str(i+1), + # str(n_pairs), c, (classes[c[0]], classes[c[1]]), str(time.time()-t))) ecoc_table = np.reshape(ecoc_table, [n_classes, 2 * n_pairs]) # Build final Softmax layer - if (functional_api == False): + if not functional_api: output_names = net.add_One_vs_One_Merge(outputs_list, n_classes, activation=activations[1]) else: output_names = net.add_One_vs_One_Merge_Functional(outputs_list, n_classes, activation=activations[1]) @@ -267,8 +318,18 @@ def build_Specific_OneVsOneECOC_loss_Stage(net, input, input_shape, classes, eco def prepareECOCLossOutputs(net, ds, ecoc_table, input_name, output_names, splits=['train', 'val', 'test']): + """ + + :param net: + :param ds: + :param ecoc_table: + :param input_name: + :param output_names: + :param splits: + :return: + """ # Insert ecoc_table in net - if (not 'additional_data' in net.__dict__.keys()): + if 'additional_data' not in net.__dict__.keys(): net.additional_data = dict() net.additional_data['ecoc_table'] = ecoc_table @@ -300,6 +361,12 @@ def prepareECOCLossOutputs(net, ds, ecoc_table, input_name, output_names, splits def loadGoogleNetForFood101(nClasses=101, load_path='/media/HDD_2TB/CNN_MODELS/GoogleNet'): + """ + + :param nClasses: + :param load_path: + :return: + """ logging.info('Loading GoogLeNet...') # Build model (loading the previously converted Caffe's model) @@ -312,7 +379,11 @@ def loadGoogleNetForFood101(nClasses=101, load_path='/media/HDD_2TB/CNN_MODELS/G def prepareGoogleNet_Food101(model_wrapper): - """ Prepares the GoogleNet model after its conversion from Caffe """ + """ + Prepares the GoogleNet model after its conversion from Caffe + :param model_wrapper: + :return: + """ # Remove unnecessary intermediate optimizers layers_to_delete = ['loss2/ave_pool', 'loss2/conv', 'loss2/relu_conv', 'loss2/fc_flatten', 'loss2/fc', 'loss2/relu_fc', 'loss2/drop_fc', 'loss2/classifier', 'output_loss2/loss', @@ -323,8 +394,11 @@ def prepareGoogleNet_Food101(model_wrapper): def prepareGoogleNet_Food101_ECOC_loss(model_wrapper): - """ Prepares the GoogleNet model for inserting an ECOC structure after removing the last part of the net """ - + """ + Prepares the GoogleNet model for inserting an ECOC structure after removing the last part of the net + :param model_wrapper: + :return: + """ # Remove all last layers (from 'inception_5a' included) layers_to_delete = ['inception_5a/1x1', 'inception_5a/relu_1x1', 'inception_5a/3x3_reduce', 'inception_5a/relu_3x3_reduce', @@ -354,14 +428,22 @@ def prepareGoogleNet_Food101_ECOC_loss(model_wrapper): def prepareGoogleNet_Food101_Stage1(model_wrapper): - """ Prepares the GoogleNet model for serving as the first Stage of a Staged_Netork """ + """ + Prepares the GoogleNet model for serving as the first Stage of a Staged_Netork + :param model_wrapper: + :return: + """ # Adds a new output after the layer 'pool4/3x3_s2' model_wrapper.model.add_output(name='pool4', input='pool4/3x3_s2') def prepareGoogleNet_Stage2(stage1, stage2): - """ Removes the second part of the GoogleNet for inserting it into the second stage. """ - + """ + Removes the second part of the GoogleNet for inserting it into the second stage. + :param stage1: + :param stage2: + :return: + """ # Remove all last layers (from 'inception_5a' included) layers_to_delete = ['inception_5a/1x1', 'inception_5a/relu_1x1', 'inception_5a/3x3_reduce', 'inception_5a/relu_3x3_reduce', @@ -439,7 +521,6 @@ def prepareGoogleNet_Stage2(stage1, stage2): stage2.model.add_input(name='input_data', input_shape=(832, 7, 7)) stage2.model.nodes[layers_to_delete[0]].previous = stage2.model.inputs['input_data'] - ## Insert layers into stage # stage2.model = Graph() ## Input @@ -459,8 +540,14 @@ def prepareGoogleNet_Stage2(stage1, stage2): ##stage2.model.add_output(name='loss3/loss3_', input=layers_to_delete[-1]) ##stage2.model.input = input # recover input - def simplifyDataset(ds, id_classes, n_classes=50): + """ + + :param ds: + :param id_classes: + :param n_classes: + :return: + """ logging.info("Simplifying %s from %d to %d classes." % (str(ds.name), len(ds.classes), n_classes)) ds.classes[id_classes] = ds.classes[id_classes][:n_classes] @@ -472,7 +559,7 @@ def simplifyDataset(ds, id_classes, n_classes=50): kept_X = dict() exec ('labels_set = ds.Y_' + s + '[id_labels]') for i, y in enumerate(labels_set): - if (y < n_classes): + if y < n_classes: for id_out in ds.ids_outputs: exec ('sample = ds.Y_' + s + '[id_out][i]') try: @@ -497,6 +584,7 @@ def one_hot_2_indices(preds, pad_sequences=True, verbose=0): """ Converts a one-hot codification into a index-based one :param preds: Predictions codified as one-hot vectors. + :param pad_sequences: Whether we should pad sequence or not :param verbose: Verbosity level, by default 0. :return: List of convertedpredictions """ @@ -540,9 +628,9 @@ def decode_predictions_one_hot(preds, index2word, verbose=0): """ if verbose > 0: logging.info('Decoding one hot prediction ...') - preds = map(lambda x: np.nonzero(x)[1], preds) + preds = map(lambda prediction: np.nonzero(prediction)[1], preds) PAD = '' - flattened_answer_pred = [map(lambda x: index2word[x], pred) for pred in preds] + flattened_answer_pred = [map(lambda index: index2word[index], pred) for pred in preds] answer_pred_matrix = np.asarray(flattened_answer_pred) answer_pred = [] @@ -568,9 +656,9 @@ def decode_predictions(preds, temperature, index2word, sampling_type, verbose=0) if verbose > 0: logging.info('Decoding prediction ...') flattened_preds = preds.reshape(-1, preds.shape[-1]) - flattened_answer_pred = map(lambda x: index2word[x], sampling(scores=flattened_preds, - sampling_type=sampling_type, - temperature=temperature)) + flattened_answer_pred = map(lambda index: index2word[index], sampling(scores=flattened_preds, + sampling_type=sampling_type, + temperature=temperature)) answer_pred_matrix = np.asarray(flattened_answer_pred).reshape(preds.shape[:-1]) answer_pred = [] @@ -670,9 +758,15 @@ def decode_predictions_beam_search(preds, index2word, alphas=None, heuristic=0, mapping=None, verbose=0): """ Decodes predictions from the BeamSearch method. + :param preds: Predictions codified as word indices. :param index2word: Mapping from word indices into word characters. + :param alphas: Attention model weights + :param heuristic: Replace unknown words heuristic (0, 1 or 2) + :param x_text: Source text (for unk replacement) + :param unk_symbol: Unknown words symbol :param pad_sequences: Whether we should make a zero-pad on the input sequence. + :param mapping: Source-target dictionary (for unk_replace heuristics 1 and 2) :param verbose: Verbosity level, by default 0. :return: List of decoded predictions """ @@ -776,4 +870,4 @@ def flatten(l): """ if not l: return l - return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l] \ No newline at end of file + return flatten(l[0]) + (flatten(l[1:]) if len(l) > 1 else []) if type(l) is list else [l]