k-鄰近算法概述
k-鄰近算法採用測量不同特徵值之間的距離方法進行分類
優點: 精度高、對異常值不敏感、無數據輸入假定
缺點:計算複雜度高、空間複雜度高
使用數據範圍:數值型和標稱型
工作原理:存在一個樣本數據集合(也稱作訓練樣本集),並且樣本集中每個數據都存在標籤,即我們知道樣本集中每一數據與所屬的對應關係。輸入沒有標籤的新數據後,將新數據的每個特徵與樣本集中數據對應的特徵進行比較,然後算法提取樣本集中特徵最相似數據(最鄰近)的分類標籤。一般來說,選取樣本數據集中前k個最相似的數據,這就是k-近鄰算法中k的出處,通常k是不大於20的整數。最後,選擇k個最相似數據中出現次數最多的分類,作爲新數據的分類。
k-鄰近算法代碼分析:
對未知類別屬性的數據集中的每個點依次執行以下操作:
(1)計算已知類別數據集中的點與當前點之間的距離;
(2)按照距離遞增次序排序;
(3)選取與當前點距離最小的k個點;
(4)確定前k個點所在類別的出現頻率;
(5)返回前k個點出現頻率最高的類別作爲當前點的預測分類。
代碼如下:
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]
代碼註解:
【1】shape[0] 計算矩陣的行數,shape[1]計算矩陣的列數
【2】tile 數組inX以dataSetSize行1列重複,例如:intX 爲[0, 0],則tile計算後
[0, 0]
[0, 0]
[0, 0]
[0, 0]
..... dataSetSize行
【3】** 是指次方, diffMat**2 爲diffMat的平方, 比如[1, 2]**2 = [1, 4]
【4】sqDiffMat.sum(axis=1) 指array中每行元素的和,這些和再組成一個array:
例如: >>>a = array([[1, 2], [2, 4]])
>>>s = a.sum(axis=1)
>>>s
array([3, 6])
>>>a = array([[1, 2, 3], [2, 3, 4]])
>>>s = a.sum(axis=1)
>>>s
array([6, 9])
但是如果array只有一行,例如array([1, 2]), 則不能用sum(axis=1),只能用sum()
【5】classCount = {}新建一個dict, dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value,這裏classCount.get(voteIlabel, 0)是指不存在相對應key值的value則返回0
例如: >>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95
>>> d['Thomas']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'Thomas'
要避免key不存在的錯誤,有兩種辦法,一是通過in判斷key是否存在:
>>> 'Thomas' in d
False
二是通過dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value:
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1
【6】sorted() 按classCount字典的第2個元素(即類別出現的次數)從大到小排序
測試代碼運行效果:
kNN.py文件:
from numpy import *
import operator
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]
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