KNN(K鄰近)演算法
阿新 • • 發佈:2018-12-31
k-鄰近演算法的一般流程
- 收集資料:可以使用任何方法
- 準備資料:距離計算(應該是計算距離)所需要的數值,最好是結構化的資料格式
- 分析資料:可以使用任何方法
- 訓練演算法: 此步驟不適用與k-鄰近演算法
- 測試演算法:計算錯誤率
- 使用演算法:首先需要輸入樣本資料和結構化的輸出結果,然後執行k-鄰近演算法判定輸入資料分別屬於哪個分類,最後應用對計算出的分類執行後續的處理
# -*- coding: utf-8 -*-
# 建立名為kNN.py的Python模組
from numpy import * # 匯入科學計算包NumPy
import operator # 匯入運算子模組
# 匯入資料的函式,該函式返回 group 和 labels
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
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
# 計算array的維度,array(4,2),array.shape=(4,2),shape[0]=4
#dataSetSize = 4
diffMat = tile(inX, (dataSetSize, 1 )) - dataSet
# tile功能是重複某個陣列,tile(A,n).tile(A,(2,1))重複得到的陣列是一個二維陣列
# diffMat :
# [-1. , -1.1],
# [-1. , -1. ],
# [ 0. , 0. ],
# [ 0. , 0.1]
sqDiffMat = diffMat ** 2
# 計算每個特徵值與inX點值的差值的平方
# sqDiffMat:
# [1. , 1.21],
# [1. , 1. ],
# [0. , 0. ],
# [0. , 0.01],
sqDistances = sqDiffMat.sum(axis=1)
# sum of each row,if axis=0:sum of each column
# sqDistances:
# 該步驟的運算結果為:[ 2.21, 2. , 0. , 0.01]
distances = sqDistances ** 0.5
# 計算歐式距離,即xA(xA0, xA1)和xB(xB0, xB1)之間的距離
# d = sqrt((xA0-xB0)^2) + (xA1-xB1)^2)
# 例如:點(0, 0)與(1,2)之間的距離計算為:
# sqrt( (1 - 0)^2 + (2 -0)^2 )
# 這一步的運算結果為:[ 1.48660687, 1.41421356, 0. , 0.1 ]
sortedDistIndicies = distances.argsort()
# numpy.argsort(a, axis=-1, kind='quicksort', order=None)
# 這一步的運算結果為:[2, 3, 1, 0],即sortedDistIndicies[2] < sortedDistIndicies[3] < sortedDistIndicies[1] < sortedDistIndicies[0],
'''
One dimensional array:
>>> x = np.array([3, 1, 2])
>>> np.argsort(x)
array([1, 2, 0])
Two-dimensional array:
>>> x = np.array([[0, 3], [2, 2]])
>>> x
array([[0, 3],
[2, 2]])
'''
classCount = {}
# classCount 是字典
for i in range(k):
m = sortedDistIndicies[i]
# 當i=0時,sortedDistIndicies[0] = 2
voteIlabel = labels[m]
# voteIlabel = B
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
# dict.get(key, default=None)
# key -- 字典中要查詢的鍵。
# default -- 如果指定鍵的值不存在時,返回該預設值值
# 返回指定鍵的值,如果值不在字典中返回預設值None
# 迴圈結束後的結果為:
# classCount = {'A': 1, 'B': 2}
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse= True)
# itemgetter(1)方法按照第二個元素的次序對元組進行排序,
# reverse表示逆序,結果為:[('B', 2), ('A', 1)]
return sortedClassCount[0][0]
if __name__ == '__main__':
group, labels = createDataSet()
print classify0([0, 0], group, labels, 3)
輸出的結果是: B