一、混淆矩阵定义
混淆矩阵是机器学习中总结分类模型预测结果的情形分析表,以矩阵形式将数据集中的记录按照真实的类别与分类模型预测的类别判断两个标准进行汇总。其中矩阵的行表示真实值,矩阵的列表示预测值,下面我们先以二分类为例,看下矩阵表现形式,如下:
![461ac951ba2a481b9d32c21cb7267135.png](https://i-blog.csdnimg.cn/blog_migrate/9ea67ee05171ad073d2f51b8f9dafd11.png)
在讲矩阵之前,我们先复习下之前在讲分类评估指标中定义的一些符号含义,如下:
- TP(True Positive):将正类预测为正类数,真实为0,预测也为0
- FN(False Negative):将正类预测为负类数,真实为0,预测为1
- FP(False Positive):将负类预测为正类数, 真实为1,预测为0
- TN(True Negative):将负类预测为负类数,真实为1,预测也为1
刚才分析的是二分类问题,那么对于多分类问题,混淆矩阵表示的含义也基本相同,这里我们以三类问题为例,看看如何根据混淆矩阵计算各指标值。
![772d1718fb02570eadc6df870af49126.png](https://i-blog.csdnimg.cn/blog_migrate/6682da0f6543bf25b1ef6d2cefce4862.png)
与二分类混淆矩阵一样,矩阵行数据相加是真实值类别数,列数据相加是分类后的类别数,那么相应的就有以下计算公式;
- 精确率_类别1=a/(a+d+g)
- 召回率_类别1=a/(a+b+c)
二、python 绘画混淆矩阵
混淆矩阵(Confusion Matrix),是一种在深度学习中常用的辅助工具,可以让你直观地了解你的模型在哪一类样本里面表现得不是很好。
例:
![52c39e86aed81db3425d37606686f8e9.png](https://i-blog.csdnimg.cn/blog_migrate/4ff9fcb8217dc771f046c63e37d4485a.png)
代码如下:
import seaborn as sns
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
sns.set()
f,ax = plt.subplots()
y_true = [0,0,1,2,1,2,0,2,2,0,1,1]
y_pred = [1,0,1,2,1,0,0,2,2,0,1,1]
C2 = confusion_matrix(y_true,y_pred,labels=[0,1,2])
#打印 C2
print(C2)
sns.heatmap(C2,annot=True,ax=ax) #画热力图
ax.set_titile('confusion matrix') #标题
ax.set_xlabel('predict') #x 轴
ax.set_ylabel('true') #y 轴
三、F1 Score
精准率和召回率这两个指标有时精准率低一些有时召回率低一些,有时可能都低。那么实际中用哪个指标比较好呢?这一般和应用场景有关,对于有些场景,我们更注重精准率,比如股票预测,假设预测的是一个二分类问题:股票会升还是降,显然为了利润我们关注的是升(即上升为类1),为什么这种情况下精准率指标更好呢?因为精准率是所有分类为1的预测中有多少是正确的,对本例也就是预测未来股票上升有多少是对的,这更复合我们的利润最大决策。而召回率是实际上升的股票中我们预测对了多少,基于风险投资理念,有很多股票会上升的时刻,我们就算落掉一些也是没有关系的,没有投资进去也就没有损失,更重要的是我们的决策中有多少能赚钱,所以在这种场景下,精准率更好。
而如果在医疗领域,则是召回率更加重要,也就是要能在实际得病的人中尽量预测的更加准确,我们不想漏掉任何真正患病的人,这样才更有可能挽回一些人的生命,而精准率低些(没病的被预测为有病)并不会导致特别严重的后果,只是进行了一些过度医疗。
不过并非所有场景都如上面两个例子般极端,只关注精准率或只关注召回率。更多的我们希望得到它们之间的一种平衡,即同时关注精准率和召回率。这种情况下我们有一个新的指标:F1 Score,它的计算公式为:
![3defa112cc1de2cf5af6c2497eed1bf0.png](https://i-blog.csdnimg.cn/blog_migrate/0a87f6cd31ea3cd3619cd75bfd053355.png)
如果两个都为0,则定义F1=0。本质上F1是精准率和召回率的调和平均调和平均一个很重要的特性是如果两个数极度不平衡(一个很大一个很小),最终的的结果会很小,只有两个数都比较高时,调和平均才会比较高,这样便达到了平衡精准率和召回率的目的。
四、Precision-Recall的平衡
精准率和召回率是相互制约的,如果想要精准率提高,召回率则会下降,如果要召回率提高,精准率则会下降,我们需要找到二者之间的一个平衡。
P-R曲线的生成方法:根据学习器的预测结果对样本进行排序,排在前面的是学习器认为最可能是正例的样本,排在最后的是最不可能是正例的样本,按此顺序逐个将样本作为正例预测,则每次可以计算出当前的查全率、查准率,以查全率为横轴、查准率为纵轴做图,得到的查准率-查全率曲线即为P-R曲线。也就是说对每个样本预测其为正例的概率,然后将所有样本按预测的概率进行排序,然后依次将排序后的样本做为正例进行预测,从而得到每次预测的查全率与查准率。这个依次将样本做为正例的过程实际上就是逐步降低样本为正例的概率的域值,通过降低域值,更多的样本会被预测为正例,从而会提高查全率,相对的查准率可能降低,而随着后面负样本的增加,查全率提高缓慢甚至没有提升,精度降低会更快。
![3215771c8c0ed48bf30a8063f56ea3bc.png](https://i-blog.csdnimg.cn/blog_migrate/6c2a44887f29b3f5715e99ca54666d28.png)
代码实现如下:
import matplotlib
import numpy
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
from sklearn.utils.fixes import signature
plt.figure('P-R Curve')
plt.title('Precision/Recall Curve')
plt.xlabel('Recall')
plt.ylabel('Precision')
#y_true为样本实际的类别,y_scores为样本为正例的概率
y_true = np.array([1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0])
y_scores = np.array([0.9, 0.75, 0.86, 0.47, 0.55, 0.56, 0.74, 0.62, 0.5, 0.86, 0.8, 0.47, 0.44, 0.67, 0.43, 0.4, 0.52, 0.4, 0.35, 0.1])
precision, recall, thresholds = precision_recall_curve(y_true, y_scores)
plt.plot(recall,precision)
plt.show()
五、ROC 曲线 Receiver Operation Characeristic Curve
![f5fe36190621237ac42b42b2eff8d55f.png](https://i-blog.csdnimg.cn/blog_migrate/a3c1a2d99e575c87e5612d5db121c7e6.png)
该曲线的横坐标为假阳性率(False Positive Rate, FPR),N是真实负样本的个数,
FP是N个负样本中被分类器预测为正样本的个数。
纵坐标为真阳性率(True Positive Rate, TPR),
代码如下:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.meics import auc
y = np.array([1, 1, 2, 2])
scores = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)
metrics.auc(fpr, tpr)