Exemplo n.º 1
0
def make_dataset(data_generator, data_format, batch_size, mode):
    first = next(data_generator())

    if mode == tf.estimator.ModeKeys.PREDICT:
        types = tf.uint8
        shapes = first.shape
    else:
        types = (tf.uint8, tf.uint8)
        shapes = (first[0].shape, first[1].shape)

    dataset = Dataset.from_generator(data_generator, types, shapes)

    if mode == tf.estimator.ModeKeys.TRAIN:
        dataset = dataset.shuffle(buffer_size=10)
        dataset = dataset.repeat()

    process_data_fn = process_image if mode == tf.estimator.ModeKeys.PREDICT else process_image_label
    dataset = dataset.map(partial(process_data_fn, data_format=data_format),
                          num_parallel_calls=64)

    dataset = dataset.batch(batch_size)

    if mode == tf.estimator.ModeKeys.TRAIN:
        dataset = dataset.map(partial(augment_data))

    dataset = dataset.prefetch(batch_size)

    return dataset
Exemplo n.º 2
0
    def _dataset_with_targets(self, Xs, Y, train, context=None):
        if not callable(Xs) and not callable(Y):
            if self.config.use_auxiliary_info:
                dataset = lambda: zip(
                    Xs, Y, context
                )  # Do not need to check if context is callable - it is turned in along with Xs, and thus must have the same form
            else:
                dataset = lambda: zip(Xs, Y)
        elif callable(Xs) and callable(Y):
            if self.config.use_auxiliary_info:
                dataset = lambda: zip(Xs(), Y(), context()
                                      )  # encode one sample at a time.
            else:
                dataset = lambda: zip(Xs(), Y())
        else:
            raise ValueError(
                "Either neither or both of Xs and Y should be callable, not a mixture"
            )

        dataset_encoded = lambda: itertools.chain.from_iterable(
            map(lambda xy: self.text_to_tokens_mask(*xy), dataset()))

        if not callable(Y) and train:
            dataset_encoded_list = list(dataset_encoded())
            dataset_encoded_list = self._filter_empty_examples(
                dataset_encoded_list)
            class_counts = self._compute_class_counts(dataset_encoded_list)
            self.config.dataset_size = len(dataset_encoded_list)
            if self.config.class_weights is not None:
                self.config.class_weights = compute_class_weights(
                    class_weights=self.config.class_weights,
                    class_counts=class_counts)
        shape_def = self.feed_shape_type_def()
        return Dataset.from_generator(
            lambda: self.wrap_tqdm(dataset_encoded(), train), *shape_def)
Exemplo n.º 3
0
    def _dataset_without_targets(self,
                                 Xs,
                                 train,
                                 context=None,
                                 update_hook=None):
        if context is not None:
            # we assume that X must have known length if we also provide context so this is safe
            if callable(Xs):
                Xs_ = Xs()
            else:
                Xs_ = Xs
            Xs_gen = lambda: zip(Xs_, [None] * len(Xs_), context)
            Xs_fn = lambda: self.wrap_tqdm(
                Xs_gen(), train, update_hook=update_hook)
            dataset_encoded = lambda: itertools.chain.from_iterable(
                map(lambda xyc: self.text_to_tokens_mask(*xyc), Xs_fn()))
        else:
            if not callable(Xs):
                Xs_fn = lambda: self.wrap_tqdm(
                    Xs, train, update_hook=update_hook)
            else:
                Xs_fn = lambda: self.wrap_tqdm(
                    Xs(), train, update_hook=update_hook)
            dataset_encoded = lambda: itertools.chain.from_iterable(
                map(self.text_to_tokens_mask, Xs_fn()))

        if not callable(Xs) and self.config.chunk_long_sequences:
            # Adjust dataset size to account for long documents being chunked
            dataset_encoded_list = list(dataset_encoded())
            self.config.dataset_size = len(dataset_encoded_list)
        types, shapes = self.feed_shape_type_def()
        return Dataset.from_generator(dataset_encoded, types[0],
                                      shapes[0])  # 0s cut out the targets
Exemplo n.º 4
0
    def _dataset_with_targets(self, Xs, Y, train):
        if not callable(Xs) and not callable(Y):
            dataset = lambda: zip(Xs, Y)
        elif callable(Xs) and callable(Y):
            dataset = lambda: zip(Xs(), Y())  # encode one sample at a time.
        else:
            raise ValueError(
                "Either neither or both of Xs and Y should be callable, not a mixture"
            )

        dataset_encoded = lambda: itertools.chain.from_iterable(
            map(lambda xy: self.text_to_tokens_mask(*xy), dataset()))
        shape_def = self.feed_shape_type_def()

        if not callable(Y) and train:
            dataset_encoded_list = list(dataset_encoded())
            class_counts = self._compute_class_counts(dataset_encoded_list)
            self.config.dataset_size = len(dataset_encoded_list)
            if self.config.class_weights is not None:
                self.config.class_weights = compute_class_weights(
                    class_weights=self.config.class_weights,
                    class_counts=class_counts)

        return Dataset.from_generator(
            lambda: self.wrap_tqdm(dataset_encoded(), train), *shape_def)
Exemplo n.º 5
0
    def _dataset_without_targets(self, Xs, train):
        if not callable(Xs):
            Xs_fn = lambda: self.wrap_tqdm(Xs, train)
        else:
            Xs_fn = lambda: self.wrap_tqdm(Xs(), train)

        dataset_encoded = lambda: itertools.chain.from_iterable(map(self.text_to_tokens_mask, Xs_fn()))
        types, shapes = self.feed_shape_type_def()
        return Dataset.from_generator(dataset_encoded, types[0], shapes[0])  # 0s cut out the targets
Exemplo n.º 6
0
    def __init__(self,
                 *,
                 batch_size,
                 num_classes,
                 prefetch_size=1e8,
                 shuffle_size=1000):
        super().__init__(batch_size, prefetch_size, shuffle_size)

        self._num_classes = num_classes

        (x_train, y_train), (x_test, y_test) = self._load_data()

        x_train = np.float32(x_train) / 255.
        x_test = np.float32(x_test) / 255.

        y_train = np.float32(self._to_one_hot(y_train))
        y_test = np.float32(self._to_one_hot(y_test))

        self.train_size = y_train.shape[0]
        self.test_size = y_test.shape[0]

        output_types = (x_train.dtype, y_train.dtype)
        output_shape = (x_train.shape[1:], y_train.shape[1:])

        train_dataset = Dataset.from_generator(lambda: self._gen_data(x_train, y_train), output_types, output_shape). \
            shuffle(self.shuffle_size).\
            batch(self.batch_size, drop_remainder=True).\
            prefetch(self.prefetch_size)

        test_dataset = Dataset.from_generator(lambda: self._gen_data(x_test, y_test), output_types, output_shape). \
            shuffle(self.shuffle_size).\
            batch(self.batch_size, drop_remainder=True).\
            prefetch(self.prefetch_size)

        iter_ = Iterator.from_structure(train_dataset.output_types,
                                        train_dataset.output_shapes)

        self.x, self.y = iter_.get_next()

        self.train_init_op = iter_.make_initializer(train_dataset)
        self.test_init_op = iter_.make_initializer(test_dataset)
Exemplo n.º 7
0
    def get_dataset(self, mode: str, max_num=None, **kwargs) -> Dataset:
        dataset_type, dataset_shape = self.model.get_dataset_info(
            mode, **kwargs)

        def gen():
            records = self.get_records(mode=mode, max_num=max_num, **kwargs)
            for record in records:
                rs = {k: record[k] for k, dtype in dataset_type.items()}
                yield rs

        dataset = Dataset.from_generator(generator=gen,
                                         output_types=dataset_type)
        return dataset
Exemplo n.º 8
0
    def _dataset_without_targets(self, Xs, train):
        if not callable(Xs):
            Xs_fn = lambda: self.wrap_tqdm(Xs, train)
        else:
            Xs_fn = lambda: self.wrap_tqdm(Xs(), train)

        dataset_encoded = lambda: itertools.chain.from_iterable(
            map(self.text_to_tokens_mask, Xs_fn()))
        if not callable(Xs) and self.config.chunk_long_sequences:
            # Adjust dataset size to account for long documents being chunked
            dataset_encoded_list = list(dataset_encoded())
            self.config.dataset_size = len(dataset_encoded_list)
        types, shapes = self.feed_shape_type_def()
        return Dataset.from_generator(dataset_encoded, types[0],
                                      shapes[0])  # 0s cut out the targets
Exemplo n.º 9
0
    def _dataset_with_targets(self, Xs, Y, train):
        if not callable(Xs) and not callable(Y):
            dataset = lambda: zip(Xs, Y)
        elif callable(Xs) and callable(Y):
            dataset = lambda: zip(Xs(), Y())  # encode one sample at a time.
        else:
            raise ValueError("Either neither or both of Xs and Y should be callable, not a mixture")

        dataset_encoded = lambda: itertools.chain.from_iterable(
            map(lambda xy: self.text_to_tokens_mask(*xy), dataset()))
        shape_def = self.feed_shape_type_def()
        if not callable(Y) and self.config.chunk_long_sequences:
            dataset_encoded_list = list(dataset_encoded())  # come up with a more principled way to do this .
            self.config.dataset_size = len(dataset_encoded_list)
        return Dataset.from_generator(lambda: self.wrap_tqdm(dataset_encoded(), train), *shape_def)
Exemplo n.º 10
0
def input_fn(is_training,
             data_dir,
             channel_name,
             batch_size,
             num_epochs=1,
             num_parallel_calls=1,
             multi_gpu=False,
             mode='File'):
    """Input function which provides batches for train or eval.
  Args:
    is_training: A boolean denoting whether the input is for training.
    channel_name: The directory containing the input data.
    batch_size: The number of samples per batch.
    num_epochs: The number of epochs to repeat the dataset.
    num_parallel_calls: The number of records that are processed in parallel.
      This can be optimized per data set but for generally homogeneous data
      sets, should be approximately the number of available CPU cores.
    multi_gpu: Whether this is run multi-GPU. Note that this is only required
      currently to handle the batch leftovers, and can be removed
      when that is handled directly by Estimator.

  Returns:
    A dataset that can be used for iteration.
  """
    dataset = None
    num_images = is_training and _NUM_IMAGES['train'] or _NUM_IMAGES[
        'validation']

    if mode == 'File':
        filenames = get_filenames(data_dir)
        dataset = tf.data.Dataset.from_tensor_slices(filenames)

        # Convert to individual records
        dataset = dataset.flat_map(tf.data.TFRecordDataset)
    else:
        generator = TFRecordDatasetGenerator(channel_name)
        dataset = Dataset.from_generator(generator, tf.string)

    return resnet.process_record_dataset(dataset,
                                         is_training,
                                         batch_size,
                                         parse_record,
                                         num_epochs,
                                         num_parallel_calls,
                                         examples_per_epoch=num_images,
                                         multi_gpu=multi_gpu)
def create_dataset(filelist, path, buffer_size=25, batch_size=10):
    def gen(filelist, path):
        for fn in filelist:
            data = np.float32(load_pickle(os.path.join(path, fn)))
            data = np.expand_dims(data, 4)
            data = np.repeat(data, 3, axis=4)
            for i in range(data.shape[0]):
                yield data[i, :13, :, :, :], np.zeros((13, ), dtype=np.int32)

    ds = Dataset.from_generator(
        lambda: gen(filelist, path), (tf.float32, tf.int32),
        (tf.TensorShape([13, 80, 80, 3]), tf.TensorShape([
            13,
        ])))
    ds = ds.repeat(count=None)
    ds = ds.prefetch(buffer_size)
    ds = ds.batch(batch_size)
    return ds
Exemplo n.º 12
0
    def _dataset_without_targets(self, Xs, train):
        if not callable(Xs):
            Xs_fn = lambda: self.wrap_tqdm(Xs, train)
        else:
            Xs_fn = lambda: self.wrap_tqdm(Xs(), train)

        dataset_encoded = lambda: itertools.chain.from_iterable(
            map(self.get_text_token_mask, Xs_fn()))
        if not callable(Xs) and self.config.chunk_long_sequences:
            # Adjust dataset size to account for long documents being chunked
            dataset_encoded_list = list(dataset_encoded())
            self.config.dataset_size = len(dataset_encoded_list)
        else:
            _ = (
                self.get_active_pipeline()
            )  # Call of dataset_encoded will refresh self.pipeline; if it is not called, still need to refresh

        types, _ = self.feed_shape_type_def()

        return Dataset.from_generator(dataset_encoded, output_types=types[0])
Exemplo n.º 13
0
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
Exemplo n.º 14
0
    def __init__(self, config: AppConfig, params: ModelParams):
        logger = config.logger

        logger.info('maximum length of training sent: %d' %
                    params.len_threshold)

        with JobContext('indexing all chars/chatrooms/users...', logger):
            b = db.read_text(config.data_file).map(json.loads)
            msg_stream = b.filter(lambda x: x['msgType'] == 'Text').filter(
                lambda x: len(x['text']) <= params.len_threshold)
            text_stream = msg_stream.pluck('text').distinct()
            chatroom_stream = msg_stream.pluck('chatroomName').distinct()
            user_stream = msg_stream.pluck('fromUser').distinct()

            all_chars = sorted(
                text_stream.flatten().filter(lambda x: x).distinct())
            all_rooms = sorted(chatroom_stream.compute())
            all_users = sorted(user_stream.compute())

            unknown_char_idx = 0
            reserved_chars = 1
            char2int_map = {
                c: idx + reserved_chars
                for idx, c in enumerate(all_chars)
            }

            unknown_room_idx = len(char2int_map)
            reserved_chars += len(char2int_map) + 1
            room2int_map = {
                c: idx + reserved_chars
                for idx, c in enumerate(all_rooms)
            }

            unknown_user_idx = len(room2int_map)
            reserved_chars += len(room2int_map) + 1
            user2int_map = {
                c: idx + reserved_chars
                for idx, c in enumerate(all_users)
            }

            reserved_chars += len(user2int_map)

        with JobContext('computing some statistics...', logger):
            num_sent = text_stream.count().compute()
            num_room = chatroom_stream.count().compute()
            num_user = user_stream.count().compute()
            num_char = len(char2int_map) + 1
            logger.info('# sentences: %d' % num_sent)
            logger.info('# chars: %d' % num_char)
            logger.info('# rooms: %d' % num_room)
            logger.info('# users: %d' % num_user)
            logger.info('# symbols: %d' % reserved_chars)

        with JobContext('building dataset...', logger):
            d = (msg_stream.map(lambda x: (
                [char2int_map.get(c, unknown_char_idx) for c in x['text']],
                room2int_map.get(x['chatroomName'], unknown_room_idx),
                user2int_map.get(x['fromUser'], unknown_user_idx))))

            X = d.pluck(0).compute(), d.pluck(1).compute(), d.pluck(
                2).compute()

            def gen():
                for i in range(len(X[0])):
                    yield X[0][i], len(X[0][i]), X[1][i], X[2][i]

            ds = Dataset.from_generator(
                generator=gen,
                output_types=(tf.int32, tf.int32, tf.int32, tf.int32),
                output_shapes=([None], [], [],
                               [])).shuffle(buffer_size=10000)  # type: Dataset
            self.eval_ds = ds.take(params.num_eval)
            self.train_ds = ds.skip(params.num_eval)

        self.num_char = num_char
        self.num_reserved_char = reserved_chars
        self.num_sent = num_sent
        self.num_room = num_room
        self.num_user = num_user
        self.char2int = char2int_map
        self.user2int = user2int_map
        self.room2int = room2int_map
        self.int2char = {i: c for c, i in char2int_map.items()}
        self.int2user = {i: c for c, i in user2int_map.items()}
        self.int2room = {i: c for c, i in room2int_map.items()}
        self.unknown_char_idx = unknown_char_idx
        self.unknown_user_idx = unknown_user_idx
        self.unknown_room_idx = unknown_room_idx

        params.add_hparam('num_char', num_char)
        self.params = params

        logger.info('data loading finished!')
Exemplo n.º 15
0
def train_model_retinanet(model,
                          dataset,
                          expt='',
                          test_size=.2,
                          n_epoch=10,
                          batch_size=1,
                          num_gpus=None,
                          include_masks=False,
                          panoptic=False,
                          panoptic_weight=0.1,
                          transforms=['watershed'],
                          transforms_kwargs={},
                          anchor_params=None,
                          pyramid_levels=['P3', 'P4', 'P5', 'P6', 'P7'],
                          min_objects=3,
                          mask_size=(28, 28),
                          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,
                          sigma=3.0,
                          alpha=0.25,
                          gamma=2.0,
                          score_threshold=0.01,
                          iou_threshold=0.5,
                          max_detections=100,
                          weighted_average=True,
                          lr_sched=rate_scheduler(lr=0.01, decay=0.95),
                          rotation_range=0,
                          flip=True,
                          shear=0,
                          zoom_range=0,
                          compute_map=True,
                          seed=0,
                          **kwargs):
    """Train a RetinaNet model from the given backbone.

    Adapted from:
        https://github.com/fizyr/keras-retinanet &
        https://github.com/fizyr/keras-maskrcnn

    Args:
        model (tensorflow.keras.Model): The model to train.
        dataset (str): Path to a dataset to train the model with.
        expt (str): Experiment, substring to include in model name.
        test_size (float): Percent of data to leave as test data.
        n_epoch (int): Number of training epochs.
        batch_size (int): Number of batches per training step.
        num_gpus (int): The number of GPUs to train on.
        include_masks (bool): Whether to generate masks using MaskRCNN.
        panoptic (bool): Whether to include semantic segmentation heads.
        panoptic_weight (float): Weight applied to the semantic loss.
        transforms (list): List of transform names as strings. Each transform
            will have its own semantic segmentation head.
        transforms_kwargs (list): List of dicts of optional values for each
            transform in transforms.
        anchor_params (AnchorParameters): Struct containing anchor parameters.
            If None, default values are used.
        pyramid_levels (list): Pyramid levels to attach
            the object detection heads to.
        min_objects (int): If a training image has fewer than min_objects
            objects, the image will not be used for training.
        mask_size (tuple): The size of the masks.
        log_dir (str): Filepath to save tensorboard logs. If None, disables
            the tensorboard callback.
        model_dir (str): Directory to save the model file.
        model_name (str): Name of the model (and name of output file).
        sigma (float): The point where the loss changes from L2 to L1.
        alpha (float): Scale the focal weight with alpha.
        gamma (float): Take the power of the focal weight with gamma.
        iou_threshold (float): The threshold used to consider when a detection
            is positive or negative.
        score_threshold (float): The score confidence threshold
            to use for detections.
        max_detections (int): The maximum number of detections to use per image
        weighted_average (bool): Use a weighted average in evaluation.
        optimizer (object): Pre-initialized optimizer object (SGD, Adam, etc.)
        lr_sched (function): Learning rate schedular function
        rotation_range (int): Maximum rotation range for image augmentation
        flip (bool): Enables horizontal and vertical flipping for augmentation
        shear (int): Maximum rotation range for image augmentation
        zoom_range (tuple): Minimum and maximum zoom values (0.8, 1.2)
        seed (int): Random seed
        compute_map (bool): Whether to compute mAP at end of training.
        kwargs (dict): Other parameters to pass to _transform_masks

    Returns:
        tensorflow.keras.Model: The trained model
    """

    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 = '{}_{}_{}'.format(todays_date, data_name, expt)

    model_path = os.path.join(model_dir, '{}.h5'.format(model_name))
    loss_path = os.path.join(model_dir, '{}.npz'.format(model_name))

    train_dict, test_dict = get_data(dataset, seed=seed, test_size=test_size)

    channel_axis = 1 if is_channels_first else -1
    n_classes = model.layers[-1].output_shape[channel_axis]

    n_semantic_classes = [
        layer.output_shape[channel_axis] for layer in model.layers
        if layer.name.startswith('semantic') and panoptic
    ]

    # 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:', test_dict['X'].shape)
    print('y_test shape:', test_dict['y'].shape)
    print('Output Shape:', model.layers[-1].output_shape)
    print('Number of Classes:', n_classes)

    if num_gpus is None:
        num_gpus = train_utils.count_gpus()

    print('Training on {} GPUs'.format(num_gpus))

    # evaluation of model is done on `retinanet_bbox`
    pred_model_fn = retinamask_bbox if include_masks else retinanet_bbox
    prediction_model = pred_model_fn(
        model,
        nms=True,
        anchor_params=anchor_params,
        num_semantic_heads=len(n_semantic_classes),
        panoptic=panoptic,
        class_specific_filter=False)

    retinanet_losses = losses.RetinaNetLosses(sigma=sigma,
                                              alpha=alpha,
                                              gamma=gamma,
                                              iou_threshold=iou_threshold,
                                              mask_size=mask_size)

    def semantic_loss(n_classes):
        def _semantic_loss(y_pred, y_true):
            if n_classes > 1:
                return panoptic_weight * losses.weighted_categorical_crossentropy(
                    y_true, y_pred, n_classes=n_classes)
            return panoptic_weight * MSE(y_true, y_pred)

        return _semantic_loss

    loss = {
        'regression': retinanet_losses.regress_loss,
        'classification': retinanet_losses.classification_loss
    }

    if include_masks:
        loss['masks'] = retinanet_losses.mask_loss

    if panoptic:
        # Give losses for all of the semantic heads
        for layer in model.layers:
            if layer.name.startswith('semantic'):
                n_classes = layer.output_shape[channel_axis]
                loss[layer.name] = semantic_loss(n_classes)

    model.compile(loss=loss, optimizer=optimizer)

    if num_gpus >= 2:
        # Each GPU must have at least one validation example
        if test_dict['y'].shape[0] < num_gpus:
            raise ValueError('Not enough validation data for {} GPUs. '
                             'Received {} validation sample.'.format(
                                 test_dict['y'].shape[0], num_gpus))

        # When using multiple GPUs and skip_connections,
        # the training data must be evenly distributed across all GPUs
        num_train = train_dict['y'].shape[0]
        nb_samples = num_train - num_train % batch_size
        if nb_samples:
            train_dict['y'] = train_dict['y'][:nb_samples]
            train_dict['X'] = train_dict['X'][:nb_samples]

    # this will do preprocessing and realtime data augmentation
    datagen = image_generators.RetinaNetGenerator(
        # fill_mode='constant',  # for rotations
        rotation_range=rotation_range,
        shear_range=shear,
        zoom_range=zoom_range,
        horizontal_flip=flip,
        vertical_flip=flip)

    datagen_val = image_generators.RetinaNetGenerator(
        # fill_mode='constant',  # for rotations
        rotation_range=0,
        shear_range=0,
        zoom_range=0,
        horizontal_flip=0,
        vertical_flip=0)

    train_data = datagen.flow(train_dict,
                              seed=seed,
                              include_bbox=include_masks,
                              include_masks=include_masks,
                              panoptic=panoptic,
                              transforms=transforms,
                              transforms_kwargs=transforms_kwargs,
                              pyramid_levels=pyramid_levels,
                              min_objects=min_objects,
                              anchor_params=anchor_params,
                              compute_shapes=guess_shapes,
                              batch_size=batch_size)

    val_data = datagen_val.flow(test_dict,
                                seed=seed,
                                include_bbox=include_masks,
                                include_masks=include_masks,
                                panoptic=panoptic,
                                transforms=transforms,
                                transforms_kwargs=transforms_kwargs,
                                pyramid_levels=pyramid_levels,
                                min_objects=min_objects,
                                anchor_params=anchor_params,
                                compute_shapes=guess_shapes,
                                batch_size=batch_size)

    input_type_dict = {'input': tf.float32}
    input_shape_dict = {'input': tuple([None] + list(train_data.x.shape[1:]))}
    output_type_dict = {'regression': tf.float32, 'classification': tf.float32}
    output_shape_dict = {
        'regression': (None, None, None),
        'classification': (None, None, None)
    }

    if include_masks:
        output_type_dict['masks'] = tf.float32
        output_shape_dict['masks'] = (None, None, None)

        input_type_dict['boxes_input'] = tf.float32
        input_shape_dict['boxes_input'] = (None, None, 4)

        for i, n in enumerate(n_semantic_classes):
            output_type_dict['semantic_{}'.format(i)] = tf.float32
            output_shape_dict['semantic_{}'.format(i)] = (None, None, None, n)

    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)

    eval_callback = RedirectModel(
        Evaluate(val_data,
                 iou_threshold=iou_threshold,
                 score_threshold=score_threshold,
                 max_detections=max_detections,
                 tensorboard=train_callbacks[-1] if log_dir else None,
                 weighted_average=weighted_average), prediction_model)

    train_callbacks.append(eval_callback)

    # fit the model on the batches generated by datagen.flow()
    loss_history = model.fit(
        train_dataset,
        steps_per_epoch=train_data.y.shape[0] // batch_size,
        epochs=n_epoch,
        validation_data=val_dataset,
        validation_steps=val_data.y.shape[0] // batch_size,
        callbacks=train_callbacks)

    np.savez(loss_path, loss_history=loss_history.history)

    if compute_map:
        average_precisions = evaluate(
            val_data,
            prediction_model,
            iou_threshold=iou_threshold,
            score_threshold=score_threshold,
            max_detections=max_detections,
        )

        # print evaluation
        total_instances = []
        precisions = []
        for label, (average_precision,
                    num_annotations) in average_precisions.items():
            print('{:.0f} instances of class'.format(num_annotations), label,
                  'with average precision: {:.4f}'.format(average_precision))
            total_instances.append(num_annotations)
            precisions.append(average_precision)

        if sum(total_instances) == 0:
            print('No test instances found.')
        else:
            print(
                'mAP using the weighted average of precisions among classes: {:.4f}'
                .format(
                    sum([a * b for a, b in zip(total_instances, precisions)]) /
                    sum(total_instances)))
            print('mAP: {:.4f}'.format(
                sum(precisions) / sum(x > 0 for x in total_instances)))

    return model
Exemplo n.º 16
0
def path_glob_dataset(path, pattern, recursive=True):
    return Dataset.from_generator(
        lambda: path_glob_iterator(path, pattern, recursive=recursive),
        output_types=tf.string)