上一篇博客讲到基于贝叶斯算法的垃圾邮件分类Java实现,最后得到每一封测试邮件为垃圾邮件的概率probability数组,最后的分类步骤和指标评价任务留到了这篇博客进行讲解。因为联合概率法和贝叶斯法最后的正确率相仿,本文只对联合概率法的结果进行评价。
首先,我们需要明确我们所需要的评价指标:混淆矩阵、各种指标率、ROC曲线。对评价指标不了解的小伙伴先阅读这篇博客,非常好懂!https://blog.csdn.net/chocolate_chuqi/article/details/81162244
1 混淆矩阵
对于二分类问题,混淆矩阵由四个值构成:
public static int TP = 0;//实际为垃圾,预测也为垃圾
public static int FN = 0;//实际为垃圾,预测却为正常
public static int FP = 0;//实际为正常,预测却为垃圾
public static int TN = 0;//实际为正常,预测也为正常
显然,如果一个分类器的结果全部由TP和TN组成,那么这个分类器不谈性能可以说是“完美”分类器了。
在本项目中,我们已经得到的概率probability数组,还需要设定一个阈值才能得到混淆矩阵。
1.当我们设定阈值为0时,意味着只要probability大于等于0,则该邮件被判断为垃圾邮件。显然,所有的邮件都会被预测为垃圾邮件。由程序的输出可以看到,10000封测试邮件中,所有邮件都被预测成了垃圾邮件。其中6400封原本就为垃圾邮件(TP),3600封原本为正常邮件(FP)。
------------------阈值(0.00)-----------------
--------------------------------------------------
| | 实际类 |
| 数量 |---------------------------------|
| | 垃圾 | 正常 |
|----------------|---------------------------------|
|预测类|垃圾 | 6400 | 3600 |
| |正常 | 0 | 0 |
|----------------|---------------------------------|
2.当我们将阈值调整为0.5时,再看程序输出。TP = 6207,FP = 175,FN = 193,TN = 3425。对比阈值为0的情况,我们发现正确率已经很不错了,但是还是“错杀”了175封正常邮件,这在实际运用中是不能被允许的。那么该如何描述分类器存在的问题呢?除了正确率,下面将介绍其它几项指标。
------------------阈值(0.50)-----------------
--------------------------------------------------
| | 实际类 |
| 数量 |---------------------------------|
| | 垃圾 | 正常 |
|----------------|---------------------------------|
|预测类|垃圾 | 6207 | 175 |
| |正常 | 193 | 3425 |
|----------------|---------------------------------|
2 各种指标率
1.Accuracy(正确率) :我们最容易理解的指标,也是最直观的指标。
Accuracy = (TP+TN)/(TP+FP+TN+FN)
2.Precision(精确率):这个概率在本项目中就是衡量“错杀”很好的指标,如果Precision为1,则没有一封正常邮件被错杀。
Precision=TP/(TP+FP)
3.Specificity(特效率):这个概率在本项目中也可以作为衡量“错杀”的指标,如果Specificity为1,则没有一封正常邮件被错杀。
Specificity=TN/(TN+FP)
4.Recall(召回率)、Sensitivity(灵敏度):两者的公式一样,在本项目中可以作为衡量“漏杀”的指标,如果Recall(Sensitivity)为1,则没有一封垃圾邮件被漏杀。
Recall=Sensitivity=TP/(TP+FN)
/*被分对的样本数除以所有的样本数,通常来说,正确率越高,分类器越好*/ public static double accuracy = 0;//准确率Accuracy = (TP+TN)/(TP+FP+TN+FN) /*被分为正例的示例中实际为正例的比例*/ public static double precision = 0;//精确率precision=TP/(TP+FP) /*所有负例中被分对的比例,衡量了分类器对负例的识别能力*/ public static double specificity = 0;//特效率specificity=TN/N /*所有正例中被分对的比例,衡量了分类器对正例的识别能力*/ public static double recall = 0;//召回率recall=TP/(TP+FN) = 灵敏度(Sensitivity) /*F1-Score指标综合了Precision与Recall的产出的结果。 F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差。*/ public static double F1_Score = 0;//平衡F分数:准确率和召回率的调和平均数
在阈值等于0时,虽然正确率高于50%,但特效度=0,代表着该分类器一封正确的邮件都识别不出来,完全不起作用。
正确率(accuracy)= (TP+TN)/(P+N) = 0.64
特效度(specificity)= TN/N = 0.00
精度(precision)= TP/(TP+FP) = 0.64
召回率(recall)= 灵敏度(sensitive)= TP/(TP+FN) = 1.00
综合分类率(F1)= 2 * precision * recall / (precision + recall) = 0.78
在阈值等于0.5时,各项指标都大于等于95%,分类效果明显。
正确率(accuracy)= (TP+TN)/(P+N) = 0.96
特效度(specificity)= TN/N = 0.95
精度(precision)= TP/(TP+FP) = 0.97
召回率(recall)= 灵敏度(sensitive)= TP/(TP+FN) = 0.97
综合分类率(F1)= 2 * precision * recall / (precision + recall) = 0.97
3 概率分布图和ROC曲线
Java中并没有绘制概率分布图和ROC曲线现成的包,我通过JFreeChart绘制的折线图。
3.1 概率分布图
概率分布图描述的是测试样本的概率分布情况,即每一封测试邮件对应的概率分布情况。它的横坐标是概率值probability,纵坐标是这个概率值probability对应的样本(邮件)数量。
本项目中概率值probability表示我们预测的邮件为垃圾邮件的概率。那么,绘制出的概率分布图中,实际为垃圾邮件的样本应该更靠近直线x=1,而实际为正常邮件的样本应该更靠近直接x=0。
这是程序所绘制出的概率分布图,红线代表的是实际为垃圾邮件的分布情况,蓝线代表的是实际为正常邮件的分布情况。我们可以看到:
1.大部分样本是被完全分成了两个极端,证明分类器区分能力强。
2.概率值probability = 0.5上汇集了小部分样本,程序中设定了当垃圾邮件和正常邮件概率都趋于0时,手动设定probability = 0.5,因此可能是这类邮件所含分词一部分在正常邮件中,另一部分在垃圾邮件,导致分类器无法正确区分。
3.概率值probability = 0上汇集了小部分垃圾邮件样本,可能这类邮件所含垃圾分词还未被训练到。
4.概率值probability = 1上汇集了小部分正常邮件样本,这部分原因尚未发现,但却是程序的大问题,它代表着“错杀”正确邮件。
-----------------------------概率分布曲线------------------------------
概率分布坐标点:
正例坐标:
(0.00, 162)(0.01, 1)(0.02, 1)(0.05, 1)(0.08, 14)(0.14, 2)(0.31, 2)(0.34, 5)(0.46, 4)(0.47, 1)(0.50, 122)(0.55, 1)(0.64, 1)(0.65, 1)(0.66, 3)(0.71, 2)(0.77, 19)(0.84, 1)(0.87, 1)(0.91, 2)(0.93, 5)(0.94, 1)(0.97, 38)(0.98, 5)(0.99, 1)(1.00, 6004)
负例坐标:
(0.00, 3412)(0.01, 3)(0.02, 2)(0.03, 2)(0.04, 1)(0.08, 1)(0.13, 1)(0.18, 1)(0.25, 1)(0.41, 1)(0.50, 35)(0.67, 1)(0.92, 1)(0.97, 1)(0.98, 1)(0.99, 2)(1.00, 134)
3.2 ROC曲线
对ROC曲线不了解的同学可以先看这篇博客:https://blog.csdn.net/liweibin1994/article/details/79462554
ROC曲线的横纵坐标为两个指标FPR、TPR。计算公式:
//得到ROC曲线坐标值 TPR = (double) TP / (double) (TP + FN); FPR = (double) FP / (double)(FP + TN);
每一组坐标值都需要由混淆矩阵得到,而每一个混淆矩阵都对应着一个阈值。因此,为了得到多组ROC坐标,我们需要调整多个阈值。而ROC曲线需要经过(0,0)、(1,1)点,它们对应着阈值为0和1的情况。因此,我们就设定初始阈值为-0.05,阈值增值为0.05,阈值最大值为1.05,这样就能多组ROC坐标,同时保证ROC曲线过(0,0)、(1,1)这两点。
根据概率分布图,我们发现其实样本概率基本分布在两点,导致我们的阈值设定在0.05-0.95之间时,对应的混淆矩阵变化不大,所以即使我们设定了20多个不同阈值,但得到的ROC坐标却大部分相同,且处于同一块小区域。
-----------------------------ROC曲线------------------------------
ROC曲线坐标点:
(1.00, 1.00)(1.00, 1.00)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.05, 0.97)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.04, 0.95)(0.02, 0.87)(0.00, 0.00)
后续
1.优化了判定条件,解决了概率分布图x=0.5样本聚集情况。
2.至于x=0和x=1处的样本聚集,在于训练样本不足,导致概率差距过大,很容易导致垃圾邮件(rate)和正常邮件(tempRate)概率产生一个10倍以上的差距,导致弱势一方的比重微不足道。
3.对比了联合概率法和贝叶斯法60000封邮件下的预测结果,发现阈值0.5时,贝叶斯法小优于联合概率法。
贝叶斯法
------------------阈值(0.50)-----------------
--------------------------------------------------
| | 实际类 |
| 数量 |---------------------------------|
| | 垃圾 | 正常 |
|----------------|---------------------------------|
|预测类|垃圾 | 6217 | 147 |
| |正常 | 183 | 3453 |
|----------------|---------------------------------|正确率(accuracy)= (TP+TN)/(P+N) = 0.97
特效度(specificity)= TN/N = 0.96
精度(precision)= TP/(TP+FP) = 0.98
召回率(recall)= 灵敏度(sensitive)= TP/(TP+FN) = 0.97
综合分类率(F1)= 2 * precision * recall / (precision + recall) = 0.97
联合概率法
------------------阈值(0.50)-----------------
--------------------------------------------------
| | 实际类 |
| 数量 |---------------------------------|
| | 垃圾 | 正常 |
|----------------|---------------------------------|
|预测类|垃圾 | 6207 | 147 |
| |正常 | 193 | 3453 |
|----------------|---------------------------------|正确率(accuracy)= (TP+TN)/(P+N) = 0.97
特效度(specificity)= TN/N = 0.96
精度(precision)= TP/(TP+FP) = 0.98
召回率(recall)= 灵敏度(sensitive)= TP/(TP+FN) = 0.97
综合分类率(F1)= 2 * precision * recall / (precision + recall) = 0.97