1. 程式人生 > >K-近鄰演算法小案例(二)

K-近鄰演算法小案例(二)

K-近鄰演算法案例

使用k-近鄰演算法來預測一個花的分類。資料集使用的是sklearn裡面的iris資料集。

k近鄰就是尋找當前樣本的最近的k個點,然後把這k個點進行分類,哪個類別最多就把這個當前的樣本點作為哪個分類。

步驟:

1,首先獲取資料,把資料變成一個連結串列list,把分類新增進去之後再轉換成一個矩陣。

還要吧樣本分成測試集合訓練集。

2,計算每個點與樣本點之間的距離,並且排序。

3,得到最近的k個點

4,得到最多的分類

5,預測準確率

首先是獲取資料:

from sklearn import datasets
import numpy
import pandas
import csv
import random
import math
import operator
引入包
def loadDataset(split, trainingSet = [], testSet = []):
    data = datasets.load_iris().data
    target = datasets.load_iris().target
    data = numpy.ndarray.tolist(data)
    data = pandas.DataFrame(data)
    data.insert(4,'target',target)
    dataset = data.as_matrix()
    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])
因為得到的資料集裡面是有幾個欄位的,是一個字典型別。裡面的data就是主要的資料,一些引數都在裡面。target就是預測的目標,用0,1,2,3,4等等來表示。target_name就是一個target的名字:



而我們得到的data資料是不帶target的,所以要新增一個維度。先把資料轉換成一個表格型別,也就是一個DataFrame型別,再新增一個維度,把tarhet新增進去,但是要注意新增的行數要一樣,要不可能會出錯。之後使用一個split分割率來分成訓練集和測試集。比如split是等於0.7,那麼就有7成的是訓練集,3成的是測試集。

求距離函式:

def Distance(instance1,instance2,length):
    distance = 0
    for x in range(length):
        distance += pow((instance1[x] - instance2[x]), 2)
    return math.sqrt(distance)
傳進來兩個例項,length就是維度,就是一個矩陣有多少列的意思。然後相減開發即可。

求附近點的函式:

def getNeighbors(trainingSet, testInstance, k):
    distances = []
    length = len(testInstance)-1
    for x in range(len(trainingSet)):
        dist = Distance(trainingSet[x],testInstance,length)
        distances.append((trainingSet[x],dist))
    distances.sort(key = operator.itemgetter(1))
    neighbors = []
    for y in range(k):
        neighbors.append(distances[y][0])
    return neighbors
傳進來三個引數,一個訓練集一個測試集,還有一個就是鄰居的個數了。一個測試樣本要和訓練集的所有的樣本求距離,所以測試集就只有一個樣本,而訓練集就是所有的。

先得到測試集的一個維度length,測試集和訓練集的維度是一樣的。直接計算並排序就可以了。因為加入到distances連結串列裡面的是一個元祖,所以排序要按照第二個距離來排

istances.sort(key = operator.itemgetter(1))

那個1就第二個,0才是第一個

trainingSet[x]

得到最高投票的類別:

def getResponse(neighbors):
    classVotes = {}
    for x in range(len(neighbors)):
        response = neighbors[x][-1]#因為之前已經在最後添加了一個target的維度,這個neighbors也是從訓#練集拿的,所以也帶有target。-1就是倒數第一個,也就是類別的編號。
        if response in classVotes:
            classVotes[response] += 1
        else:
            classVotes[response] = 1
    sortVotes = sorted(classVotes.items(),key=operator.itemgetter(1),reverse = True)
    return sortVotes[0][0]
準確率的計算函式:
def getAccuracy(testSet, predictions):
    correct = 0
    for x in range(len(testSet)):
        if testSet[x][-1] == predictions[x]:
            correct += 1
    return (correct/float(len(testSet)))*100.0
這個。。。。沒啥好說的。。。

執行函式:

def run(k1):
    split = 0.7
    trainingSet = []
    testSet = []
    loadDataset(split,trainingSet,testSet)
    print('trainingSet',len(trainingSet))
    print('testSet',len(testSet))
    predictions = []
    k = k1
    for x in range(len(testSet)):
        neighbors = getNeighbors(trainingSet,testSet[x],k)
        results = getResponse(neighbors)
        predictions.append(results)
    accuracy = getAccuracy(testSet, predictions)
    print('Accuracy: ' + repr(accuracy) + '%')
    return accuracy
這個是執行函式。。。沒啥好說的。

可以畫一下準確率的影象:
acc = []
for x in range(2,15):
    acc.append(run(x+1))
import matplotlib.pyplot as plt
fig,ax = plt.subplots(figsize = (12,4))
nums = numpy.arange(2,15,step = 1)
print(nums)
print(acc)
ax.plot(nums,acc,'r')
ax.set_xlabel('')
plt.show()
這個是根據k的值畫出準確率的曲線。



可以看到一直都是在百分之90左右,貌似沒有什麼規律。。。。。