作者:A.y.
日期:2019/10/15
上机环境:Spyder(Anaconda3)
一、问题描述
使用原生python实现knn分类算法,用鸢尾花数据集。
二、算法设计
定义一个KNN_arithm()函数来实现knn分类算法,函数参数为鸢尾花数据集以及测试集。鸢尾花数据集中的数据共分三类,首先定义对应的三个列表以及一个distance列表分别用来存放测试数据与各个数据的欧式距离以及测试数据与所有训练数据的距离,再定义三个整型变量用来表示各类鸢尾花与测试数据的邻近个数。
利用math和numpy库中的函数计算出测试数据与鸢尾花数据集的欧式距离并存入对应的列表,计算结束后将distance列表按升序重新排列,for循环判断distance中的距离在哪一个列表中,既该类邻近个数++,循环次数为k次。判断三类邻近个数的大小,个数最多的那一类既为测试数据的类别
三、代码实现
# -*- coding: utf-8 -*-
"""
Created on Thu Oct 10 15:19:48 2019
@author: Asus
"""
#coding=utf-8
import numpy
import math
import pdb
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
def KNN_arithm(iris_datasets,expected_data): #定义knn算法函数,函数参数为训练集和测试集
iris_data,expected_data,iris_target,expected_target = train_test_split(iris_datasets['data'],iris_datasets['target'],random_state=0)
k = int(input("请输入邻居数k:")) #输入邻近点数
test_target = [] #用来存放测试结果
for j in range(0,len(expected_data)):
distance = [] #用来存放测试集数据与训练集数据的欧氏距离
iris1 = [] #用来存放测试集数据与第一类鸢尾花数据的欧氏距离
iris2 = [] #用来存放测试集数据与第二类鸢尾花数据的欧氏距离
iris3 = [] #用来存放测试集数据与第三类鸢尾花数据的欧氏距离
index1 = 0 #测试集数据与第一类鸢尾花邻近个数
index2 = 0 #测试集数据与第二类鸢尾花邻近个数
index3 = 0 #测试集数据与第三类鸢尾花邻近个数
for i in range(0,len(iris_data)): #计算欧氏距离
distance.append(math.sqrt((numpy.square(expected_data[j][0]-iris_data[i][0])+numpy.square(expected_data[j][1]-iris_data[i][1])+numpy.square(expected_data[j][2]-iris_data[i][2])+numpy.square(expected_data[j][3]-iris_data[i][3]))))
if(iris_target[i]==0):
iris1.append(math.sqrt((numpy.square(expected_data[j][0]-iris_data[i][0])+numpy.square(expected_data[j][1]-iris_data[i][1])+numpy.square(expected_data[j][2]-iris_data[i][2])+numpy.square(expected_data[j][3]-iris_data[i][3]))))
elif(iris_target[i]==1):
iris2.append(math.sqrt((numpy.square(expected_data[j][0]-iris_data[i][0])+numpy.square(expected_data[j][1]-iris_data[i][1])+numpy.square(expected_data[j][2]-iris_data[i][2])+numpy.square(expected_data[j][3]-iris_data[i][3]))))
elif(iris_target[i]==2):
iris3.append(math.sqrt((numpy.square(expected_data[j][0]-iris_data[i][0])+numpy.square(expected_data[j][1]-iris_data[i][1])+numpy.square(expected_data[j][2]-iris_data[i][2])+numpy.square(expected_data[j][3]-iris_data[i][3]))))
distance.sort(reverse = False) #将列表元素升序排列
distance = distance[0:k-1] #截取最短的k个距离
for m in distance: #计算三个类别邻近数
if m in iris1:
index1=index1+1
elif m in iris2:
index2=index2+1
else:
index3=index3+1
final=[index1,index2,index3]
final_index= final.index(max(final))
if final_index==0:
test_target.append(0)
elif final_index==1:
test_target.append(1)
else:
test_target.append(2)
print("预测分类:",test_target)
correct = 0
for i in range(0,len(expected_target)):
if(expected_target[i]==test_target[i]):
correct=correct+1
print("正确率为:","%.2f%%"%(correct/len(expected_target)
*100))
if __name__ =="__main__":
iris_datasets=load_iris()
expected_data=[10,100,5,2]
KNN_arithm(iris_datasets, expected_data)
四、测试截图
设置断点调试观测代码执行顺序:
(省略上面这部分的for循环)
(省略上面这部分for循环)
五、运行结果
六、总结
对knn算法的基本原理和使用了解得更加深刻,因为之前几乎没用过python敲代码,写代码的时候也遇到过很多的问题,第一个问题就是测试数据集与训练集的距离怎样存储的问题,因为对于二维列表的使用不太熟悉,所以我将每一个测试数据与训练集的数据求出的欧式距离存在一维列表distance中,再将求出来的类别加入target列表中。对于distance列表的排序也是需要用到sort()函数,参数reverse是False则表示升序排列,True则表示降序排列。