1. 程式人生 > >python 例項簡述 k-近鄰演算法的基本原理

python 例項簡述 k-近鄰演算法的基本原理

鄰近演算法,或者說K最近鄰(kNN,k-NearestNeighbor)分類演算法是資料探勘分類技術中最簡單的方法之一。

k-近鄰演算法概述

k-近鄰演算法採用測量不同特徵值之間的距離方法來進行分類,距離計算方法可以有很多,其中比如說有歐式距離,曼哈頓距離,標準化歐式距離,夾角餘弦等等,可以參考 yoyo 的部落格: http://blog.sina.com.cn/s/blog_52510b1d01015nrg.html ,距離演算法的選擇應當參考實際的專案需求,這裡作為例子用歐氏距離來計算距離。

接下來來看看 kNN 演算法的工作原理:首先我們一個樣本集合,也稱為訓練樣本集,在訓練樣本集中每個資料都存在一個標籤用來指明該資料的所屬分類。在輸入一個新的未知所屬分類的資料後,將新資料的所有特徵和樣本集中的所有資料計算距離。從樣本集中選擇與新資料距離最近的 k 個樣本,將 k 個樣本中出現頻次最多的分類作為新資料的分類,通常 k 是小於20的,這也是 k 的出處。

k近鄰演算法的優點:精度高,對異常值不敏感,無資料輸入假定。
k 近鄰演算法的缺點:時間複雜度和空間複雜度高
資料範圍:數值型和標稱型

簡單的k 近鄰演算法實現

第一步:使用 python 匯入資料

from numpy import *
import operator
'''simple kNN test'''
#get test data
def createDataSet():
        group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
        labels=['A','A','B','B']
        return
group,labels

作為例子,直接建立資料集和標籤,實際應用中往往是從檔案中讀取資料集和標籤。array 是 numpy 提供的一種資料結構,用以儲存同樣型別的資料,除了常規資料型別外,其元素也可以是列表和元組。這裡 group 就是元素資料型別為 list 的資料集。labels 是用列表表示的標籤集合。其中 group 和 labels 中的資料元素一一對應,比如資料點[1.0,1.1]標籤是 A,資料點[0,0.1]標籤是 B。

第二步:實施 kNN 演算法

kNN 演算法的自然語言描述如下:
1. 計算已知類別資料集中的所有點與未分類點之間的距離。
2. 將資料集中的點按照與未分類點的距離遞增排序。
3. 選出資料集中的與未分類點間距離最近的 n 個點。
4. 統計這 n 個點中所屬類別出現的頻次。
5. 返回這 n 個點中出現頻次最高的那個類別。

實現程式碼:

def classify0(inX,dataSet,labels,k):
        dataSetSize=dataSet.shape[0]
        diffMat=tile(inX,(dataSetSize,1))-dataSet
        sqDiffMat=diffMat**2
        sqDistances=sqDiffMat.sum(axis=1)
        distances=sqDistances**0.5
        sortedDistIndicies=distances.argsort()
        classCount={}
        for i in range(k):
             voteIlabel=labels[sortedDistIndicies[i]]
             classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
             sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
        return sortedClassCount[0][0]

classify0函式中的四個引數含義分別如下:inX 是希望被分類的資料點的屬性向量,dataSet 是訓練資料集向量,labels 是標籤向量,k 是 kNN 演算法的引數 k。
接下來來看看本函式的語句都做了那些事。
第一行dataSetSize=dataSet.shape[0],dataSet 是 array 型別,那麼dataSet.shape表示 dataSet 的維度矩陣,dataSet.shape[0]表示第二維的長度,dataSet.shape[1]表示第一維的長度。在這裡dataSetSize 表示訓練資料集中有幾條資料。
第二行tile(inX,(dataSetSize,1))函式用以返回一個將 inX 以矩陣形式重複(dataSetSize,1)遍的array,這樣產生的矩陣減去訓練資料集矩陣就獲得了要分類的向量和每一個數據點的屬性差,也就是 diffMat。
第三行**在 python 中代表乘方,那麼sqDiffMat也就是屬性差的乘方矩陣。
第四行array 的 sum 函式若是加入 axis=1的引數就表示要將矩陣中一行的資料相加,這樣,sqDistances的每一個數據就代表輸入向量和訓練資料點的距離的平方了。
第五行不解釋,得到了輸入向量和訓練資料點的距離矩陣。
第六行sortedDistIndicies=distances.argsort(),其中 argsort 函式用以返回排序的索引結果,直接使用 argsort 預設返回第一維的升序排序的索引結果。
然後建立一個字典。
接下來進行 k 次迴圈,每一次迴圈中,找到 i 對應的資料的標籤,並將其所在字典的值加一,然後對字典進行遞減的按 value 的排序。
這樣迴圈完成後,classCount 字典的第一個值就是kNN 演算法的返回結果了,也就是出現最多次數的那個標籤。

二維的歐式距離公式如下,很簡單:
這裡寫圖片描述
相同的,比如說四維歐式距離公式如下:
這裡寫圖片描述

第三步:測試分類器

在測試 kNN 演算法結果的時候,其實就是討論分類器效能,至於如何改進分類器效能將在後續學習研究中探討,現在,用正確率來評估分類器就可以了。完美分類器的正確率為1,最差分類器的正確率為0,由於分類時類別可能有多種,注意在分類大於2時,最差分類器是不能直接轉化為完美分類器的。