【機器學習】KNN基本介紹+程式碼實現
阿新 • • 發佈:2019-01-04
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()