编程题目
接收操作特征(Receiver Operating Characteristic ,ROC )曲线,即通常所讲的ROC Curve ,是机器学习领域中常用的分类性能评估曲线,横轴是False Positive Rate ,纵轴是True Positive Rate 。请用Matlab 编写一个自动画出ROC 曲线的函数,并给出测试例子。
实验过程和解答
[1] 原理分析
对于经典的二分类(0、1)问题来说,分类器分类之后,往往会得到对每个样本是哪一类的一个估计predict,像是LR模型就会将这个估计规范化到【0、1】。根据这个估计,你选择一个阈值p_i,就可以将分类结果映射到0、1了;分类效果好不好跟真实的对应的ground_truth中的标签比比就行了。所以你手里有predict和ground_truth两个向量,用来做分类结果的评估,这两个向量便是函数的两个输入参数。
为了更好的衡量ROC 所表达结果的好坏,Area Under Curve (AUC )被提了出来,简单来说就是曲线右下角部分占正方形格子的面积比例。那么计算这个东西其实就很简单了,在这里我用到了matlab 中自带的一个函数trapz ,它可以计算出这个面积。通常来说,曲线越靠近图像的左上角,也就是曲线的下方面积越大,表示模型的性能越好。
[2] 程序代码
其实画ROC 曲线函数的代码编写方法不止一种。老师注释里提供的方法是一种很简洁高效的方法。只需要不断遍历排序后的predict 向量,引入x_step 和y_step ,循环判断排序后predict[i] 对应的ground_truth[i] 的值,然后让x 轴或者y 轴减小x_step 或y_step 。这样,便不必每次去统计TP 和FP 的值然后再计算每个点的坐标了。最后代码如下:
function auc = plot_roc( predict, ground_truth ) % INPUTS % predict - 分类器对测试集的分类结果 % ground_truth - 测试集的正确标签,这里只考虑二分类,即0和1 % OUTPUTS % auc - 返回ROC曲线的曲线下的面积 %初始点为(1.0, 1.0) x = 1.0; y = 1.0; %计算出ground_truth中正样本的数目pos_num和负样本的数目neg_num pos_num = sum(ground_truth==1); neg_num = sum(ground_truth==0); %根据该数目可以计算出沿x轴或者y轴的步长 x_step = 1.0/neg_num; y_step = 1.0/pos_num; %首先对predict中的分类器输出值按照从小到大排列 [predict,index] = sort(predict); ground_truth = ground_truth(index); %对predict中的每个样本分别判断他们是FP或者是TP %遍历ground_truth的元素, %若ground_truth[i]=1,则TP减少了1,往y轴方向下降y_step %若ground_truth[i]=0,则FP减少了1,往x轴方向下降x_step for i=1:length(ground_truth) if ground_truth(i) == 1 y = y - y_step; else x = x - x_step; end X(i)=x; Y(i)=y; end %画出图像 plot(X,Y,'-ro','LineWidth',2,'MarkerSize',3); xlabel('虚报概率'); ylabel('击中概率'); title('ROC曲线图'); %计算小矩形的面积,返回auc auc = -trapz(X,Y); end
由于缺少具体测试数据,在这里我们简单用【0,1 】之间的101 个点作为predict 向量值,用101 维随机0-1 值向量作为ground_truth 。测试代码如下:
clear all; predict=(0:1/100:1); %生成间隔为0.01的预测阈值 ground_truth=randi([0,1],1,101);%生成0-1随机向量 result=plot_roc(predict,ground_truth); disp(result);
[3] 实验效果
由最后的ROC 曲线图效果如下。