def test_count_pairs(self): batches = 1 frames = 2 classes = 4 prob = 0.5 expected = batches * frames * classes * (classes + 1) / prob # channels_last y = np.random.randint(low=0, high=classes + 1, size=(batches, frames, 30, 30, 1)) pairs = tracking_utils.count_pairs(y, same_probability=prob) self.assertEqual(pairs, expected) # channels_first y = np.random.randint(low=0, high=classes + 1, size=(batches, 1, frames, 30, 30)) pairs = tracking_utils.count_pairs(y, same_probability=prob, data_format='channels_first') self.assertEqual(pairs, expected)
def train_model_siamese_daughter(model, dataset, expt='', test_size=.1, n_epoch=100, batch_size=1, num_gpus=None, crop_dim=32, min_track_length=1, neighborhood_scale_size=10, features=None, optimizer=SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True), log_dir='/data/tensorboard_logs', model_dir='/data/models', model_name=None, focal=False, gamma=0.5, lr_sched=rate_scheduler(lr=0.01, decay=0.95), rotation_range=0, flip=True, shear=0, zoom_range=0, seed=None, **kwargs): is_channels_first = K.image_data_format() == 'channels_first' if model_name is None: todays_date = datetime.datetime.now().strftime('%Y-%m-%d') data_name = os.path.splitext(os.path.basename(dataset))[0] model_name = '{}_{}_[{}]_neighs={}_epochs={}_seed={}_{}'.format( todays_date, data_name, ','.join(f[0] for f in sorted(features)), neighborhood_scale_size, n_epoch, seed, expt) model_path = os.path.join(model_dir, '{}.h5'.format(model_name)) loss_path = os.path.join(model_dir, '{}.npz'.format(model_name)) print('training on dataset:', dataset) print('saving model at:', model_path) print('saving loss at:', loss_path) train_dict, val_dict = get_data(dataset, mode='siamese_daughters', seed=seed, test_size=test_size) # the data, shuffled and split between train and test sets print('X_train shape:', train_dict['X'].shape) print('y_train shape:', train_dict['y'].shape) print('X_test shape:', val_dict['X'].shape) print('y_test shape:', val_dict['y'].shape) print('Output Shape:', model.layers[-1].output_shape) n_classes = model.layers[-1].output_shape[1 if is_channels_first else -1] def loss_function(y_true, y_pred): if focal: return losses.weighted_focal_loss(y_true, y_pred, gamma=gamma, n_classes=n_classes, from_logits=False) return losses.weighted_categorical_crossentropy(y_true, y_pred, n_classes=n_classes, from_logits=False) if num_gpus is None: num_gpus = train_utils.count_gpus() if num_gpus >= 2: batch_size = batch_size * num_gpus model = train_utils.MultiGpuModel(model, num_gpus) print('Training on {} GPUs'.format(num_gpus)) model.compile(loss=loss_function, optimizer=optimizer, metrics=['accuracy']) print('Using real-time data augmentation.') # this will do preprocessing and realtime data augmentation datagen = image_generators.SiameseDataGenerator( rotation_range=rotation_range, shear_range=shear, zoom_range=zoom_range, horizontal_flip=flip, vertical_flip=flip) datagen_val = image_generators.SiameseDataGenerator(rotation_range=0, zoom_range=0, shear_range=0, horizontal_flip=0, vertical_flip=0) total_train_pairs = tracking_utils.count_pairs(train_dict['y'], same_probability=5.0) total_test_pairs = tracking_utils.count_pairs(val_dict['y'], same_probability=5.0) train_data = datagen.flow(train_dict, crop_dim=crop_dim, batch_size=batch_size, min_track_length=min_track_length, neighborhood_scale_size=neighborhood_scale_size, features=features) val_data = datagen_val.flow( val_dict, crop_dim=crop_dim, batch_size=batch_size, min_track_length=min_track_length, neighborhood_scale_size=neighborhood_scale_size, features=features) print('total_train_pairs:', total_train_pairs) print('total_test_pairs:', total_test_pairs) print('batch size:', batch_size) print('validation_steps: ', total_test_pairs // batch_size) # fit the model on the batches generated by datagen.flow() loss_history = model.fit_generator( train_data, steps_per_epoch=total_train_pairs // batch_size, epochs=n_epoch, validation_data=val_data, validation_steps=total_test_pairs // batch_size, callbacks=[ callbacks.LearningRateScheduler(lr_sched), callbacks.ModelCheckpoint(model_path, monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=num_gpus >= 2), callbacks.TensorBoard(log_dir=os.path.join(log_dir, model_name)) ]) model.save_weights(model_path) np.savez(loss_path, loss_history=loss_history.history) return model
def train_model_siamese_daughter(model, dataset, expt='', test_size=.2, n_epoch=100, batch_size=1, num_gpus=None, crop_dim=32, min_track_length=1, neighborhood_scale_size=10, features=None, optimizer=SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True), log_dir='/data/tensorboard_logs', model_dir='/data/models', model_name=None, focal=False, gamma=0.5, lr_sched=rate_scheduler(lr=0.01, decay=0.95), rotation_range=0, flip=True, shear=0, zoom_range=0, seed=0, **kwargs): is_channels_first = K.image_data_format() == 'channels_first' if model_name is None: todays_date = datetime.datetime.now().strftime('%Y-%m-%d') data_name = os.path.splitext(os.path.basename(dataset))[0] model_name = '{}_{}_[{}]_neighs={}_epochs={}_seed={}_{}'.format( todays_date, data_name, ','.join(f[0] for f in sorted(features)), neighborhood_scale_size, n_epoch, seed, expt) model_path = os.path.join(model_dir, '{}.h5'.format(model_name)) loss_path = os.path.join(model_dir, '{}.npz'.format(model_name)) print('training on dataset:', dataset) print('saving model at:', model_path) print('saving loss at:', loss_path) train_dict, val_dict = get_data(dataset, mode='siamese_daughters', seed=seed, test_size=test_size) # the data, shuffled and split between train and test sets print('X_train shape:', train_dict['X'].shape) print('y_train shape:', train_dict['y'].shape) print('X_test shape:', val_dict['X'].shape) print('y_test shape:', val_dict['y'].shape) print('Output Shape:', model.layers[-1].output_shape) n_classes = model.layers[-1].output_shape[1 if is_channels_first else -1] def loss_function(y_true, y_pred): if focal: return losses.weighted_focal_loss(y_true, y_pred, gamma=gamma, n_classes=n_classes, from_logits=False) return losses.weighted_categorical_crossentropy(y_true, y_pred, n_classes=n_classes, from_logits=False) if num_gpus is None: num_gpus = train_utils.count_gpus() print('Training on {} GPUs'.format(num_gpus)) model.compile(loss=loss_function, optimizer=optimizer, metrics=['accuracy']) print('Using real-time data augmentation.') # this will do preprocessing and realtime data augmentation datagen = image_generators.SiameseDataGenerator( rotation_range=rotation_range, shear_range=shear, zoom_range=zoom_range, horizontal_flip=flip, vertical_flip=flip) datagen_val = image_generators.SiameseDataGenerator(rotation_range=0, zoom_range=0, shear_range=0, horizontal_flip=0, vertical_flip=0) # same_probability values have varied from 0.5 to 5.0 total_train_pairs = tracking_utils.count_pairs(train_dict['y'], same_probability=5.0) total_test_pairs = tracking_utils.count_pairs(val_dict['y'], same_probability=5.0) train_data = datagen.flow(train_dict, seed=seed, crop_dim=crop_dim, batch_size=batch_size, min_track_length=min_track_length, neighborhood_scale_size=neighborhood_scale_size, features=features) val_data = datagen_val.flow( val_dict, seed=seed, crop_dim=crop_dim, batch_size=batch_size, min_track_length=min_track_length, neighborhood_scale_size=neighborhood_scale_size, features=features) print('total_train_pairs:', total_train_pairs) print('total_test_pairs:', total_test_pairs) print('batch size:', batch_size) print('validation_steps: ', total_test_pairs // batch_size) # Make dicts to map the two generator outputs to the Dataset and model # input here is model input and output is model output features = sorted(features) input_type_dict = {} input_shape_dict = {} for feature in features: feature_name1 = '{}_input1'.format(feature) feature_name2 = '{}_input2'.format(feature) input_type_dict[feature_name1] = tf.float32 input_type_dict[feature_name2] = tf.float32 if feature == 'appearance': app1 = tuple([ None, train_data.min_track_length, train_data.crop_dim, train_data.crop_dim, 1 ]) app2 = tuple( [None, 1, train_data.crop_dim, train_data.crop_dim, 1]) input_shape_dict[feature_name1] = app1 input_shape_dict[feature_name2] = app2 elif feature == 'distance': dist1 = tuple([None, train_data.min_track_length, 2]) dist2 = tuple([None, 1, 2]) input_shape_dict[feature_name1] = dist1 input_shape_dict[feature_name2] = dist2 elif feature == 'neighborhood': neighborhood_size = 2 * train_data.neighborhood_scale_size + 1 neigh1 = tuple([ None, train_data.min_track_length, neighborhood_size, neighborhood_size, 1 ]) neigh2 = tuple([None, 1, neighborhood_size, neighborhood_size, 1]) input_shape_dict[feature_name1] = neigh1 input_shape_dict[feature_name2] = neigh2 elif feature == 'regionprop': rprop1 = tuple([None, train_data.min_track_length, 3]) rprop2 = tuple([None, 1, 3]) input_shape_dict[feature_name1] = rprop1 input_shape_dict[feature_name2] = rprop2 output_type_dict = {'classification': tf.int32} # Ouput_shape has to be None because we dont know how many cells output_shape_dict = {'classification': (None, 3)} train_dataset = Dataset.from_generator(lambda: train_data, (input_type_dict, output_type_dict), output_shapes=(input_shape_dict, output_shape_dict)) val_dataset = Dataset.from_generator(lambda: val_data, (input_type_dict, output_type_dict), output_shapes=(input_shape_dict, output_shape_dict)) train_callbacks = get_callbacks(model_path, lr_sched=lr_sched, tensorboard_log_dir=log_dir, save_weights_only=num_gpus >= 2, monitor='val_loss', verbose=1) # fit the model on the batches generated by datagen.flow() loss_history = model.fit(train_dataset, steps_per_epoch=total_train_pairs // batch_size, epochs=n_epoch, validation_data=val_dataset, validation_steps=total_test_pairs // batch_size, callbacks=train_callbacks) np.savez(loss_path, loss_history=loss_history.history) return model