题目:原生python实现knn分类算法,用鸢尾花数据集。
一、题目分析
Knn的基本思想就是在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较,找到训练集中与之最为相似的前k个数据,则该测试数据对应的类别就是k个数据中出现次数最多的那个分类。其算法描述为:
(1)计算测试数据与各个训练数据之间的距离;
(2)按照距离的递增关系进行排序;
(3)选取距离最小的K个点;
(4)确定前K个点所在类别的出现频率;
(5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。
二、算法构造
三、程序实现(源代码)
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 14 16:24:51 2019
@author: Administrator
"""
import csv #用于处理csv文件
import random #用于随机数
import math
import operator
#加载数据集
def loadDataset(filename,split,trainingSet=[],testSet = []):
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):
res = 0
for x in range(length):
res += pow((instance1[x] - instance2[x]),2) #两者求差值的平方
return math.sqrt(res) #再开方
#返回K个最近邻
def getNeighbors(trainingSet,testInstance,k):
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)) #定义函数key,获取对象的第1个域的值,并对其进行升序
neighbors = []
#返回k个最近邻
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
#对k个近邻进行合并,返回value最大的key
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
#排序(其中reverse参数是一个bool变量,表示升序还是降序排列,默认为false(升序排列),定义为True时将按降序排列)
sortedVotes = sorted(classVotes.items(),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]:
correct+=1
return (correct/float(len(testSet))) * 100.0
return ("{:2f}%".format(100*correct/len(testSet)))
def main():
trainingSet = [] #训练集
testSet = [] #测试集
split = 0.7 #分割的比例
loadDataset("iris.csv", split, trainingSet, testSet)
print ("训练集:" + repr(len(trainingSet)) )
print ("测试集:" + repr(len(testSet)) ) #其中repr() 函数将对象转化为供解释器读取的形式。
predictions = [] #预测值
k=5
#k = 5 #定义返回5个最近邻居数
for x in range(len(testSet)):
neighbors = getNeighbors(trainingSet, testSet[x], k)
result = getResponse(neighbors)
predictions.append(result)
print( "预测值为: " + repr(result) + ",实际值为: " + repr(testSet[x][-1]) )
accuracy = getAccuracy(testSet, predictions)
print ("准确率为:" + repr(accuracy) + "%" )
if __name__ =="__main__":
main()
四、调试、测试及运行结果
4.1调试结果
4.2测试结果
4.2.1测试代码(加载数据集)
测试结果
4.2.2测试代码(计算准确率):
测试结果:
4.3.运行结果
五、总结
1.不足:刚开始不知道knn算法从何入手,查询了相关资料后了解了knn算法的大致过程,在网上找了相关视频从基础看了下理清了思路后才开始着手写,但是实现过程中还是遇到了很多问题:
- 刚开始iris.csv鸢尾花数据集导入不成功,经过检查发现没有导入csv文件,并且要将.py文件和.csv文件放在一个目录下;
- 由于粗心大意,过程中出现了一些细小错误,打开csv文件时,错把“:”写成“;”,报错了,可见还是要细心。
打开csv文件如下所示:
2.心得:此次knn算法我也收获了很多,通过查找资料,学习视频我了解了knn的基本算法过程,总体分为5步,此次作业是通过导入鸢尾花的数据集做的,而不是导入库函数;同时我对列表,字典等的应用也有了一定的掌握!
参考网址:https://www.cnblogs.com/momo072994MLIA/p/9435102.html