总结:
假设原始样本中有两类,其中:
1:总共有 P个类别为1的样本,假设类别1为正例。
2:总共有N个类别为0 的样本,假设类别0为负例。
经过分类后:
3:有 TP个类别为1 的样本被系统正确判定为类别1,FN 个类别为1 的样本被系统误判定为类别 0,显然有P=TP+FN;
4:有 FP 个类别为0 的样本被系统误判断定为类别1,TN 个类别为0 的样本被系统正确判为类别 0,显然有N=FP+TN;
比如:trueY = [1,1,2,2,2,3]
predY = [2,1,1,3,2,1]
那么:
精确度(Precision):( 以predY的角度考虑,所有分类为1的值中正确的比重 1/(1+1+1)=0.33 )
P = TP/(TP+FP) ; 反映了被分类器判定的正例中真正的正例样本的比重(
准确率(Accuracy)
A = (TP + TN)/(P+N) = (TP + TN)/(TP + FN + FP + TN);
反映了分类器统对整个样本的判定能力——能将正的判定为正,负的判定为负
召回率(Recall),也称为查全率--True Positive Rate:( 以trueY的角度考虑,所有真实类别为1的值(位于trueY中的)被正确分类为1的比重 1/(1+1)=0.5 )
R = TP/(TP+FN) = 1 - FN/T; 反映了被正确判定的正例占总的正例的比重
转移性(Specificity,不知道这个翻译对不对,这个指标用的也不多),
也称为 True NegativeRate
S = TN/(TN + FP) = 1 – FP/N; 明显的这个和召回率是对应的指标,
只是用它在衡量类别0 的判定能力。
F-measure or balanced F-score
F = 2 * 召回率 * 准确率/ (召回率+准确率);这就是传统上通常说的F1 measure,
为什么会有这么多指标呢?
这是因为模式分类和机器学习的需要。判断一个分类器对所用样本的分类能力或者在不同的应用场合时,需要有不同的指标。
因此在统计信号分析中,有另外两个指标来衡量分类器错误判断的后果:
漏警概率(Missing Alarm)
MA = FN/(TP + FN) = 1 – TP/T = 1 - R; 反映有多少个正例被漏判了(我们这里就是真正的导弹信号被判断为模拟信号,可见MA此时为 33.33%,太高了)
虚警概率(False Alarm)
FA = FP / (TP + FP) = 1 – P;反映被判为正例样本中,有多少个是负例。
统计信号分析中,希望上述的两个错误概率尽量小。而对分类器的总的惩罚旧
是上面两种错误分别加上惩罚因子的和:COST = Cma *MA + Cfa * FA。
不同的场合、需要下,对不同的错误的惩罚也不一样的。像这里,我们自然希望对漏警的惩罚大,
因此它的惩罚因子 Cma 要大些。
个人观点:虽然上述指标之间可以互相转换,但在模式分类中,一般用 P、R、A 三个指标,不用MA和 FA。而且统计信号分析中,也很少看到用 R 的。
为什么先讲Precision和Recall呢?因为IR中很多算法的评估都用到Precision和Recall来评估好坏。所以我先讲什么是"好人",再告诉你他是"好人"
先看下面这张图来理解了,后面再具体分析。下面用P代表Precision,R代表Recall
通俗的讲,Precision 就是检索出来的条目中(比如网页)有多少是准确的,Recall就是所有准确的条目有多少被检索出来了。
下面这张图介绍True Positive,False Negative等常见的概念,P和R也往往和它们联系起来。
我们当然希望检索的结果P越高越好,R也越高越好,但事实上这两者在某些情况下是矛盾的。比如极端情况下,我们只搜出了一个结果,且是准确的,那么P就是100%,但是R就很低;而如果我们把所有结果都返回,那么必然R是100%,但是P很低。
因此在不同的场合中需要自己判断希望P比较高还是R比较高。如果是做实验研究,可以绘制Precision-Recall曲线来帮助分析(我应该会在以后介绍)
前面已经讲了,P和R指标有的时候是矛盾的,那么有没有办法综合考虑他们呢?我想方法肯定是有很多的,最常见的方法应该就是F Measure了,有些地方也叫做F Score,都是一样的。
F Measure是Precision和Recall加权调和平均:
F = (a^2+1)P*R / a^2P +R
当参数a=1时,就是最常见的F1了:
F1 = 2P*R / (P+R)
很容易理解,F1综合了P和R的结果
比如target=[2,2,2,3,2] pred=[2,2,1,3,4]
此时重叠的部分为pred[0]、pred[1]、pred[3],accuracy=3/5=0.6
而precision_score意思类似,但不完全一样,它是从pred的角度考虑,意思是我虽然预测了这么多个,但有几个预测对了?占比多少?这就是precision。
举例:
target=np.array([1,1,1,1,1])
pred=np.array([2,2,1,1,1])
p=precision_score(target,pred)
print(p)#1.0
的结果为1.0(看不懂?马上解释);
但如果是accuracy_score(target,pred),就会输出0.60(预测了5个,对了3个) 此外,
p=precision_score(target,pred)
其实等价于
p=precision_score(target,pred,average='binary',pos_label=1)
average='binary'表示pred当中(最多)只有两种标签(此处是1,2),pos_label=1表示最后输出的结果是针对类别值"1"的计算结果。
如果改成pos_label=2
p=precision_score(target,pred,average='binary',pos_label=2)
则表示计算结果是针对类别为"2"的统计结果,结果为0.0(因为pred中有两个2,但都预测错了,所以为0)。
pos_label这个参数只有average='binary'时管用,若pred中出现3种及以上类别的标签,则pos_label参数即使设置了也会被忽略。
而当average='macro'时,会计算每个种类标签的precision_score,再取平均(不考虑各个类别的样本分布差异)。例如:
target=np.array([1,1,2,3,3])
pred=np.array([2,2,1,3,4])
precision_score(target,pred,average='macro')
的结果为0.25,怎么算出来的0.25?
这样算:首先确定,pred中一共是4个类别(1,2,3,4),预测对的只有pred[3],
类别1的precision=0/1(pred中只有1个标签1,预测对了0个)结果为0
类别2的precision=0/2(pred中有2个标签2,预测对了0个),结果为0
类别3的precision=1/1(pred中有1个标签3,预测对了1个),结果为1
类别4的precision=0/1(pred中有1个标签4,预测对了0个),结果为0
再取平均(不考虑类别的分布差异):(0+0+1+0)/4=0.25。
Macro另外一个需要注意的地方在于,它在做平均的时候,它认为的类别数不是看target有多少个类别,也不是看pred有多少个类别,而是两者取并集,作为总的类别数。
例如,
target=np.array([1,1,3,3,4])
pred = np.array([1,1,2,0,0,])
print(precision_score(target,pred,average='macro'))#输出0.2
输出0.2,你敢信?并且报了一个警告:
D:\Anaconda3\lib\site-packages\sklearn\metrics\_classification.py:1221: UndefinedMetricWarning: Precision is ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.
_warn_prf(average, modifier, msg_start, len(result))
说那些没有被预测的类别的precision_score默认为0,
于是,就是类别1的预测precision_score=1,但一共有0,1,2,3,4,共5类别,而其余类别的precison均为0,所以1/5=0.2。
而当average='weighted'时,前面的步骤跟macro相同,分别计算pred中各个类别的precision_score,但汇总时则会考虑各个类别的样本的分布差异。例如,
target=np.array([1,1,2,2,3,3])
pred=np.array([2,2,1,3,4,3])
precision_score(target,pred,average='macro')
输出0.125
计算过程:pred中有4个类别,类别1、2、4预测正确的个数为0,precision_score均为0,而类别3,预测了2个(pred[3]、pred[5]),仅对了1个(pred[5]),precision_score=0.5,再取平均(0+0+0.5+0)/4=0.125,而
precision_score(target,pred,average='weighted')
则输出0.1666
因为average='weighted'时,会考虑各个类别(在target中,而非pred中)的分布比例,比如,类别1在target中出现占比为2/6,同理类别3的占比为2/6=1/3,
因此最后结果等于0*1/3+0*1/3+0.5*1/3+0*1/3=1/6=0.1666
举例:
target=np.array([1,2,2,2,3,3])
pred=np.array([2,2,1,3,4,3])
recall_score(target,pred,average='macro')
输出0.20833333333333331,其实就是5/24。怎么来的?
首先依据定义,pred的召回率是指pred中出现的各类标签,预测正确的次数占target中该类标签数的比例。
类别1的recall=0/1=0
类别2的recall=1/3(1个,即pred[1]预测正确,target中类别2出现了3次)
类别3的recall=1/2(1个,即pred[5]预测正确,target中类别3出现2次)
类别4的recall=0,类别4在target中没有出现,因此预测错误。
最后求平均:(1/3+1/2)/4=5/24=0.20833333333333334
同理,average='weighted'时,
recall_score(np.array([1,2,2,2,3,3]),np.array([2,2,1,3,4,3]),average='weighted')
输出0.333333=1/3
即分别用标签1、2、3、4的recall_score再乘上它们再target中的占比,0*1/6+1/3*3/6+1/2*2/6+0*0/6=1/3。