K-近鄰演算法小案例(二)
阿新 • • 發佈:2019-01-24
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
因為得到的資料集裡面是有幾個欄位的,是一個字典型別。裡面的data就是主要的資料,一些引數都在裡面。target就是預測的目標,用0,1,2,3,4等等來表示。target_name就是一個target的名字: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的,所以要新增一個維度。先把資料轉換成一個表格型別,也就是一個DataFrame型別,再新增一個維度,把tarhet新增進去,但是要注意新增的行數要一樣,要不可能會出錯。之後使用一個split分割率來分成訓練集和測試集。比如split是等於0.7,那麼就有7成的是訓練集,3成的是測試集。
求距離函式:
傳進來兩個例項,length就是維度,就是一個矩陣有多少列的意思。然後相減開發即可。def Distance(instance1,instance2,length): distance = 0 for x in range(length): distance += pow((instance1[x] - instance2[x]), 2) return math.sqrt(distance)
求附近點的函式:
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左右,貌似沒有什麼規律。。。。。