Spark自程式設計實現KNN演算法

2021-09-01 11:41:16 字數 3366 閱讀 5188

knn(k-nearest neighbors)又稱作k-近鄰。k-nn就是把未標記分類的案列歸為與它們最相似的帶有分類標記的案例所在的類。

優點缺點

簡單且有效

不產生模型

訓練階段很快

分類過程比較慢

對資料分布無要求

模型解釋性較差

適合稀疏時間和多分類問題

名義變數和缺失資料需要額外處理……

k近鄰模型有三個基本要素:距離度量、k值的選擇、分類決策規則

實現步驟

計算距離:計算待測案例與訓練樣本之間的距離 。

選擇乙個合適的k:確定用於knn演算法的鄰居數量,一般用交叉驗證或僅憑經驗選擇乙個合適的k值,待測案例與訓練樣本之間距離最小的k個樣本組成乙個案例池。

類別判定:根據案例池的資料採用投票法或者加權投票法等方法來決定待測案例所屬的類別。

kd-tree

kd-tree是一種分割k維資料空間的資料結構。主要應用於多維空間資料的搜尋,經常使用在sift、knn等多維資料搜尋的場景中,以knn(k近鄰)為例,使用線性搜尋的方式效率低下,k-d樹本質是對多維空間的劃分,其每個節點都為k維點的二叉樹kd-tree,因此可以大大提高搜尋效率。詳細的構造方法和kd樹的最近鄰搜尋方法可以參考李航老師的《統計學習方法》。

1.定義kd樹類及其方法

package ch3_knearestneibor

/** * created by wzzc on 2019/11/29

**//** *

* @param label 分類指標

* @param value 節點資料

* @param dim 當前切分維度

* @param left 左子節點

* @param right 右子節點

*/case class treenode(label: string,

value: seq[double],

dim: int,

var left: treenode,

var right: treenode)

extends serializable {}

object treenode

} /**

* 從root節點開始,dfs搜尋直到葉子節點,同時在stack中順序儲存已經訪問的節點。

* 如果搜尋到葉子節點,當前的葉子節點被設為最近鄰節點。

* 然後通過stack回溯:

* 如果當前點的距離比最近鄰點距離近,更新最近鄰節點.

* 然後檢查以最近距離為半徑的圓是否和父節點的超平面相交.

* 如果相交,則必須到父節點的另外一側,用同樣的dfs搜尋法,開始檢查最近鄰節點。

* 如果不相交,則繼續往上回溯,而父節點的另一側子節點都被淘汰,不再考慮的範圍中.

* 當搜尋回到root節點時,搜尋完成,得到最近鄰節點。

** @param treenode

* @param data

* @param k

* @return

*/def knn(treenode: treenode, data: seq[double], k: int = 1) =

if (math.abs(dimr) < resarr.last._1)

if (dimr > 0) finder(treenode.left) else finder(treenode.right)

}resarr.last._2

}finder(treenode)

resarr

}}

2.spark實現 knn模型
package ch3_knearestneibor

import org.apache.spark.ml.feature.vectorassembler

import org.apache.spark.ml.linalg.densevector

import org.apache.spark.ml.util.identifiable

import org.apache.spark.sql.dataframe

import org.apache.spark.sql.functions._

/** * created by wzzc on 2019/11/29

**/case class knnmodel(data: dataframe, labelname: string) extends serializable

private val kdtrees: array[treenode] = datatransform(data)

.withcolumn(ftsname, vec2seq(col(ftsname)))

.select(labelname, ftsname)

.withcolumn("partitionin", spark_partition_id())

.rdd //在大資料情況下,分割槽構建kdtree

.map(row => )

.groupby(_._1)

.mapvalues(_.toseq.map(tp3 => (tp3._2, tp3._3)))

.mapvalues(nn => treenode.creatkdtree(nn, 0, shapes))

.values

.collect()

/***

* @param predictdf

* @param k

* @return

*/def predict(predictdf: dataframe, k: int): dataframe =

/***

* @param predictdata

* @param k

* @return

*/def predict(predictdata: seq[double], k: int): string = )

.flatmap(_.toseq)

.sortby(_._1)

.take(k)

// 按照投票選舉的方法選擇分類結果

val cl = res

.map(tp3 => (tp3._3, 1))

.groupby(_._1)

.mapvalues(_.map(_._2).sum)

.maxby(_._2)

._1cl

} }

3.演算法測試
package ch3_knearestneibor

import org.apache.spark.sql.sparksession

/** * created by wzzc on 2019/11/29

**/object knnrunner

}

機器學習 KNN演算法原理 Spark實現

不懂演算法的資料開發者不是乙個好的演算法工程師,還記得研究生時候,導師講過的一些資料探勘演算法,頗有興趣,但是無奈工作後接觸少了,資料工程師的鄙視鏈,模型 實時 脫機數倉 etl工程師 bi工程師 不喜勿噴哈 現在做的工作主要是脫機數倉,當然前期也做過一些etl的工作,為了職業的長遠發展,拓寬自己的...

機器學習 KNN演算法原理 Spark實現

不懂演算法的資料開發者不是乙個好的演算法工程師,還記得研究生時候,導師講過的一些資料探勘演算法,頗有興趣,但是無奈工作後接觸少了,資料工程師的鄙視鏈,模型 實時 脫機數倉 etl工程師 bi工程師 不喜勿噴哈 現在做的工作主要是脫機數倉,當然前期也做過一些etl的工作,為了職業的長遠發展,拓寬自己的...

knn演算法實現

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