统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图

要求:随机生成两组数据,每组50个数,其中一组服从正态分布,另一组服从N(1,1) 。编写一个code:

Input:上面产生的100个数,类别数:2

Output:1、0标签序列(每个标签对应每个数)

评估以上code输出结果的准确度。(准确度标准:查准率、查全率)

查准率:P=\frac{TP}{TP+FP}

查全率:R=\frac{TP}{TP+FN}

PR图理解错了,不是多个独立的样例,而是修改阈值,我一直用的是>=0.5判为1,即阈值设置的是0.5,应该修改这个阈值

另外老师会嫌弃只用查准率、查全率,建议画AUC曲线等(感觉被嫌弃了_(:з」∠)_)

数据生成:

X_1=normrnd(0,1,1,50);
y_1=ones(1,50);
X_2=normrnd(1,1,1,50);
y_2=zeros(1,50);
X_p=[X_1,X_2];
y_p=[y_1,y_2];
c=randperm(numel(X_p));                                                    %打乱顺序
X=X_p(c(1:numel(X_p)));                                                    %数据集
y=y_p(c(1:numel(X_p)));                                                    
X=X';
y=y';

一、十折交叉验证

统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图_第1张图片

function [p r]=cross(X,y,fold);
    indices=crossvalind('Kfold',100,fold);      %Indices = crossvalind('Kfold', N, K) K折交叉
    p=0;
    r=0;
    % cp=classperf(X);
    for i=1:fold
        test=(indices==i);
        train=~test;
        train_x=X(train,:);
        train_y=y(train,:);
        test_x=X(test,:);
        test_y=y(test,:);
        b=glmfit(train_x,train_y,'binomial','link','logit');%用逻辑回归来计算系数矩阵 
        logitFit=glmval(b,test_x,'logit');                  %用逻辑回归的结果预测测试集的结果
        logitFit=(logitFit>=0.5);                           %如果概率值不小于0.5,就认为是1,否则是0
        pp=0;
        rr=0;
        tpfp=length(find(logitFit==1));                     %预测出来的正例
        tpfn=length(find(test_y==1));                       %正例真正个数
        m=length(test_y);
        tp=0;
        for j=1:m
            if((test_y(j)==logitFit(j))&&(test_y(j)==1))
                tp=tp+1;                                    %预测出来的正确的正例个数
            end;
        end;
        if(tpfp)
             pp=tp/tpfp;                                    %一次验证得到的查准率
        end;
        if(tpfn)
             rr=tp/tpfn;                                    %一次验证得到的查全率
        end;
        p=p+pp;
        r=r+rr;  
    end
    p=p/fold;                                               %求平均值
    r=r/fold;

数据展示:

P=zeros(100,1);
R=zeros(100,1);
for k=1:100
    [P(k) R(k)]=cross(X,y,10);
end;
figure;
plot(P,R,'rx','MarkerSize',10);
title('100 times 10 fold cross valindation');
xlabel('查准率');
ylabel('查全率');

 

当然每次生成的数据集不一样,结果也很随机~

特例:当fold=N(样本数),就是留一法

[P R]=cross(X,y,100);   %为啥留一法出来的值那么低,

训练出来的结果查准率和查全率都在0.3左右

二、留出法

统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图_第2张图片

留出法实现参考博客

function [P R]=split(X,y,k,ratio)
m=size(X,1);
y_labels=unique(y);       %去重,只留下标记
train_x=[];
train_y=[];
d=[1:m]';
for i=1:k
    class_i=find(y==y_labels(i));
    if isempty(class_i)
        continue;
    end
    size_i=length(class_i);                             %打乱标记i
    rp=randperm(size_i);
    rp_ratio=rp(1:floor(size_i*ratio));                 %在标记i中取ratio作为训练集  以保证每个类别都取出一定的数量来训练
    indices=class_i(rp_ratio);                          %i类作为训练集的下标
    train_x=[train_x;X(indices,:)];
    train_y=[train_y;y(indices,:)];
    d=setdiff(d,indices);                               %训练集以外为测试集
end
        test_x=X(d,:);
        test_y=y(d,:);
        

P-R图

(注意P-R图绘制方法是错的,还没修改)

正确方法是将logitFit按照从大到小顺序排序,每次以一个logitFit作为正例和反例的界限,计算P值和R值

 for r=1:1:100
        tpfn=length(find(test_y==1));       %正例真正个数
        b=glmfit(train_x,train_y,'binomial','link','logit');%用逻辑回归来计算系数矩阵 
        logitFit=glmval(b,test_x,'logit');  %用逻辑回归的结果预测测试集的结果
        logitFit=(logitFit>=1.0*r/100);
%         P=0;
%         R=0;
        tpfp=length(find(logitFit==1));     %预测出来的正例
        
        m=length(test_y);
        tp=0;
%         plot(logitFit,test_y,'rx');
        for j=1:m
            if((test_y(j)==logitFit(j))&&(test_y(j)==1))
                tp=tp+1;
            end
        end
        if(tpfp)
             P(r)=tp/tpfp;
        end
        if(tpfn)
             R(r)=tp/tpfn;
        end
     end;
     plot(P,R);

 

统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图_第3张图片

阈值由0.01到1,步长0.01

三、自助法

统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图_第4张图片

function [P R]=bootstrap(X,y)
m=size(X,1);                           %得到样本个数
train_x=[];
train_y=[];
d=[1:m]';
for i=1:m
    indices=unidrnd(m);                 
    train_x=[train_x;X(indices,:)];
    train_y=[train_y;y(indices,:)];
    d=setdiff(d,indices);     
end
 test_x=X(d,:);
 test_y=y(d,:);

 

四、总结

讲道理小数据自助法应该比较好用,是不是我代码写崩了

 

 

你可能感兴趣的:(统计机器学习 作业一 采用交叉验证、留出法、自助法划分数据集,绘制PR图)