I am using PyTorch’s AUCMeter
to calculate the AUC value. In the instances when target is all 0’s, tpr
is coming to be NaN
, as its formula is: tpr /= (self.targets.sum() * 1.0)
. While fpr
comes to NaN
when all targets are 1 as its formula is fpr /= ((self.targets - 1.0).sum() * -1.0)
. How to calculate tpr
and fpr
in such instances and avoid NaN
? Below is the complete code of AUCMeter
def __init__(self):
super(AUCMeter, self).__init__()
self.reset()
def reset(self):
self.scores = torch.DoubleTensor(torch.DoubleStorage()).numpy()
self.targets = torch.LongTensor(torch.LongStorage()).numpy()
def add(self, output, target):
if torch.is_tensor(output):
output = output.cpu().squeeze().numpy()
if torch.is_tensor(target):
target = target.cpu().squeeze().numpy()
elif isinstance(target, numbers.Number):
target = np.asarray([target])
assert np.ndim(output) == 1, \
'wrong output size (1D expected)'
assert np.ndim(target) == 1, \
'wrong target size (1D expected)'
assert output.shape[0] == target.shape[0], \
'number of outputs and targets does not match'
assert np.all(np.add(np.equal(target, 1), np.equal(target, 0))), \
'targets should be binary (0, 1)'
self.scores = np.append(self.scores, output)
self.targets = np.append(self.targets, target)
print("scores", self.scores)
print("targets", self.targets )
def value(self):
# case when number of elements added are 0
if self.scores.shape[0] == 0:
return (0.5, 0.0, 0.0)
# sorting the arrays
scores, sortind = torch.sort(torch.from_numpy(
self.scores), dim=0, descending=True)
scores = scores.numpy()
sortind = sortind.numpy()
# creating the roc curve
tpr = np.zeros(shape=(scores.size + 1), dtype=np.float64)
fpr = np.zeros(shape=(scores.size + 1), dtype=np.float64)
for i in range(1, scores.size + 1):
if self.targets[sortind[i - 1]] == 1:
tpr[i] = tpr[i - 1] + 1
fpr[i] = fpr[i - 1]
else:
tpr[i] = tpr[i - 1]
fpr[i] = fpr[i - 1] + 1
tpr /= (self.targets.sum() * 1.0)
fpr /= ((self.targets - 1.0).sum() * -1.0)
print('tpr', tpr )
print("fpr", fpr)
# calculating area under curve using trapezoidal rule
n = tpr.shape[0]
h = fpr[1:n] - fpr[0:n - 1]
sum_h = np.zeros(fpr.shape)
sum_h[0:n - 1] = h
sum_h[1:n] += h
area = (sum_h * tpr).sum() / 2.0
print('area')
return (area, tpr, fpr)