統計學習方法:KNN

做者:桂。html

時間:2017-04-19  21:20:09算法

連接:http://www.cnblogs.com/xingshansi/p/6736385.html ide

聲明:歡迎被轉載,不過記得註明出處哦~學習


前言測試

本文爲《統計學習方法》第三章:KNN(k-Nearest Neighbor),主要包括:idea

  1)KNN原理及代碼實現;spa

  2)K-d tree原理;.net

內容爲本身的學習記錄,其中多有借鑑他人的地方,最後一併給出連接。3d

 

1、KNN原理及代碼實現rest

KNN對應算法流程:

 其實就是在指定準則下,最近的K個決定了自身的類別。

  • LP距離

p=2時爲歐式距離(Euclidean distance),p=1爲曼哈頓距離(Manhattan distance),p=∞對應最大值。

  • K值選擇

K一般選較小的數值,且經過交叉驗證來尋優。

試着寫了三種距離下的KNN,給出主要代碼:

function resultLabel = knn(test,data,labels,k,flag)
%%
%   test:test database
%   data:train database
%   labels:train data labels
%   flag: distance criteria selection.
%     'E':Euclid Distance.
%     'M':Manhanttan distance.
%     'C':Cosine similarity.
%%
resultLabel=zeros(1,size(test,1));
dats.f=flag;
switch flag
    case 'C'
        Ifg='descend';
    otherwise
        Ifg='ascend';
end
for i=1:size(test,1)
    dats.tes=test(i,:);
    dats.tra=data;
    distanceMat =distmode(dats);
    [B , IX] = sort(distanceMat,Ifg);
    len = min(k,length(B));
    resultLabel(1,i) = mode(labels(IX(1:len)));
end
end

 dismode.m: 

function distanceMat =distmode(dats)
%distance calculation.
%%
% dats.tra:train database;
% dats.tes:test database;
% dats.f: distance flag;
%%
switch dats.f
    case 'E'%Euclidean distance
        p=2;
        datarow = size(dats.tra,1);
        diffMat = abs(repmat(dats.tes,[datarow,1]) - dats.tra) ;
        distanceMat=(sum(diffMat.^p,2)).^1/p;
    case 'M'%Manhanttan distance
        p=1;
        datarow = size(dats.tra,1);
        diffMat = abs(repmat(dats.tes,[datarow,1]) - dats.tra) ;
        distanceMat=(sum(diffMat.^p,2)).^1/p;
    case 'C'%Cosine similarity
        datarow = size(dats.tra,1);
        tesMat = repmat(dats.tes,[datarow,1]) ;
        diffup=sum(tesMat.*dats.tra,2);
        diffdown=sqrt(sum(tesMat.*tesMat,2)).*sqrt(sum(dats.tra.*dats.tra,2));
        distanceMat=diffup./diffdown;
end

  

2、K-d tree原理

KNN方法對於一個測試數據,須要與全部訓練樣本比對,再排序尋K個最優,如今換一個思路:若是在比對以前,就按某種規則排序(即構成一個二叉搜索樹),這樣一來,對於一個新的數據點,只要在先後尋K個最優便可,這樣就提升了搜索的效率。

給出構造平衡kd樹的算法:

以一個例子分析該思路,給定一個數據集:

對應思路:

步驟一:x(1)的中位數:7,對應數據{7,2};按小於/大於分左右;

步驟二:1mod2+1=2,對x(2)的中位數,對第二層進行劃分,左邊中位數爲5,右邊中位數爲9,依次劃分;

步驟三:2mod2+1=1,對x(1)的第三層進行劃分,結束,對應效果圖:

爲何KD樹能夠這麼構造?這也容易理解,對於一個數據點(x,y),距離公式爲,單單比較x是不夠的,若是對x按大小已經切分,下一步怎麼作?再按y進行切分,這樣距離大小就被細化,查找範圍進一步縮小,x切完y切,若是是三維,y切完z再切,對應數學表達就是。 

構造出了Kd tree以後,如何藉助它解決kNN問題呢?

給出搜索kd tree的算法:

 給出下圖,現有(2,5)這個點,但願找出最近的K=3 個點:

分析步驟:

步驟一:包含(2,5)的葉節點,發現落在(4,7)節點區域內,(4,7)爲當前最近點;

步驟二:檢查(4,7)對應父節點(5,4)的另外一個子節點(2,3),發現距離(2,5)更近,(2,5)記爲當前最近點;

步驟三:向上回退到(5,4),此時(5,4)時子節點,其父節點爲(7,2),依次類推。

具體以下圖所示:

爲何KD樹能夠這麼搜索?對應節點(右圖)能夠看出搜索按層回溯,對應左圖就是先上下搜索,再往右推動。這樣理解就比較直觀,由於距離是愈來愈大的。

完成尋最優之後,最簡單的辦法是刪除節點,重複尋最優,固然也能夠存儲不一樣結果,在少許樣本中挑出K個最優

 同理,對於三維數據,能夠依次類推:

給出Kd tree的測試代碼的效果圖,code對應連接點擊這裏

參考:

相關文章
相關標籤/搜索