Pythonic计算灵敏度和特异性的方法

时间:2017-01-30 14:42:21

标签: python numpy

我想计算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方法来计算灵敏度和特异性吗?

谢谢!

4 个答案:

答案 0 :(得分:4)

通过NumPy支持的ufunc-vectorized操作,broadcastingarray-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))