【機器學習】KNN基本介紹+代碼實現

1.基本概念

k近鄰算法:通過測量待預測點和已知點的特徵值之間的距離,選取前k個距離近的,根據多數表決的方法來分類。

訓練過程:無訓練過程。

測試過程:根據距離來分類。

k越小,模型越複雜,越容易過擬合。

需要對各個屬性(特徵)進行歸一化,防止數值較大的屬性對分類器的影響過大。

2. 優缺點

優點:精度高,異常值不敏感,對輸入格式無要求。

缺點:時間空間複雜度高。無法給出數據的基礎結構信息,無法分析數據特徵。

適用數據範圍:標量和數值型。

3. 常用距離

樣本一:x = (x1, x2, ..., xn)

樣本二:y = (y1, y2, ..., yn)

歐氏距離: L(x,y) = \sqrt{\sum (x_i - y_i)^2}

曼哈頓距離:L(x,y) = \sum |x_i - y_i|

距離最大值:L(x,y) =max |x_i - y_i|

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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章