I want to compute the sensitivity and specificity of 2 numpy arrays (test, truth). Both arrays have the same shapes and store only the numbers 0 (test/truth false), 1 (test/truth true). Therefore I had to compute the false_positives, true_positives, false_negative and true_negative values. I did it this way:
true_positive = 0
false_positive = 0
false_negative = 0
true_negative = 0
for y in range(mask.shape[0]):
for x in range(mask.shape[1]):
if (mask[y,x] == 255 and truth[y,x] == 255):
true_positive = true_positive + 1
elif (mask[y,x] == 255 and truth[y,x] == 0):
false_positive = false_positive + 1
elif (mask[y,x] == 0 and truth[y,x] == 255):
false_negative = false_negative + 1
elif (mask[y,x] == 0 and truth[y,x] == 0):
true_negative = true_negative + 1
sensitivity = true_positive / (true_positive + false_negative)
specificity = true_negative / (false_positive + true_negative)
I think there could exist a much easier (more readable) way because it's python and not C++ ... First I tried something like: true_positive = np.sum(mask == 255 and truth == 255) but I got this error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Is there a more pythonic way to compute the sensitivity and specificity?
Thanks!
Focusing on compactness through NumPy supported ufunc-vectorized operations, broadcasting and array-slicing, here's an approach -
C = (((mask==255)*2 + (truth==255)).reshape(-1,1) == range(4)).sum(0)
sensitivity, specificity = C[3]/C[1::2].sum(), C[0]/C[::2].sum()
Alternatively, going a bit NumPythonic, we could have counts C with np.bincount -
C = np.bincount(((mask==255)*2 + (truth==255)).ravel())
To make sure we are getting floating pt numbers as the ratios, at the start, we need to use : from __future__ import division.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With