コード例 #1
0
ファイル: train.py プロジェクト: swcho84/pelee_keras
                       ground_truth_available=True,
                       include_classes='all',
                       ret=False)

# We need the `classes_to_cats` dictionary. Read the documentation of this function to understand why.
cats_to_classes, classes_to_cats, cats_to_names, classes_to_names = get_coco_category_maps(
    train_annotations_filename)

# set the image transformations for pre-processing and data augmentation options.
# For the training generator:
ssd_data_augmentation = SSDDataAugmentation(img_height=image_size[0],
                                            img_width=image_size[1],
                                            background=subtract_mean)

# For the validation generator:
convert_to_3_channels = ConvertTo3Channels()
resize = Resize(height=image_size[0], width=image_size[1])

# instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

# The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
predictor_sizes = [
    model.get_layer('ssd_cls1conv2_bn').output_shape[1:3],
    model.get_layer('ssd_cls2conv2_bn').output_shape[1:3],
    model.get_layer('ssd_cls3conv2_bn').output_shape[1:3],
    model.get_layer('ssd_cls4conv2_bn').output_shape[1:3],
    model.get_layer('ssd_cls5conv2_bn').output_shape[1:3]
]

ssd_input_encoder = SSDInputEncoder(
    img_height=image_size[0],
コード例 #2
0
    def train(self):
        # build model
        model = mobilenet_v2_ssd(self.training_config)

        # load weights
        model.load_weights(self.weights_path, by_name=True)

        # compile the model
        adam = Adam(lr=0.001,
                    beta_1=0.9,
                    beta_2=0.999,
                    epsilon=1e-08,
                    decay=0.0)
        ssd_loss = SSDLoss(neg_pos_ratio=3, alpha=1.0)
        # set_trainable(r"(ssd\_[cls|box].*)", model)
        model.compile(optimizer=adam, loss=ssd_loss.compute_loss)

        print(model.summary())

        # load data
        train_dataset = DataGenerator(load_images_into_memory=False,
                                      hdf5_dataset_path=None)
        val_dataset = DataGenerator(load_images_into_memory=False,
                                    hdf5_dataset_path=None)

        train_dataset.parse_json(
            images_dirs=[self.train_dir],
            annotations_filenames=[self.train_annotations],
            ground_truth_available=True,
            include_classes='all',
            ret=False)
        val_dataset.parse_json(images_dirs=[self.val_dir],
                               annotations_filenames=[self.val_annotations],
                               ground_truth_available=True,
                               include_classes='all',
                               ret=False)

        # We need the `classes_to_cats` dictionary. Read the documentation of this function to understand why.
        cats_to_classes, classes_to_cats, cats_to_names, classes_to_names = get_coco_category_maps(
            train_annotations_filename)

        # set the image transformations for pre-processing and data augmentation options.
        # For the training generator:
        ssd_data_augmentation = SSDDataAugmentation(img_height=image_size[0],
                                                    img_width=image_size[1],
                                                    background=subtract_mean)

        # For the validation generator:
        convert_to_3_channels = ConvertTo3Channels()
        resize = Resize(height=image_size[0], width=image_size[1])

        # instantiate an encoder that can encode ground truth labels into the format needed by the SSD loss function.

        # The encoder constructor needs the spatial dimensions of the model's predictor layers to create the anchor boxes.
        predictor_sizes = [
            model.get_layer('ssd_cls1conv2_bn').output_shape[1:3],
            model.get_layer('ssd_cls2conv2_bn').output_shape[1:3],
            model.get_layer('ssd_cls3conv2_bn').output_shape[1:3],
            model.get_layer('ssd_cls4conv2_bn').output_shape[1:3],
            model.get_layer('ssd_cls5conv2_bn').output_shape[1:3],
            model.get_layer('ssd_cls6conv2_bn').output_shape[1:3]
        ]

        ssd_input_encoder = SSDInputEncoder(
            img_height=image_size[0],
            img_width=image_size[1],
            n_classes=n_classes,
            predictor_sizes=predictor_sizes,
            scales=scales,
            aspect_ratios_per_layer=aspect_ratios_per_layer,
            two_boxes_for_ar1=two_boxes_for_ar1,
            steps=steps,
            offsets=offsets,
            clip_boxes=clip_boxes,
            variances=variances,
            matching_type='multi',
            pos_iou_threshold=0.5,
            neg_iou_limit=0.3,
            normalize_coords=normalize_coords)

        # create the generator handles that will be passed to Keras' `fit_generator()` function.

        train_generator = train_dataset.generate(
            batch_size=batch_size,
            shuffle=True,
            transformations=[ssd_data_augmentation],
            label_encoder=ssd_input_encoder,
            returns={'processed_images', 'encoded_labels'},
            keep_images_without_gt=False)

        val_generator = val_dataset.generate(
            batch_size=batch_size,
            shuffle=False,
            transformations=[convert_to_3_channels, resize],
            label_encoder=ssd_input_encoder,
            returns={'processed_images', 'encoded_labels'},
            keep_images_without_gt=False)

        # Get the number of samples in the training and validations datasets.
        train_dataset_size = train_dataset.get_dataset_size()
        val_dataset_size = val_dataset.get_dataset_size()

        print("Number of images in the training dataset:\t{:>6}".format(
            train_dataset_size))
        print("Number of images in the validation dataset:\t{:>6}".format(
            val_dataset_size))

        callbacks = [
            LearningRateScheduler(schedule=lr_schedule, verbose=1),
            TensorBoard(log_dir=log_dir,
                        histogram_freq=0,
                        write_graph=True,
                        write_images=False),
            ModelCheckpoint(os.path.join(
                log_dir,
                "ssdseg_coco_{epoch:02d}_loss-{loss:.4f}_val_loss-{val_loss:.4f}.h5"
            ),
                            monitor='val_loss',
                            verbose=1,
                            save_best_only=True,
                            save_weights_only=True)
        ]

        model.fit_generator(train_generator,
                            epochs=1000,
                            steps_per_epoch=1000,
                            callbacks=callbacks,
                            validation_data=val_generator,
                            validation_steps=100,
                            initial_epoch=0)
コード例 #3
0
def predict_all_to_json(out_file,
                        model,
                        img_height,
                        img_width,
                        classes_to_cats,
                        data_generator,
                        batch_size,
                        data_generator_mode='resize',
                        model_mode='training',
                        confidence_thresh=0.01,
                        iou_threshold=0.45,
                        top_k=200,
                        pred_coords='centroids',
                        normalize_coords=True):
    """
    Runs detection predictions over the whole dataset given a model and saves them in a JSON file
    in the MS COCO detection results format.
    Arguments:
        out_file (str): The file name (full path) under which to save the results JSON file.
        model (Keras model): A Keras SSD model object.
        img_height (int): The input image height for the model.
        img_width (int): The input image width for the model.
        classes_to_cats (dict): A dictionary that maps the consecutive class IDs predicted by the model
            to the non-consecutive original MS COCO category IDs.
        data_generator (DataGenerator): A `DataGenerator` object with the evaluation dataset.
        batch_size (int): The batch size for the evaluation.
        data_generator_mode (str, optional): Either of 'resize' or 'pad'. If 'resize', the input images will
            be resized (i.e. warped) to `(img_height, img_width)`. This mode does not preserve the aspect ratios of the
            images.
            If 'pad', the input images will be first padded so that they have the aspect ratio defined by `img_height`
            and `img_width` and then resized to `(img_height, img_width)`. This mode preserves the aspect ratios of the
            images.
        model_mode (str, optional): The mode in which the model was created, i.e. 'training', 'inference' or
            'inference_fast'.
            This is needed in order to know whether the model output is already decoded or still needs to be decoded.
            Refer to the model documentation for the meaning of the individual modes.
        confidence_thresh (float, optional): A float in [0,1), the minimum classification confidence in a specific
            positive class in order to be considered for the non-maximum suppression stage for the respective class.
            A lower value will result in a larger part of the selection process being done by the non-maximum
            suppression
            stage, while a larger value will result in a larger part of the selection process happening in the
            confidence thresholding stage.
        iou_threshold (float, optional): A float in [0,1]. All boxes with a Jaccard similarity of greater than
            `iou_threshold` with a locally maximal box will be removed from the set of predictions for a given class,
            where 'maximal' refers to the box score.
        top_k (int, optional): The number of highest scoring predictions to be kept for each batch item after the
            non-maximum suppression stage. Defaults to 200, following the paper.
        input_coords (str, optional): The box coordinate format that the model outputs. Can be either 'centroids'
            for the format `(cx, cy, w, h)` (box center coordinates, width, and height), 'minmax' for the format
            `(xmin, xmax, ymin, ymax)`, or 'corners' for the format `(xmin, ymin, xmax, ymax)`.
        normalize_coords (bool, optional): Set to `True` if the model outputs relative coordinates
            (i.e. coordinates in [0,1]) and you wish to transform these relative coordinates back to absolute
            coordinates. If the model outputs relative coordinates, but you do not want to convert them back
            to absolute coordinates, set this to `False`. Do not set this to `True` if the model already outputs
            absolute coordinates, as that would result in incorrect coordinates. Requires `img_height`
            and `img_width` if set to `True`.
    Returns:
        None.
    """

    convert_to_3_channels = ConvertTo3Channels()
    resize = Resize(height=img_height, width=img_width)
    if data_generator_mode == 'resize':
        transformations = [convert_to_3_channels, resize]
    elif data_generator_mode == 'pad':
        random_pad = RandomPadFixedAR(patch_aspect_ratio=img_width /
                                      img_height,
                                      clip_boxes=False)
        transformations = [convert_to_3_channels, random_pad, resize]
    else:
        raise ValueError(
            "Unexpected argument value: `data_generator_mode` can be either of 'resize' or 'pad', \
            but received '{}'.".format(data_generator_mode))

    # Set the generator parameters.
    generator = data_generator.generate(
        batch_size=batch_size,
        shuffle=False,
        transformations=transformations,
        label_encoder=None,
        returns={'processed_images', 'image_ids', 'inverse_transform'},
        keep_images_without_gt=True)
    # Put the results in this list.
    results = []
    # Compute the number of batches to iterate over the entire dataset.
    n_images = data_generator.get_dataset_size()
    print("Number of images in the evaluation dataset: {}".format(n_images))
    n_batches = int(ceil(n_images / batch_size))
    # Loop over all batches.
    tr = trange(n_batches, file=sys.stdout)
    tr.set_description('Producing results file')
    for i in tr:
        # Generate batch.
        batch_X, batch_image_ids, batch_inverse_transforms = next(generator)
        # Predict.
        y_pred = model.predict(batch_X)
        # If the model was created in 'training' mode, the raw predictions need to
        # be decoded and filtered, otherwise that's already taken care of.
        if model_mode == 'training':
            # Decode.
            y_pred = decode_detections(y_pred,
                                       confidence_thresh=confidence_thresh,
                                       iou_threshold=iou_threshold,
                                       top_k=top_k,
                                       input_coords=pred_coords,
                                       normalize_coords=normalize_coords,
                                       img_height=img_height,
                                       img_width=img_width)
        else:
            # Filter out the all-zeros dummy elements of `y_pred`.
            y_pred_filtered = []
            for i in range(len(y_pred)):
                y_pred_filtered.append(y_pred[i][y_pred[i, :, 0] != 0])
            y_pred = y_pred_filtered
        # Convert the predicted box coordinates for the original images.
        y_pred = apply_inverse_transforms(y_pred, batch_inverse_transforms)

        # Convert each predicted box into the results format.
        for k, batch_item in enumerate(y_pred):
            for box in batch_item:
                class_id = box[0]
                # Transform the consecutive class IDs back to the original COCO category IDs.
                cat_id = classes_to_cats[class_id]
                # Round the box coordinates to reduce the JSON file size.
                xmin = float(round(box[2], 1))
                ymin = float(round(box[3], 1))
                xmax = float(round(box[4], 1))
                ymax = float(round(box[5], 1))
                width = xmax - xmin
                height = ymax - ymin
                bbox = [xmin, ymin, width, height]
                result = {}
                result['image_id'] = batch_image_ids[k]
                result['category_id'] = cat_id
                result['score'] = float(round(box[1], 3))
                result['bbox'] = bbox
                results.append(result)

    with open(out_file, 'w') as f:
        json.dump(results, f)

    print("Prediction results saved in '{}'".format(out_file))