1. 程式人生 > >【機器學習】使用python實現kNN演算法

【機器學習】使用python實現kNN演算法

kNN(k-nearest neighbor)是一種基本的分類與迴歸的演算法。這裡我們先只討論分類中的kNN演算法。

k鄰近演算法的輸入為例項的特徵向量,對對應於特徵空間中的點;輸出為例項的類別,可以取多類,k近鄰法是建設給定一個訓練資料集,其中的例項類別已定,分類時,對於新的例項,根據其k個最鄰近的訓練例項的類別,通過多數表決等方式進行預測。所以可以說,k近鄰法不具有顯示的學習過程。k臨近演算法實際上是利用訓練資料集對特徵向量空間進行劃分,並作為其分類的“模型”

k值的選擇,距離的度量和分類決策規則是k近鄰演算法的三個基本要素。

這裡需要說明的是,對於距離的度量,我們有很多種度量方法可以選擇,如歐氏距離(2-範數),曼哈頓距離(1-範數),無窮範數等,根據不同的例項,我們可以選擇不同的距離度量方法。

下面給出了利用python和sklearn庫實現的kNN演算法的過程及部分註釋:

# coding=utf-8

# 首先利用sklearn的庫進行knn演算法的建立與預測
# from sklearn import neighbors
# from sklearn import datasets
#
# knn = neighbors.KNeighborsClassifier()      # 呼叫分類器賦在變數knn上
#
# iris = datasets.load_iris()     # 返回一個數據庫,賦值在iris上
#
# print iris      # 顯示這個資料集
#
# knn.fit(iris.data, iris.target) # fit的第一個引數 是特徵值矩陣,第二個引數是一維的向量
#
# predictedLabel = knn.predict([[0.1,0.2,0.3,0.4]])
#
# print predictedLabel

# 下面自己寫一個程式實現knn演算法

import csv
import random
import math
import operator

# filename是指檔名,split是某一個數字,數字前的資料當做訓練集,數字後的資料當做測試集
# trainingSet是訓練集,testSet是測試集
# 函式作用,載入檔案,並將檔案通過隨機數的方法分為訓練集和測試集
def loadDataset(filename, split, trainingSet=[], testSet=[]):
    with open(filename, 'rb') as csvfile:    # 匯入檔案為csvfile格式
        lines = csv.reader(csvfile)     # 讀取所有的行 reader函式的作用
        dataset = list(lines)       # 將所有的行轉換為list的資料節後
        for x in range(len(dataset)-1):     # x在總共的行數中遍歷
            for y in range(4):
                dataset[x][y] = float(dataset[x][y])
            if random.random() < split:
                trainingSet.append(dataset[x])
            else:
                testSet.append(dataset[x])


# 函式作用:計算歐氏距離
# 函式的輸入是兩個例項和他們的維度
def euclideanDistance(instance1, instance2, length):
    distance = 0
    for x in range(length):     # 對於每一個維度內進行一個差的計算,計算出所有維度的平方和
        distance += pow((instance1[x] - instance2[x]),2)
    return math.sqrt(distance)

# 函式作用:返回最近的k的neightbor
# 也就是返回在trainingSet中距離testInstance最近的k個鄰居
def getNeigthbors(trainingSet, testInstance, k):
    distances =[]  # 距離的容器,用來存放所有的距離值
    length = len(testInstance) - 1  # 用來存放testInstance的維度
    for x in range(len(trainingSet)):
        # 對於每一個x 計算訓練集中的資料與例項的距離
        dist = euclideanDistance(testInstance,trainingSet[x],length)
        distances.append((trainingSet[x],dist))
    # 把這些距離從小到大排起來
    distances.sort(key=operator.itemgetter(1))
    neighbors = []
    for x in range(k):
        neighbors.append(distances[x][0])
    return neighbors        # 返回最近的鄰居

def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortedVotes = sorted(classVotes.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortedVotes[0][0]

# 用來檢驗預測結果的正確率
def getAccuracy(testSet,predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:        # [-1]值的是最後一個值,也就是每行的最後的值,即為花的分類
            correct += 1
    return (correct/float(len(testSet))) * 100.00


def main():
    # prepare data
    trainingSet = []
    testSet = []
    split = 0.67
    loadDataset('irisdata.txt',split,trainingSet,testSet) # r的作用是防止錯誤字串意思
    print 'Train Set' + repr(len(trainingSet))
    print 'Test Set' + repr(len(testSet))

    # generate predicitions
    predicitions = []
    k = 3
    for x in range(len(testSet)):
        neighbors = getNeigthbors(trainingSet,testSet[x],k)
        result = getResponse(neighbors)
        predicitions.append(result)
        print('> predicition = ' + repr(result) + ', actual = ' +repr(testSet[x][-1]))
    accuracy = getAccuracy(testSet,predicitions)
    print('Accuracy:' + repr(accuracy) + '%')

main()
程式執行後,相應的輸出如下: