本文是一篇介紹K近鄰數據挖掘算法的文章,而所謂數據挖掘,就是討論如何在數據中尋找模式的一門學科。算法
其實人類的科學技術發展的歷史,就一直伴隨着數據挖掘,人們一直在試圖中數據中尋找模式,數據庫
所謂數據挖掘,本質上就是經過分析存在於數據庫裏的數據來解決問題,數據挖掘被定義爲找出數據中的模式的過程,這個過程必須是自動的或半自動的。數據結構
接下來的問題就是,如何表示數據模式?app
有價值的數據模式可以讓咱們對新數據作出非凡的預測,表示一個數據模式有兩種極端的方法:機器學習
兩種方法可能均可以作出好的預測,它們的區別在於被挖掘出的模式可否以結構的形式清晰地表現,這個結構是否經得起分析,理由是否充分,可否用來造成將來的決策。ide
若是模式可以以顯而易見的方法得到決策結構,就稱爲結構模式(structural pattern),換句話說,結構模式可以幫助解釋有關數據的一些現象,具有可解釋性。函數
更進一步地,機器學習從數據中挖掘結構模式的過程,稱爲知識表達,機器學習所能發現的模式有許多不一樣的表達方式,每一種方式就是一種推斷數據輸出結構的技術,包括:工具
瞭解了前因後果的知識脈絡以外,咱們將視野縮小到」基於實例的機器學習「這個領域內。學習
在基於實例的學習中,訓練樣本被一字不差地保存,而且使用一個距離函數來斷定訓練集中的哪一個實例與一個未知的測試實例最靠近。一旦找到最靠近的訓練實例,那麼最靠近實例所屬的類就被預測爲測試實例的類。測試
基於實例的算法,有時也稱爲基於記憶的學習,它不是明確概括機率分佈或者分界面,而是將新的問題例子與訓練過程當中見過的例子進行對比,這些見過的例子就在存儲器中。
Relevant Link:
《數據挖掘 實用機器學習工具與技術》Ian H.Witten Eibe Frank,Mark A.Hall
咱們先來看下面這張圖,
假設咱們如今的目標是尋找圖中離綠色點最近的實例。這個問題的答案彷佛是顯而易見的,很顯然是右下方向的紅色三角。
可是咱們只要對題目稍加改造,例如將空間維數從2維擴展到100維,圖上的點密度增長10倍,這個時候,答案還依然明顯嗎?顯然不是了!
最直觀的想法是,咱們須要建一張表(table),將圖中全部的數據點的座標都保存起來,例如:
點 | x1 | ...... | xn |
A | 1 | ...... | 2 |
.. | |||
N | 5 | ...... | 3 |
這樣,每輸入一個新的點時,咱們就遍歷一遍整張表,根據必定的距離函數(例如歐氏距離)找出距離最近的1個或k個實例。
這個場景在現實中是很是常見的需求,例如:
儘管上面描述的查表法很是簡單且有效,可是缺點是速度很是慢。這個過程與訓練實例的數量成線性關係,換句話說,就是一個單獨的預測所花費的時間與訓練實例的數量成比例關係。處理整個數據集所花費的時間與訓練集實例數量O(train)和測試集實例數量O(test)的乘積成正比。
如何解決這個關鍵矛盾呢?學者們從數據結構優化上入手,提出了一系列的高效數據結構與搜索算法,它們合稱爲K近鄰算法,K近鄰算法要解決的最核心問題就是如何有效尋找到最近鄰的實例集,支撐這種搜索的結構就是一種知識表達。咱們接下來來討論它。
K近鄰法(k-nearest neighbor KNN)是一種數據驅動(基於實例的算法(Instance-based Algorithms))的分類與迴歸方法。它屬於一種判別模型。
在多分類問題中的k近鄰法,k近鄰法的輸入爲實例的特徵向量,對應於特徵空間的點,輸出爲實例的類別。
k近鄰法假設給定一個訓練數據集,其中的實例類別已定,分類時,對新的實例,根據其k個最近鄰的訓練實例的類別,經過多數表決等方式進行預測。所以,k近鄰法不具備顯示的學習過程(或者說是一種延遲學習),k近鄰法實際上利用訓練數據集對特徵向量空間進行劃分,並做爲其分類的「模型」。
KNN算法不只能夠用於分類,還能夠用於迴歸。經過找出一個樣本的k個最近鄰居,將這些鄰居的屬性的平均值賦給該樣本,就能夠獲得該樣本的屬性。
更有用的方法是將不一樣距離的鄰居對該樣本產生的影響給予不一樣的權值(weight),如權值與距離成正比。
輸入訓練數據集,其中
爲實例的特徵向量,
爲實例的類別。
根據給定的距離度量,在訓練集中找出與 x 最鄰近的 K(須要人工設定調參) 個點,在由這 K 個點組成的鄰域中根據分類決策規則決定 x 的類別 y
K近鄰法的特殊狀況是k=1的情形,稱爲最近鄰算法,即對於輸入的實例點(特徵向量)x,最近鄰法將訓練數據集中與x最鄰近的類做爲x的類。
Y = P(y | x):這裏機率函數P指某種最小化距離斷定公式
能夠看到,K近鄰法沒有顯示的學習過程,做爲判別模型的一種,k近鄰法的判別函數的具體形式也不是很明顯。
K近鄰法使用的模型實際上對應於特徵空間的劃分,某種意義上來講,k近鄰的模型就是樣本特徵空間自己。
在k近鄰法中,當下列基本要素:
肯定後,對於任何一個新的輸入實例,它所屬的類惟一地肯定。這至關於根據上述基本要素將特徵空間劃分爲一些子空間,肯定子空間裏的每一個點所屬的類。
特徵空間中,對每一個訓練實例點x1,距離該點比其餘點更近的全部點組成一個區域,叫做單元(cell)。每一個訓練實例點擁有一個單元,全部訓練實例點的單元構成對特徵空間的一個劃分:
K近鄰很好地體現了判別式模型的思想,k近鄰不生成機率分佈函數,它只是經過三個基本要素儘量地「捕捉」訓練樣本中的機率密度特徵。之因此輸入樣本會被分到不一樣的類別,其本質就在於在訓練樣本中存在不均勻的機率密度分佈,即某一個區域某一個類別密度佔比比其餘的類多。
下面咱們來具體談談K近鄰模型的幾個基本要素。
K值的選擇會對K近鄰法的結果產生重大影響。
近似偏差和估計偏差的核心區別在因而假設臨近點的噪音擾動比較多仍是遠點的噪音擾動比較多。
在實際應用中,K值通常選取一個比較小的數值,即咱們基本上認爲近鄰點的相關性是比較大的,而原點的相關性比較小
在實際項目中,K值的選擇和樣本中的機率密度分佈有關,並無一個定式的理論告訴我麼該選什麼樣的K值,好在的是這個K值的搜索空間並非很大,一般咱們能夠採起一個for循環交叉驗證來搜索全部可能的K值,經過重複進行屢次實驗,每次隨機選取不一樣的train set和validate set,查看KNN模型對train set和validate set的擬合和泛化能力來選擇一個最好的K值。
理論上分析:
理論上說,當 k 和實例的數量 n 都變成無窮大,使得 k/n -> 0 時,那麼在數據集上產生的偏差機率將達到理論上的最小值。
特徵空間中兩個實例點的距離是兩個實例點類似程度的一種數字化度量。
K近鄰模型的特徵空間通常是n維實數向量空間,計算兩個向量之間的距離有不少種方法,注意這不是KNN獨有的算法,向量間距離模型是數學中的基礎概念:
設特徵空間是n維實數向量空間
:
,
的Lp距離定義爲:
下圖給出了二維空間中p取不一樣值時,與原點的Lp距離爲1(Lp = 1)的點的集合圖形
這張圖很好地說明了取不一樣的距離策略對於KNN對於緊鄰點的搜索範圍是不一樣的,進而影響隨後的判別分類結果
舉一個例子說明由不一樣的距離度量所肯定的最近鄰點是不一樣的。已知二維空間的3個點,咱們來對比一下在p取不一樣的值時,Lp距離下X1的最近鄰點
P值 | 和X2距離 | 和X3距離 |
1 | 4 | 6 |
2 | 4 | 4.24 |
3 | 4 | 3.78 |
4 | 4 | 3.57 |
能夠看到,p = 1/2時,X2是X1的最近鄰點;P >= 3,X3是X1的最近鄰點。
近鄰法中的分類決策規則每每是多數表決,即由輸入實例的k個臨近的訓練實例中的多數的label決定輸入實例的類。當K=1時算法退化爲最近鄰搜索。
多數表決規則(majority voting rule)本質也是最優化技術,它符合極大似然估計原則。
咱們假設分類的損失函數爲0-1損失函數爲:
那麼誤分類的機率是:
對給定的實例,其最近鄰的 k 個訓練實例點構成集合
,若是涵蓋
的區域的類別是Cj,那麼誤分類率是:
要使誤分類率最小,即經驗風險最小,就要使下式最大:
即模型對訓練樣本的預測準確度(擬合程度)最大。因此多數表決規則等價於經驗風險最小化。
KNN的學習策略很簡單,就是在訓練集中尋找最近鄰的K個實例點,並進行voting,選擇最多類別的那個,即經驗風險最小化。這一樣體現了極大似然估計的核心思想。
KNN的策略很是直觀易理解,算法要解決是具體的工程化問題,即如何在高維空間中選出 k 個近鄰點,當維度很高且樣本量很大的時候,若是不採起一些高效的算法而直接暴力搜索的話是很是耗時的。
解決該問題的思路就是利用特殊構造的存儲數據結構以及特殊的搜索方法來完成,這也是本文的重點討論部分。
最早被提出的一種數據結構是樹結構,經過應用分治思想,樹結構將原始的O(N)複雜度下降爲O(logN)複雜度,咱們接下來來討論它。
KD樹是一種對K維空間中的實例點進行存儲以便對其進行快速檢索的樹形數據結構。kd樹是一個二叉樹,一棵KD樹就是一個超平面,表示對K維空間的一個劃分(partition)。構造KD樹至關於不斷地用垂直於座標軸的超平面將K維空間切分,構成一系列的K維超矩形區域。KD樹的每一個結點對應於一K維超矩形區域。
這裏K是數據集屬性的數量。
下圖展現了一個k=2的小例子:
樹不必定會發展到相同的深度,訓練集中的每個實例與樹中的一個結點相對應,最多一半的結點是葉子節點。
輸入:k維空間數據集(樣本數量是N),每一個樣本的維度是k,
用一個例子來講明kd樹構造過程 ,給定一個二維空間的數據集:
與其餘大部分機器學習方法相比,基於實例學習的一個優點是新的實例能夠在任什麼時候候加入到訓練集裏。
新的數據來臨時,須要用新的數據點判斷其屬於哪一個葉子節點,而且找出葉子節點的超矩形。若是超矩形爲空,就將新數據點放置在那裏,不然分裂超矩形,分裂在最長的邊上進行,以保持方形。
這種簡單的探索式方法並不能保證在加入一系列點後,樹依然會維持平衡,也不能保證爲搜索最近鄰塑造良好的超矩形。有時候從頭開始重建數不失爲一個良策。例如,當樹的深度達到最合適的深度值的兩倍時。
完成了KD樹建樹後,接下來討論如何利用KD樹進行高效K近鄰搜索:
輸入:根據train set構造的kd樹;目標點x
輸出:x的最近鄰
用下圖來講明kd樹的搜索過程,根節點爲A,子節點是B,C,D,E,F,G;目標實例點S,求S的最近鄰
咱們已經看到,KD樹是可用於有效尋找最近鄰的良好數據結構,可是,並不完美。當面對不均勻數據的數據集時,便面臨一些基本衝突和挑戰:
這裏所謂的平衡結構,就是指樹的兩邊分叉要儘可能分佈平均,這樣能夠最大程度地發揮O(logN)的優化效果,可是若是數據點的分佈很是不均衡,採用中值的方法也許會在同一個方向上產多屢次後續分裂,從而產生瘦長型的超矩形。一個更好的解決方法是採用平均值做爲分裂點而不是中位值。這樣產生的KD樹會更趨向於方形。
可是均值分裂點技術依然沒法徹底規避KD原生的問題,爲此,學界提出了超球分界面代替超矩形分界面的改進方法。
KD tree的思想很是精妙,可是也存在一些問題, 形並非用到這裏最好的方式。偏斜的數據集會形成咱們想要保持樹的平衡與保持區域的正方形特性的衝突。另外,矩形甚至是正方形並非用在這裏最完美的形狀,因爲它的角。爲了解決這些問題,引入了ball tree,即便用超球面而不是超矩形劃分區域
Ball Tree就是一個K維超球面來覆蓋訓練樣本點。
上圖(a)顯示了一個2維平面包含16個觀測實例的圖,圖(b)是其對應的ball tree,其中結點中的數字表示包含的觀測點數。
樹中的每一個結點對應一個圓,結點的數字表示該區域保含的觀測點數,但不必定就是圖中該區域囊括的點數,由於有重疊的狀況,而且一個觀測點只能屬於一個區域。實際的ball tree的結點保存圓心和半徑。葉子結點保存它包含的觀測點。
Ball tree的建樹過程和KD tree大致上一致,區別在於ball tree每次的切分點都是當前超球體的圓心。
使用Ball tree時:
Relevant Link:
http://blog.csdn.net/pipisorry/article/details/53156836