Implemented partitioning of observations

Signed-off-by: Jim Martens <github@2martens.de>
This commit is contained in:
2019-05-22 13:58:09 +02:00
parent 5feae7f9a2
commit 1763fc5917
2 changed files with 74 additions and 23 deletions

View File

@ -222,8 +222,6 @@ def _ssd_test(args: argparse.Namespace) -> None:
with open(filename, "rb") as file: with open(filename, "rb") as file:
# get predictions per batch # get predictions per batch
_predictions = pickle.load(file) _predictions = pickle.load(file)
# select only forward pass
_predictions = _predictions[0]
predictions.extend(_predictions) predictions.extend(_predictions)
del _predictions del _predictions

View File

@ -37,16 +37,18 @@ Functions:
import os import os
import pickle import pickle
import time import time
from typing import Dict from typing import Dict, List, Sequence
from typing import Optional from typing import Optional
import numpy as np import numpy as np
import tensorflow as tf import tensorflow as tf
from tensorflow.python.ops import summary_ops_v2 from tensorflow.python.ops import summary_ops_v2
from twomartens.masterthesis.ssd_keras.bounding_box_utils import bounding_box_utils
from twomartens.masterthesis.ssd_keras.keras_loss_function import keras_ssd_loss from twomartens.masterthesis.ssd_keras.keras_loss_function import keras_ssd_loss
from twomartens.masterthesis.ssd_keras.models import keras_ssd300 from twomartens.masterthesis.ssd_keras.models import keras_ssd300
from twomartens.masterthesis.ssd_keras.models import keras_ssd300_dropout from twomartens.masterthesis.ssd_keras.models import keras_ssd300_dropout
from twomartens.masterthesis.ssd_keras.ssd_encoder_decoder import ssd_output_decoder
K = tf.keras.backend K = tf.keras.backend
tfe = tf.contrib.eager tfe = tf.contrib.eager
@ -187,26 +189,34 @@ def _predict_one_epoch(dataset: tf.data.Dataset,
from tensorflow.python.eager import context from tensorflow.python.eager import context
for inputs, labels in dataset: for inputs, labels in dataset:
decoded_predictions_batch = []
if use_dropout: if use_dropout:
detections = None
batch_size = None
for _ in range(forward_passes_per_image): for _ in range(forward_passes_per_image):
result = np.array(ssd(inputs)) result = np.array(ssd(inputs))
result_filtered = [] if batch_size is None:
# iterate over result of images batch_size = result.shape[0]
for i in range(result.shape[0]): if detections is None:
detections = [[] for _ in range(batch_size)]
for i in range(batch_size):
batch_item = result[i]
detections[i].extend(batch_item)
observations = np.asarray(_get_observations(detections))
observations = ssd_output_decoder.decode_detections_fast(observations)
result_transformed = []
for i in range(batch_size):
# apply inverse transformations to predicted bounding box coordinates # apply inverse transformations to predicted bounding box coordinates
# filter out dummy all-zero results
x_reverse = labels[i, 0, 5] x_reverse = labels[i, 0, 5]
y_reverse = labels[i, 0, 6] y_reverse = labels[i, 0, 6]
filtered = result[i][result[i, :, 0] != 0] filtered = observations[i]
filtered[:, 2] *= x_reverse filtered[:, 2] *= x_reverse
filtered[:, 4] *= x_reverse filtered[:, 4] *= x_reverse
filtered[:, 3] *= y_reverse filtered[:, 3] *= y_reverse
filtered[:, 5] *= y_reverse filtered[:, 5] *= y_reverse
result_filtered.append(filtered) result_transformed.append(filtered)
result = result_filtered decoded_predictions_batch = result_transformed
decoded_predictions_batch.append(result)
del result
else: else:
result = np.array(ssd(inputs)) result = np.array(ssd(inputs))
result_filtered = [] result_filtered = []
@ -222,9 +232,7 @@ def _predict_one_epoch(dataset: tf.data.Dataset,
filtered[:, 3] *= y_reverse filtered[:, 3] *= y_reverse
filtered[:, 5] *= y_reverse filtered[:, 5] *= y_reverse
result_filtered.append(filtered) result_filtered.append(filtered)
result = result_filtered decoded_predictions_batch = result_filtered
decoded_predictions_batch.append(result)
del result
# save predictions batch-wise to prevent memory problems # save predictions batch-wise to prevent memory problems
if nr_digits is not None: if nr_digits is not None:
@ -256,6 +264,51 @@ def _predict_one_epoch(dataset: tf.data.Dataset,
return outputs return outputs
def _get_observations(detections: Sequence[Sequence[np.ndarray]]) -> List[List[np.ndarray]]:
batch_size = len(detections)
observations = [[] for _ in range(batch_size)]
# iterate over images
for i in range(batch_size):
detections_image = np.asarray(detections[i])
overlaps = bounding_box_utils.iou(detections_image[:, -12:-8],
detections_image[:, -12:-8],
mode="outer_product",
border_pixels="include")
image_observations = []
used_boxes = set()
for j in range(overlaps.shape[0]):
# check if box is already in existing observation
if j in used_boxes:
continue
box_overlaps = overlaps[j]
overlap_detections = np.nonzero(box_overlaps >= 0.95)
observation_set = set(overlap_detections)
for k in overlap_detections:
# check if box was already removed from observation, then skip
if k not in observation_set:
continue
# check if other found detections are also overlapping with this
# detection
second_overlaps = overlaps[k]
second_detections = set(np.nonzero(second_overlaps >= 0.95))
difference = observation_set - second_detections
observation_set = observation_set - difference
used_boxes.update(observation_set)
image_observations.append(observation_set)
for observation in image_observations:
observation_detections = detections_image[np.asarray(list(observation))]
# average over class probabilities
observation_mean = np.mean(observation_detections, axis=0)
observations[i].append(observation_mean)
return observations
def train(dataset: tf.data.Dataset, def train(dataset: tf.data.Dataset,
iteration: int, iteration: int,
use_dropout: bool, use_dropout: bool,