KNN演算法的CUDA實現

2021-06-25 12:09:24 字數 2228 閱讀 9192

在參考了《fast k nearest neighbor search using gpu》後,結合現在在做的課題,寫點東西。

knn演算法的基礎是對給定的query點集,對應查詢在參考空間中距離最近的k個緊鄰點。knn的應用方面非常廣泛,在icp配準問題,spin-image旋轉影象配準法,sift點提取,資料探勘,機器學習等多個方面中有廣泛應用。

knn演算法存在的乙個重要問題是,繁重的計算量。如果參考空間由m個點,query點集有n個點,空間維度維d維,那麼計算query點集與參考空間各個點集的距離就有o(mnd)的時間複雜度。同時,對於每乙個query點計算出的m個距離進行排序,至少要有o(m*logm)的時間複雜度,僅僅排序就要有o(mn*logm)的時間複雜度。因此,整個knn問題的時間複雜度為o(mnd)+o(mnlogm)。這裡為了方便,輸入參考空間與query點集都是n個點。

雖然針對於knn演算法有各種各樣的優化方式,但是這裡討論的重點是cuda對knn問題的優化,因此採用最基礎(也是最暴力的)brute force演算法——窮舉法。

雖然快排演算法的效率很高,但是在cuda中無法採用遞迴的方法,因此這裡採用了插值方法,雖然梳排序(comb sort)的時間複雜度o(nlogn)要小於插值法o(n^2),但是在後面的分析中可以看到,針對於gpu環境下插值法可以取得更好的效果。

在cuda中記憶體按照如下格式安排。

其中gpu可以被分為多個塊,並自帶有register和shared memory,每個塊可以直接訪問constant與texture,從訪問速度上講,有registers --> shared memory --> constant memory --> ram。

這裡吧query sets安排在texture memory中,把參考空間點放在global 中。

當給定n = 4800時,隨著需要緊鄰點個數的增加,comb 排序演算法保持不變,但是插值法的計算時間不斷增加。但是可以注意到,當所取k點比較少時,插值法明顯優於comb法,因此這裡存在乙個comb法與插值法相交的k0點。

下面給出測試點數與k0值的近似關係。

當測試點集與k值落在斜線右下方時,採用插值法要更優,反之亦然。針對於本問題,採用插值法更適合於knn演算法在cuda上的應用。

採用了四種對比方法:

一種比較直觀的解釋是,當採用38400個點,96個維度的空間進行測試時,

bf-matlab用了57分鐘,bf-c用了44分鐘,ann-c++用了22分鐘,bf-cuda用了不到10s。。。

更有意思的是,當空間的維度不斷提高時,其他演算法的計算耗時也在不斷提高,但是bf-cuda的耗時沒有變化(在前面的乘法計算中也採用了並行處理的方式,因此儘管空間維度增加但是依然不會影響它的計算)。

當採用4800點,32維空間,k取20時,cpu與gpu的時間利用對比。

cpu的主要耗時就是在o(nmd)的距離計算上,排序只用了很少時間,gpu雖然在排序上耗時比例大,但是整體應用時間很小,這得益於其並行處理的框架。

knn演算法實現

knn演算法 自己實現 鳶尾花資料集 一.題目描述 題目 自己實現knn演算法 用鳶尾花資料集 knn演算法描述 在訓練集中資料和標籤已知的情況下,輸入測試資料,將測試資料的特徵與訓練集中對應的特徵進行相互比較,找到訓練集中與之最為相似的前k個資料,則該測試資料對應的類別就是k個資料 現次數最多的那...

KNN演算法實現

knn k 近鄰 knn,k nearestneighbor 演算法是一種基本分類與回歸方法,我們這裡只討論分類問題中的 k 近鄰演算法。k 近鄰演算法的輸入為例項的特徵向量,對應於特徵空間的點 輸出為例項的類別,可以取多類。k 鄰演算法假設給定乙個訓練資料集,其中的例項類別已定。分類時,對新的例項...

Python實現KNN演算法

from numpy import import operator def creatdataset group array 1.0,1.1 1.0,1.0 0,0 0,0.1 lables a a b b return group,lables def classify0 inx,dataset,...