1.基本概念
k近鄰算法:通過測量待預測點和已知點的特徵值之間的距離,選取前k個距離近的,根據多數表決的方法來分類。
訓練過程:無訓練過程。
測試過程:根據距離來分類。
k越小,模型越複雜,越容易過擬合。
需要對各個屬性(特徵)進行歸一化,防止數值較大的屬性對分類器的影響過大。
2. 優缺點
優點:精度高,異常值不敏感,對輸入格式無要求。
缺點:時間空間複雜度高。無法給出數據的基礎結構信息,無法分析數據特徵。
適用數據範圍:標量和數值型。
3. 常用距離
樣本一:x = (x1, x2, ..., xn)
樣本二:y = (y1, y2, ..., yn)
歐氏距離:
曼哈頓距離:
距離最大值:
4. 代碼實現
參考:《機器學習實戰》
源碼地址以及數據:https://github.com/JieruZhang/MachineLearninginAction_src
手寫python KNN:
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
#處理文檔
def file2mat(file):
f = open(file)
lines = f.readlines()
nums = len(lines)
mat = zeros((nums,3))
classes = []
index = 0
for line in lines:
line = line.strip()
line = line.split('\t')
mat[index,:] = line[0:3]
classes.append(int(line[-1]))
index += 1
return mat, classes
#歸一化:由於各個種類特徵的數字差異大,例如屬性1是百級的,屬性2是小數級的,則屬性1對距離的影響大。爲了使各個特徵之間重要性相同,需要歸一化。
#歸一化方法:new = (old - min)/(max-min),使分佈到0和1之間。
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges,(m,1))
return normDataSet, ranges, minVals
#分類,計算距離
def classifyKNN(test, dataSet, labels, k):
size = dataSet.shape[0]
#計算距離
distance = (((tile(test, (size,1)) - dataSet)**2).sum(axis=1))**0.5
#距離由短到長排序, 將對應的index存入列表
sortIndices = distance.argsort()
#找到前k個最近的樣本對應的類別
classCount = {}
for i in range(k):
label = labels[sortIndices[i]]
#get() 函數返回指定鍵的值,如果值不在字典中返回默認值。
classCount[label] = classCount.get(label,0) + 1
#將前k個classCount按照value的大小排序
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1), reverse=True)
#返回最大的標籤數目對應的標籤
return sortedClassCount[0][0]
#測試
def test():
ratio = 0.1
mat, labels = file2mat('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(mat)
m = normMat.shape[0]
numTest = int(m*ratio)
errorCount = 0.0
for i in range(numTest):
res = classifyKNN(normMat[i,:], normMat[numTest:m,:], labels[numTest:m],3)
if res != labels[i]:
errorCount += 1
print('error rate: %f' % (errorCount/float(numTest)))
datingMat, datingLabels = file2mat('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(datingMat)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingMat[:,1], datingMat[:,2], 15.0*array(datingLabels), 15.0*array(datingLabels))
plt.show()
test()
sklearn 實現:
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
def sklearnKNN():
ratio = 0.1
mat, labels = file2mat('datingTestSet.txt')
normMat, ranges, minVals = autoNorm(mat)
m = normMat.shape[0]
numTest = int(m*ratio)
train_mat = normMat[numTest:m,:]
test_mat = normMat[0:numTest,:]
train_labels = labels[numTest:m]
test_labels = labels[0:numTest]
knn = KNeighborsClassifier(n_neighbors = 3)
knn.fit(train_mat, train_labels)
print('error rate is : ', 1 - knn.score(test_mat, test_labels))
sklearnKNN()