Keras: Внутренняя реализация IoU, где входы - это углы коробки? - PullRequest
0 голосов
/ 15 января 2019

Я видел несколько реализаций Intersection over Union в Keras Tensorflow, но все они используют входные данные, которые представляют содержимое областей блоков. Сеть, с которой я работаю, передает четыре угла самих ящиков. Как я могу реализовать алгоритм таким образом с бэкэндом Keras?

Моя попытка:

 def IoU():
        # y_true: Tensor from the generator of shape (B, N, 5). The last value for each box is the state of the anchor (ignore, negative, positive).
        # y_pred: Tensor from the network of shape (B, N, 4).
        # box coordinates (in axis 2): [x1, y1, x2, y2]
     def _IoU(y_true, y_pred):
          anchor_state = y_true[:,:,-1]
          regression = y_pred
          regression_target = y_true[:,:,:-1]
          indices = backend.where(keras.backend.equal(anchor_state, 1))
          regression = backend.gather_nd(regression, indices)
          regression_target = backend.gather_nd(regression_target, indices)
          x1_pred = regression[:,0] # <- fails here 
          y1_pred = regression[:,1]
          x2_pred = regression[:,2]
          y2_pred = regression[:,3]
          x1_true = regression_target[:,0]
          y1_true = regression_target[:,1]
          x2_true = regression_target[:,2]
          y2_true = regression_target[:,3]
          xA = keras.backend.maximum(x1_pred, keras.backend.transpose(x1_true))
          yA = keras.backend.maximum(y1_pred, keras.backend.transpose(y1_true))
          xB = keras.backend.maximum(x2_pred, keras.backend.transpose(x2_true))
          yB = keras.backend.maximum(y2_pred, keras.backend.transpose(y2_true))
          interArea = keras.backend.maximum((xB-xA+1),0)*keras.backend.maximum((yB-yA+1),0)
          pred_area = (x2_pred-x1_pred+1)*(y2_pred-y1_pred+1)
          truth_area = (x2_true-x1_true+1)*(y2_true-y1_true+1)
          iou_arr = interArea/(pred_area + keras.backend.transpose(truth_area) - interArea)
          iou = keras.backend.mean(iou_arr)
          return iou
      return _IoU

После некоторой отладки я обнаружил, что backend.gather_nd уменьшил регрессию и regression_target с фигур (?,?, 4) до фигур (?, 4), отсюда и индексирование для x1_pred.

Однако, когда я пытаюсь использовать это как метрику для скомпилированной модели, я получаю следующую ошибку во время выполнения:

 ValueError: slice index 2 of dimension 1 out of bounds. for 'metrics/_IoU_1/strided_slice_4' (op: 'StridedSlice') with input shapes: [?,2], [2], [2], [2] and with computed input tensors: input[1] = <0 2>, input[2] = <0 3>, input[3] = <1 1>.

Если кто-нибудь знает, как я могу реализовать это в Керасе, или видит, где я ошибся, я был бы всегда благодарен.

РЕДАКТИРОВАТЬ: я понял, что это потому, что метод вызывался дважды, один раз, где (y_true, y_pred) были поле предсказание / истина (а последнее измерение было формы 4), а затем снова, где (y_true, y_pred) были классом предсказание / правда (а у меня только 2 класса).

Я получил некоторые отрицательные значения и некоторые значения> 1 для возвращенных значений iou, так что, возможно, я все еще что-то делаю неправильно?

...