# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import unittest import numpy as np from op_test import OpTest import paddle.fluid as fluid def compute_mean_iou(predictions, labels, num_classes, in_wrongs, in_corrects, in_mean_ious): assert predictions.shape == labels.shape predictions = predictions.flatten() labels = labels.flatten() out_wrong = np.zeros([num_classes]).astype("int32") for _, wrong in in_wrongs: out_wrong += wrong out_correct = np.zeros([num_classes]).astype("int32") for _, correct in in_corrects: out_correct += correct for pred, label in zip(predictions, labels): if pred == label: out_correct[pred] += 1 else: out_wrong[pred] += 1 out_wrong[label] += 1 denominator = out_wrong + out_correct valid_count = (denominator != 0).sum() denominator = np.where(denominator > 0, denominator, np.ones(denominator.shape)) mean_iou = (out_correct / denominator).sum() / valid_count for _, in_mean_iou in in_mean_ious: mean_iou += in_mean_iou return mean_iou, out_wrong, out_correct class TestMeanIOUOp(OpTest): def setUp(self): self.config() self.op_type = "mean_iou" predictions = np.random.randint(0, self.num_classes, self.image_size).astype("int32") labels = np.random.randint(0, self.num_classes, self.image_size).astype("int32") in_wrongs = [] for i in range(self.in_wrong_num): in_wrongs.append( ("in_wrong_%d" % i, np.random.randint(0, 10, [self.num_classes]).astype("int32"))) in_corrects = [] for i in range(self.in_correct_num): in_corrects.append( ("in_correct_%d" % i, np.random.randint(0, 10, [self.num_classes]).astype("int32"))) in_mean_ious = [] for i in range(self.in_mean_iou_num): in_mean_ious.append(("in_mean_iou_%d" % i, np.random.uniform(0, 1, [1]).astype("float32"))) self.inputs = { 'Predictions': predictions, 'Labels': labels, 'InWrongs': in_wrongs, 'InCorrects': in_corrects, 'InMeanIou': in_mean_ious } self.attrs = {'num_classes': int(self.num_classes)} mean_iou, out_wrong, out_correct = compute_mean_iou( predictions, labels, self.num_classes, in_wrongs, in_corrects, in_mean_ious) self.outputs = { 'OutMeanIou': mean_iou, 'OutWrong': out_wrong, 'OutCorrect': out_correct } def config(self): self.num_classes = 10 self.image_size = [128, 128] self.in_wrong_num = 0 self.in_correct_num = 0 self.in_mean_iou_num = 0 def test_check_output(self): self.check_output() class TestCase1(TestMeanIOUOp): def config(self): self.num_classes = 5 self.image_size = [100, 128] self.in_wrong_num = 2 self.in_correct_num = 2 self.in_mean_iou_num = 2 # NOTE(dev): Skip check_dygraph becuase Python API doesn't expose # in_wrong_num/in_correct_num/in_mean_iou_num argument def test_check_output(self): self.check_output(check_dygraph=False, check_eager=False) class TestMeanIOUOpError(unittest.TestCase): def test_errors(self): with fluid.program_guard(fluid.Program(), fluid.Program()): # The input type of accuracy_op must be Variable. x1 = fluid.create_lod_tensor(np.array([[-1]]), [[1]], fluid.CPUPlace()) y1 = fluid.create_lod_tensor(np.array([[-1]]), [[1]], fluid.CPUPlace()) self.assertRaises(TypeError, fluid.layers.mean_iou, x1, y1) # The input dtype of accuracy_op must be float32 or float64. x2 = fluid.layers.data(name='x2', shape=[4], dtype="float32") y2 = fluid.layers.data(name='x2', shape=[4], dtype="float32") self.assertRaises(TypeError, fluid.layers.mean_iou, x2, y2) if __name__ == '__main__': unittest.main()