Использование чистой метрики в качестве метрики в Keras / TensorFlow - PullRequest
0 голосов
/ 29 августа 2018

Я работаю над конкурсом в Kaggle, где показатель оценки определяется как

Это соревнование оценивается по средней средней точности при различных порогах пересечения по объединению (IoU). IoU предложенного набора пикселей объекта и набора пикселей истинного объекта рассчитывается как:

              IoU(A,B)=(A∩B)/(A∪B)

Метрика охватывает диапазон порогов IoU, в каждой точке рассчитывается среднее значение точности. Пороговые значения находятся в диапазоне от 0,5 до 0,95 с размером шага 0,05: (0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95). Другими словами, при пороге 0,5 прогнозируемый объект считается «попаданием», если его пересечение по объединению с наземным истинным объектом превышает 0,5. При каждом пороговом значении t точность вычисляется на основе количества истинных положительных значений (TP), ложных отрицательных значений (FN) и ложных положительных результатов (FP), полученных в результате сравнения прогнозируемого объекта со всеми наземными истинными объектами:

                     TP(t)/TP(t)+FP(t)+FN(t).

Истинный положительный результат учитывается, когда один прогнозируемый объект соответствует наземному истинному объекту с IoU выше порогового значения. Ложный положительный результат означает, что предсказанный объект не имел связанного с ним объекта истинной земли. Ложный минус указывает на то, что у наземного объекта истины не было связанного предсказанного объекта. Средняя точность одиночного изображения затем рассчитывается как среднее из вышеуказанных значений точности при каждом пороге IoU:

           (1/|thresholds|)*∑tTP(t)/TP(t)+FP(t)+FN(t)

Теперь я написал эту функцию на чистом клочке, так как ее было гораздо проще кодировать, и я украсил ее tf.py_fucn(), чтобы использовать ее с Keras. Вот пример кода:

def iou_metric(y_true_in, y_pred_in, fix_zero=False):
    labels = y_true_in
    y_pred = y_pred_in

    true_objects = 2
    pred_objects = 2

    if fix_zero:
        if np.sum(y_true_in) == 0:
            return 1 if np.sum(y_pred_in) == 0 else 0

    intersection = np.histogram2d(labels.flatten(), y_pred.flatten(), bins=(true_objects, pred_objects))[0]

    # Compute areas (needed for finding the union between all objects)
    area_true = np.histogram(labels, bins = true_objects)[0]
    area_pred = np.histogram(y_pred, bins = pred_objects)[0]
    area_true = np.expand_dims(area_true, -1)
    area_pred = np.expand_dims(area_pred, 0)

    # Compute union
    union = area_true + area_pred - intersection

    # Exclude background from the analysis
    intersection = intersection[1:,1:]
    union = union[1:,1:]
    union[union == 0] = 1e-9

    # Compute the intersection over union
    iou = intersection / union

    # Precision helper function
    def precision_at(threshold, iou):
        matches = iou > threshold
        true_positives = np.sum(matches, axis=1) == 1   # Correct objects
        false_positives = np.sum(matches, axis=0) == 0  # Missed objects
        false_negatives = np.sum(matches, axis=1) == 0  # Extra objects
        tp, fp, fn = np.sum(true_positives), np.sum(false_positives), np.sum(false_negatives)
        return tp, fp, fn

    # Loop over IoU thresholds
    prec = []

    for t in np.arange(0.5, 1.0, 0.05):
        tp, fp, fn = precision_at(t, iou)
        if (tp + fp + fn) > 0:
            p = tp / (tp + fp + fn)
        else:
            p = 0
        prec.append(p)

    return np.mean(prec)

Я пытался преобразовать его в чистую функцию tf, но не смог этого сделать, так как не могу понять, как сработает control dependencies. Может ли кто-нибудь помочь мне с этим?

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

В вашем конкретном случае вы можете использовать реализацию tenorflow: tf.metrics.mean_iou.

0 голосов
/ 28 февраля 2019

Чтобы использовать вашу функцию, вам нужно конвертировать тензоры и массивы и наоборот. Чтобы преобразовать тензор в массив numpy, используйте tf.eval (см. здесь ):

np_array = tensor.eval()

Если вы хотите преобразовать объект python (также массив numpy) в тензор, вы можете использовать tf.convert_to_tensor (см. здесь ):

tensor = tf.convert_to_tensor(np.mean(prec),dtype=tf.float32)
...