我想计算2个numpy数组的敏感性和特异性(测试,真相)。两个数组都具有相同的形状,只存储数字0(test / truth false),1(test / truth true)。因此,我必须计算false_positives,true_positives,false_negative和true_negative值。我是这样做的:
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)
我认为可能存在一种更简单(更易读)的方式,因为它是python而不是C ++ ...首先我尝试了类似:true_positive = np.sum(mask == 255 and truth == 255)
但我得到了这个错误:
ValueError:具有多个元素的数组的真值是不明确的。使用a.any()或a.all()
有更多的pythonic方法来计算灵敏度和特异性吗?
谢谢!
答案 0 :(得分:4)
通过NumPy支持的ufunc-vectorized
操作,broadcasting
和array-slicing
专注于紧凑性,这是一种方法 -
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()
或者,稍微走一点 NumPythonic ,我们可以将C
计为np.bincount
-
C = np.bincount(((mask==255)*2 + (truth==255)).ravel())
为了确保我们将浮动的pt数字作为比率,一开始我们需要使用:from __future__ import division
。
答案 1 :(得分:2)
测试相同的形状:
NULL
测试真值:
a = np.random.rand(4,4)
b = np.random.rand(4,4)
print(a.shape == b.shape) #prints true
答案 2 :(得分:1)
可以像这样找到和组织四个数组:
categories=dstack((mask&truth>0,mask>truth,mask<truth,mask|truth==0))
然后得分:
tp,fp,fn,tn = categories.sum((0,1))
最后结果:
sensitivity,specificity = tp/(tp+fn),tn/(tf+fp)
答案 3 :(得分:0)
我的想法是使用标准库中的collections.Counter
。
# building pair list (can be shortened to one-liner list comprehension, if you want)
pair_list = []
for y in range(mask.shape[0]):
for x in range(mask.shape[1]):
pair_list.append((mask[y, x], truth[y, x]))
# getting Counter object
counter = collections.Counter(pair_list)
true_positive = counter.get((255, 255))
false_positive = counter.get((255, 0))
false_negative = counter.get((0, 255))
true_negative = counter.get((0, 0))