天天看點

KNN算法簡單應用

這裡是寫給小白看的,大牛路過勿噴。

1 KNN算法簡介

  KNN(K-Nearest Neighbor)工作原理:存在一個樣本資料集合,也稱為訓練樣本集,并且樣本集中每個資料都存在标簽,即我們知道樣本集中每一資料與所屬分類對應的關系。輸入沒有标簽的資料後,将新資料中的每個特征與樣本集中資料對應的特征進行比較,提取出樣本集中特征最相似資料(最近鄰)的分類标簽。一般來說,我們隻選擇樣本資料集中前k個最相似的資料,這就是k近鄰算法中k的出處,通常k是不大于20的整數。最後選擇k個最相似資料中出現次數最多的分類作為新資料的分類

2 KNN算法優缺點

  優點:精度高,對異常值不敏感、無資料輸入假定

  缺點:計算複雜度高、空間複雜度高

做一個簡單的應用:

一種花叫做虹膜花:

KNN算法簡單應用

收集一些執行個體   萼片長度,萼片寬度,花瓣長度,花瓣寬度 (sepal length, sepal width, petal length and petal width)   類别: Iris setosa, Iris versicolor, Iris virginica.   學習目标是:根據四種屬性判斷類别   用python的sklearn庫實作: (sklearn中已經存在的資料集)

from sklearn import neighbors
from sklearn import datasets

knn = neighbors.KNeighborsClassifier()
iris = datasets.load_iris()

knn.fit(iris.data, iris.target)
# 當資料為0.1, 0.2, 0.3, 0.4時,預測它是什麼花
predictedLabel = knn.predict([[0.1, 0.2, 0.3, 0.4]])
print(predictedLabel)      

   不調用sklearn,自己實作:    這是一個資料集文本  截取資料集(irisdata.txt)的一段:

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa
5.0,3.4,1.5,0.2,Iris-setosa      

導入幾個基本的庫:

import csv
import random
import math
import operator      

全局定義兩個集合:訓練集、測試集

# 訓練集
trainingSet = []
# 測試集
testSet = []      

 讀取資料并做一些初步的處理:

 傳入一個分割機率,随機劃分訓練集和測試集

def loadDataset(filename, split):
    with open(filename, 'r') as csvfile:
        lines = csv.reader(csvfile)
        dataset = list(lines)
        for x in range(len(dataset) - 1):
            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個資料:

計算訓練集中每一項和該執行個體的歐氏距離,取最小的k個距離

def getNeighbors(k, testInstance):
    distances = []
    length = len(testInstance) - 1
    for x in range(len(trainingSet)):
        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      

擷取的這些k項未必是同一類,接下來統計類别個數,并傳回出現次數最多的類作為最終的結果:

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.items(), key=operator.itemgetter(1), reverse=True)
    return sortedVotes[0][0]      

驗證精确度:

将測試集中預測的類别和測試集中真實的類别對比,得出精确度百分比:

def getAccuracy(predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(testSet))) * 100.0      

主函數:

if __name__ == '__main__':
    main()      
def main():
    split = 0.70
    loadDataset(r'D:\ml\irisdata.txt', split)
    print('Train set: ' + repr(len(trainingSet)))
    print('Test set: ' + repr(len(testSet)))      

讀取後列印下個數:

Train set: 102
Test set: 48      

接下來預測:

predictions = []
    k = 3
    for x in range(len(testSet)):
        neighbors = getNeighbors(k, testSet[x])
        result = getResponse(neighbors)
        predictions.append(result)
        print('>predicted=' + repr(result) + ', actual=' + repr(testSet[x][-1]))      

看一下預測的一部分結果:

KNN算法簡單應用

發現基本預測準确,測試精确度:

accuracy = getAccuracy(predictions)
    print('Accuracy: ' + repr(accuracy) + '%')      

發現精确度很高:

KNN算法簡單應用

由于處理資料時候采用随機劃分的方式,可以反複運作測試,發現準确率基本在90%到96%,說明這個模型是合适的

小結:

  KNN是簡單有效的分類資料算法,在使用時必須有訓練樣本資料,還要計算距離,如果資料量非常大會非常消耗空間和時間。它的另一個缺陷是無法給出任何資料的基礎結構資訊,是以我們無法平均執行個體樣本和典型執行個體樣本具體特征,

轉載于:https://www.cnblogs.com/xuyiqing/p/8762066.html