def get_config( fname ): """ ----------------------------------------------------------------------------------------------------- Return the content of a config file in the form of a dictionary fname: [str] path of config file return: [dict] content of the file ----------------------------------------------------------------------------------------------------- """ cnfg = dict() if not os.path.isfile( fname ): ms.print_err( "Configuration file \"{}\" not found.".format( fname ) ) if DEBUG0: ms.print_msg( cnfg[ 'log_msg' ], "Reading configuration file \"{}\".\n".format( fname ) ) os.system( "cat %s" % fname ) with open( fname ) as doc: for line in doc: if line[ 0 ] == '#': continue # comment line if DEBUG1: print( line ) c = line.split( '#' )[ 0 ] # remove any following comment c = c.split() if len( c ) == 0: continue # empty line cnfg[ c[ 0 ] ] = eval( str().join( c[ 1: ] ) ) return cnfg
def create_model(): """ ----------------------------------------------------------------------------------------------------- Model architecture and weight training ----------------------------------------------------------------------------------------------------- """ global nn, test_set, test_str ar.TRAIN = args['TRAIN'] if cnfg['arch_class'] != 'ITIME': nn = ar.create_model() if args['LOAD'] is not None: if not ar.load_model(nn.model, args['LOAD']): ms.print_err("Failed to load weights from {}".format(args['LOAD'])) if args['TRAIN']: if cnfg['arch_class'] in time_models: history, train_duration = tr.train_time_model(nn) else: history, train_duration = tr.train_ae_model(nn) tr.plot_history(history, os.path.join(dir_current, 'loss')) # save duration of training with open(log_duration, 'a') as f: f.write("Training duration:\t{}\n".format(str(train_duration))) if SAVE: ar.save_model(nn.model)
def gen_dataset(dir_dset, seq_folders=('f0', 'f1', 'f2')): """ ----------------------------------------------------------------------------------------------------- Iterate over a dataset, yielding batches of images dir_dset: [str] folder of dataset (it must contain subfolders for train/valid) seq_folders: [list of str] with names of subfolders of each frame in the sequence (RGBSEQ only) return: [keras_preprocessing.image.DirectoryIterator or generator] (python built-in type) ----------------------------------------------------------------------------------------------------- """ if cnfg['data_class'] == 'RGB': return dset_same(dir_dset) if cnfg['data_class'] in ('LANE', 'CAR'): return dset_class(dir_dset, cnfg['data_class'].lower()) if cnfg['data_class'] == 'MULTI': return dset_multiple(dir_dset) if cnfg['data_class'] == 'RGBSEQ': return dset_sequence(dir_dset, seq_folders=seq_folders) if cnfg['data_class'] == 'MULTISEQ': return dset_multi_seq(dir_dset, seq_folders=seq_folders) ms.print_err("Data class {} not valid".format(cnfg['data_class']))
def init_config(): """ ----------------------------------------------------------------------------------------------------- Initialization ----------------------------------------------------------------------------------------------------- """ global dir_current dir_current = os.path.join(dir_res, time.strftime(FRMT)) os.makedirs(dir_current) os.makedirs(os.path.join(dir_current, dir_log)) # redirect stderr and stdout in log files if args['REDIRECT']: le = os.path.join(dir_current, log_err) lo = os.path.join(dir_current, log_out) sys.stderr = open(le, 'w') sys.stdout = open(lo, 'w') # how to restore # sys.stdout = sys.__stdout__ #exec( "from {} import cnfg".format( args[ 'CONFIG' ] ) ) cnfg['dir_current'] = dir_current cnfg['log_msg'] = os.path.join(dir_current, log_msg) # visible GPUs - must be here, before all the keras stuff n_gpus = eval(args['GPU']) if isinstance(n_gpus, int): os.environ["CUDA_VISIBLE_DEVICES"] = str(list(range(n_gpus)))[1:-1] elif isinstance(n_gpus, (tuple, list)): os.environ["CUDA_VISIBLE_DEVICES"] = str(n_gpus)[1:-1] n_gpus = len(n_gpus) else: ms.print_err("GPUs specification {} not valid".format(n_gpus)) cnfg['n_gpus'] = n_gpus # GPU memory fraction if n_gpus > 0: tf.set_random_seed(cnfg['seed']) tf_cnfg = tf.ConfigProto() tf_cnfg.gpu_options.per_process_gpu_memory_fraction = args['FGPU'] tf_session = tf.Session(config=tf_cnfg) K.set_session(tf_session) if not cnfg['data_class'] in pl.categories: ms.print_err("Category {} not valid".format(cnfg['data_class'])) # specialize image shape according to data category h, w = pl.sizes[cnfg['data_class']] cnfg['img_size'] = (w, h, 3) # share globals ar.cnfg = cnfg tr.cnfg = cnfg
def get_optim(): """ ------------------------------------------------------------------------------------------------- Return an Optimizer according to the object attribute return: [keras.optimizers.Optimizer] ------------------------------------------------------------------------------------------------- """ if cnfg['optimizer'] == 'ADAGRAD': return optimizers.Adagrad(lr=cnfg['lrate']) if cnfg['optimizer'] == 'SDG': return optimizers.SGD(lr=cnfg['lrate']) if cnfg['optimizer'] == 'RMS': return optimizers.RMSprop(lr=cnfg['lrate']) if cnfg['optimizer'] == 'ADAM': return optimizers.Adam(lr=cnfg['lrate']) ms.print_err("Optimizer {} not valid".format(cnfg['optimizer']))
def _get_init(self): """ ------------------------------------------------------------------------------------------------- Return an Initializer according to the object attribute return: [keras.initializers.Initializer] ------------------------------------------------------------------------------------------------- """ if self.k_initializer == 'RUNIF': return initializers.RandomUniform(minval=-0.05, maxval=0.05, seed=cnfg['seed']) if self.k_initializer == 'GLOROT': return initializers.glorot_normal(seed=cnfg['seed']) if self.k_initializer == 'HE': return initializers.he_normal(seed=cnfg['seed']) ms.print_err("Initializer {} not valid".format(self.k_initializer))
def create_model(): """ ----------------------------------------------------------------------------------------------------- Model architecture and weight training ----------------------------------------------------------------------------------------------------- """ global nn, test_set, test_str ar.TRAIN = args['TRAIN'] nn = ar.create_model() if args['LOAD'] is not None: if not ar.load_model(nn, args['LOAD']): ms.print_err("Failed to load weights from {}".format(args['LOAD'])) if args['TRAIN']: lg = os.path.join(dir_current, log_time) hs = tr.train_model(nn, lg) tr.plot_history(hs, os.path.join(dir_current, 'loss')) if SAVE: ar.save_model(nn)
def define_model(self, mname='Classifier'): """ ------------------------------------------------------------------------------------------------- Define the structure of the classifier mname: [str] name of the model return: [keras.engine.training.Model] ------------------------------------------------------------------------------------------------- """ i_conv, i_pool, i_dnse = 3 * [0] # for keeping count enc_arch_layout = self.arch_layout.split(layer_code['stop'])[0] init = self._get_init() kreg = self._get_regul() # INPUT LAYER self.input = layers.Input( shape=self.img_size) # height, width, channels x = self.input for i, layer in enumerate(enc_arch_layout): # CONVOLUTIONAL LAYER if layer == layer_code['conv']: x = layers.Conv2D( self.conv_filters[i_conv], # number of filters kernel_size=self. conv_kernel_size[i_conv], # size of window strides=self.conv_strides[i_conv], # stride (window shift) padding=self. conv_padding[i_conv], # zero-padding around the image activation=self. conv_activation[i_conv], # activation function kernel_initializer=init, kernel_regularizer= kreg, # TODO check also activity_regularizer use_bias=True, # TODO watch out for the biases! trainable=self.conv_train[i_conv], name='conv{}'.format(self.i_conv))(x) i_conv += 1 self.i_conv += 1 # MAX POOLING LAYER elif layer == layer_code['pool']: x = layers.MaxPooling2D( pool_size=self.pool_size[i_pool], # pooling size padding=self. conv_padding[i_pool], # zero-padding around the image name='pool{}'.format(self.i_pool))(x) i_pool += 1 self.i_pool += 1 # DENSE LAYERs elif layer == layer_code['dnse']: x = layers.Dense( self.dnse_size[i_dnse], # dimensionality of the output activation=self. dnse_activation[i_dnse], # activation function trainable=self.dnse_train[i_dnse], name='dnse{}'.format(self.i_dnse))(x) i_dnse += 1 self.i_dnse += 1 # FLATTEN LAYER # NOTE it supposes a single flatten layer in the architecture elif layer == layer_code['flat']: x = layers.Flatten(name='flat')(x) else: ms.print_err("Layer code '{}' not valid".format(layer)) # CLASSIFICATION LAYER # NOTE: it supposes that the first value is the probability that there is an object # and the second one the probability that there is no object # this is in fact a binary classification, but has been left as a two-class structure # for compatibility c = layers.Dense(2, activation='softmax', name='class')(x) return models.Model(inputs=self.input, outputs=c, name=mname)
def __init__(self): """ ------------------------------------------------------------------------------------------------- Initialize class attributes usign the config dicitonary, and create the network model. When using multi_gpu_model, Keras recommends to instantiate the model under a CPU device scope, so that the model's weights are hosted on CPU memory. Otherwise they may end up hosted on a GPU, which would complicate weight sharing. https://keras.io/utils/#multi_gpu_model ------------------------------------------------------------------------------------------------- """ self.arch_layout = None # [str] code describing the order of layers in the model self.img_size = None # [list] use 'channels_last' convention self.ref_model = None # [str] optional reference model from which to load weights self.k_initializer = None # [str] code specifying the type of convolution initializer self.k_regularizer = None # [str] code specifying the type of convolution regularizer self.conv_filters = None # [list of int] number of kernels for each convolution self.conv_kernel_size = None # [list of int] (square) size of kernels for each convolution self.conv_strides = None # [list of int] stride for each convolution self.conv_padding = None # [list of str] padding (same/valid) for each convolution self.conv_activation = None # [list of str] activation function for each convolution self.conv_train = None # [list of bool] False to lock training of each convolution self.pool_size = None # [list of int] pooling size for each MaxPooling self.dnse_size = None # [list of int] size of each dense layer self.dnse_activation = None # [list of str] activation function for each dense layer self.dnse_train = None # [list of bool] False to lock training of each dense layer # initialize class attributes with values from cnfg dict for k in self.__dict__: if k not in cnfg: ms.print_err( "Attribute '{}' of class '{}' not indicated".format( k, self.__class__)) exec("self.{} = cnfg[ '{}' ]".format(k, k)) # check if the string defining the architecture layout contains incorrect chars s0 = set(layer_code.values()) # accepted chars s1 = set(self.arch_layout) # chars passed as config if s1 - s0: ms.print_err("Incorrect code {} for architecture layout".format( self.arch_layout)) # check if the architecture layout is well defined if self.arch_layout.count(layer_code['flat']) > 1: ms.print_wrn( "Multiple flatten layer found. The architecture may be ill-defined" ) if self.arch_layout.count(layer_code['rshp']) > 1: ms.print_wrn( "Multiple reshape layer found. The architecture may be ill-defined" ) # keep a global count of layers per kind, to ensure different names for layers that are at # the same level in the architecture, but in different branches self.i_conv = 1 self.i_pool = 1 self.i_dnse = 1 self.i_dcnv = 1 # create model if cnfg['n_gpus'] > 1: with tf.device('/cpu:0'): self.model = self.define_model(mname=cnfg['data_class']) else: self.model = self.define_model(mname=cnfg['data_class']) assert cnfg[ 'n_conv' ] == len( self.conv_filters ) == len( self.conv_kernel_size ) == \ len( self.conv_strides ) == len( self.conv_padding ) == len( self.conv_activation ) == \ len( self.conv_train ) assert cnfg['n_dnse'] == len(self.dnse_size) == len( self.dnse_activation) == len(self.dnse_train) assert cnfg['n_pool'] == len(self.pool_size) # load from a possible reference model if self.ref_model is not None: if not load_model(self.model, self.ref_model): ms.print_err("Failed to load weights from {}".format( self.ref_model)) model_summary(self.model, fname=cnfg['data_class'])