Я работаю над конкурсом в 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
. Может ли кто-нибудь помочь мне с этим?