做者:桂。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個決定了自身的類別。
p=2時爲歐式距離(Euclidean distance),p=1爲曼哈頓距離(Manhattan distance),p=∞對應最大值。
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對應連接點擊這裏:
參考: