找回密码
 注册
关于网站域名变更的通知
查看: 721|回复: 3
打印 上一主题 下一主题

基于留一法的快速KNN代码

[复制链接]
  • TA的每日心情

    2019-11-19 15:32
  • 签到天数: 1 天

    [LV.1]初来乍到

    跳转到指定楼层
    1#
    发表于 2021-7-12 14:14 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

    EDA365欢迎您登录!

    您需要 登录 才可以下载或查看,没有帐号?注册

    x
    留一法交叉验证(LOOCV)- D7 K. W& F" F! l0 S
    留一法即Leave-One-Out Cross Validation。这种方法比较简单易懂,就是把一个大的数据集分为k个小数据集,其中k-1个作为训练集,剩下的一个作为测试集,然后选择下一个作为测试集,剩下的k-1个作为训练集,以此类推。其主要目的是为了防止过拟合,评估模型的泛化能力。计算时间较长。
    ) _1 Q5 T- J* L. ^! b2 h
    / v! f) V0 r4 K$ x4 E# n# V适用场景:
    3 F: ], k% v/ R* l6 k3 A; Q$ [
    & ]4 y5 u/ A6 U8 A8 X' {6 P数据集少,如果像正常一样划分训练集和验证集进行训练,那么可以用于训练的数据本来就少,还被划分出去一部分,这样可以用来训练的数据就更少了。loocv可以充分的利用数据。
    ) v0 W5 w/ `4 B( G  h3 y$ w8 A# \7 V) M# @# @5 W

    - j3 V8 E, z' V; g9 l! `+ I快速留一法KNN
    ( w$ |, ~$ s( y6 O+ F  y8 ]7 I# z0 \! |
    因为LOOCV需要划分N次,产生N批数据,所以在一轮训练中,要训练出N个模型,这样训练时间就大大增加。为了解决这样的问题,根据留一法的特性,我们可以提前计算出不同样本之间的距离(或者距离的中间值),存储起来。使用LOOCV时直接从索引中取出即可。下面的代码以特征选择为Demo,验证快速KNN留一法。
    7 q, ]5 h" i4 F' A" o1 W% {. Q  x8 ]  Q$ |1 p9 S/ L
    其中FSKNN1是普通KNN,FSKNN2是快速KNN
    1 _, A; |" m9 F: C3 t+ u0 D; E6 x3 e0 c9 y, y6 S
    主函数main.m& J) ], H! w) k8 T4 j$ A2 Z9 S
    - w8 B6 t- F- \4 Z' R4 R
    • clc
    • [train_F,train_L,test_F,test_L] = divide_dlbcl();
    • dim = size(train_F,2);
    • individual = rand(1,dim);
    • global choice
    • choice = 0.5;
    • global knnIndex
    • [knnIndex] = preKNN(individual,train_F);
    • for i = 1:100
    •     [error,fs] = FSKNN1(individual,train_F,train_L);
    •     [error2,fs2] = FSKNN2(individual,train_F,train_L);
    • end
      ( A9 l7 B# e  O- F
    + N9 i: K$ H; A/ U3 l& G' X
    4 n- C& h: g+ W0 }9 k; `1 Z6 x
    数据集划分divide_dlbcl.m
    1 K  d$ r: g7 Z. W- P8 Y$ |( C) q- P, k& H" ~
    • function [train_F,train_L,test_F,test_L] = divide_dlbcl()
    • load DLBCL.mat;
    • dataMat=ins;
    • len=size(dataMat,1);
    • %归一化
    • maxV = max(dataMat);
    • minV = min(dataMat);
    • range = maxV-minV;
    • newdataMat = (dataMat-repmat(minV,[len,1]))./(repmat(range,[len,1]));
    • Indices   =  crossvalind('Kfold', length(lab), 10);
    • site = find(Indices==1|Indices==2|Indices==3);
    • test_F = newdataMat(site,:);
    • test_L = lab(site);
    • site2 = find(Indices~=1&Indices~=2&Indices~=3);
    • train_F = newdataMat(site2,:);
    • train_L =lab(site2);
    • end
      : b( c! u5 ]- L5 {! z

    8 c& z+ J* K& x0 \% U- [& `
    ) L( Q6 E8 k/ }8 n; i" N1 g简单KNN# E( z% ~' {! _/ |& O" ~  h! u7 D
    * T- E. S6 F+ n: R6 l
    FSKNN1.m
    : l  f3 u3 u2 `6 A. V2 y9 v) E6 \# P
    • function [error,fs] = FSKNN1(x,train_F,train_L)
    • global choice
    • inmodel = x>choice;%%%%%设定恰当的阈值选择特征
    • k=1;
    • train_f=train_F(:,inmodel);
    • train_length = size(train_F,1);
    • flag = logical(ones(train_length,1));
    • error=0;
    • for j=1:train_length
    •     flag(j) = 0;
    •     CtrainF = train_f(flag,:);
    •     CtrainL = train_L(flag);
    •     CtestF = train_f(~flag,:);
    •     CtestL = train_L(~flag);
    •     classifyresult= KNN1(CtestF,CtrainF,CtrainL,k);
    •     if (CtestL~=classifyresult)
    •         error=error+1;
    •     end
    •     flag(j) = 1;
    • end
    •   error=error/train_length;
    •   fs = sum(inmodel);
    • end
      7 o# L& k9 r# m* M
    0 R9 j/ U1 C/ A: o6 r

    " {4 l6 ]& t1 C/ p/ M+ BKNN1.m
    & u. b3 u, J# c" y8 |2 q# D; m% F. G/ j/ E$ A
    • function relustLabel = KNN1(inx,data,labels,k)
    • %%
    • %   inx 为 输入测试数据,data为样本数据,labels为样本标签 k值自定1~3
    • %%
    • [datarow , datacol] = size(data);
    • diffMat = repmat(inx,[datarow,1]) - data ;
    • distanceMat = sqrt(sum(diffMat.^2,2));
    • [B , IX] = sort(distanceMat,'ascend');
    • len = min(k,length(B));
    • relustLabel = mode(labels(IX(1:len)));
    • end: M; Z' G# F, ]* O( g+ [4 R

    : F: `3 J& r) d# [: D" X* [" b4 b- J9 Q1 y+ v+ S9 A
    快速KNN
    3 }8 Q8 b$ O# {, ~, W0 G0 `* U9 R& K2 j3 k
    preKNN.m$ A& @2 N' }- M7 z
    / I7 b$ C, C+ V" E
    • function [knnIndex] = preKNN(x,train_F)
    •     inmodel = x > 0;
    •     train_f=train_F(:,inmodel);
    •     train_length = size(train_F,1);
    •     flag = logical(ones(train_length,1));
    •     knnIndex = cell(train_length,1);
    •     for j=1:train_length
    •         flag(j) = 0;
    •         CtrainF = train_f(flag,:);
    •         CtestF = train_f(~flag,:);
    •         [datarow , ~] = size(CtrainF);
    •         diffMat = repmat(CtestF,[datarow,1]) - CtrainF ;
    •         diffMat = diffMat.^2;
    •         knnIndex{j,1} = diffMat;
    •         flag(j) = 1;
    •     end
    • end
      + E% o) b7 J5 ~; g- i: b2 ?, V
    " B% U2 E! n) \. A" e

    " V- W; v, ]/ n1 d5 n9 o" QFSKNN2.m4 o/ x8 l; z7 I/ z9 A1 G( S& N

    3 _  t4 S8 V* o) H" @
    • function [error,fs] = FSKNN2(x,train_F,train_L)
    • global choice
    • inmodel = x>choice;%%%%%设定恰当的阈值选择特征
    • global knnIndex
    • k=1;
    • train_length = size(train_F,1);
    • flag = logical(ones(train_length,1));
    • error=0;
    • for j=1:train_length
    •     flag(j) = 0;
    •     CtrainL = train_L(flag);
    •     CtestL = train_L(~flag);
    •     classifyresult= KNN2(CtrainL,k,knnIndex{j}(:,inmodel));
    •     if(CtestL~=classifyresult)
    •         error=error+1;
    •     end
    •     flag(j) = 1;
    • end
    •   error=error/train_length;
    •   fs = sum(inmodel);
    • end  `+ o/ ~; j( l7 W/ P7 P
    ; @7 z$ ^/ z2 A) K  `$ p
    ; [# c( ^" O/ s  p& b3 m( k
    KNN2.m8 K- t" G6 x  |2 v3 q  E1 o2 ]

    2 c9 v* ]2 |6 C# F" ]* t
    • function relustLabel = KNN2(labels,k,diffMat)
    • distanceMat = sqrt(sum(diffMat,2));
    • [B , IX] = sort(distanceMat,'ascend');
    • len = min(k,length(B));
    • relustLabel = mode(labels(IX(1:len)));
    • end0 `  S* V1 F. F3 U' D  H8 J2 J

    ' S# Y8 I8 T* L; T# J/ Z+ b2 I+ i( W
    结果  L, p9 c* c& m0 L0 G. a
    ) x4 H* y( K  Y$ O6 u7 l, d

    0 I8 |' N2 Y% ^8 l3 V4 R" x1 I" A! m
    可以看到FSKNN2+preKNN的时间比FSKNN1要少很多。
    ( q* l* R* J& {$ I7 g3 |3 `8 q

    该用户从未签到

    2#
    发表于 2021-7-12 15:08 | 只看该作者
    基于留一法的快速KNN代码

    该用户从未签到

    3#
    发表于 2021-7-12 15:10 | 只看该作者
    基于留一法的快速KNN代码

    该用户从未签到

    4#
    发表于 2021-7-12 15:10 | 只看该作者
    基于留一法的快速KNN代码
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-8-12 12:32 , Processed in 0.125000 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表