数据集简介https://www.cnblogs.com/mandy-study/p/7941365.html
参考书:李航的《统计学习方法》
书上的内容写得比我好得多的多!这里不重复叙述,以下给出算法步骤:
def f1(x1,x2,p):
#两向量之间的距离度量
return sum(np.power(abs(x1-x2),p))**(1/p)
def distance_dict(x1,Training_set,p):
return {inx:f1(x1,val,p) for inx,val in enumerate(Training_set)}
上述代码中的enumerate()方法可以查阅相关文章。
def sort_dict(x1,Training_set,p,k):
#排序dict_distance中最小的k个数据,
Distance_dict = distance_dict(x1,Training_set,p)
Sort_Distance_dict = sorted(Distance_dict.items(),key=lambda x:x[1]) #元组形式
return dict([Sort_Distance_dict[i] for i in range(k)])
上述代码中的第4行可以查阅字典排序的相关文章。
#sort_k_dict参数是字典的数据结构
def count_dict1(sort_dict,Training_lable):
counter = {}
for i in sort_dict.keys(): #i是该字典的键,即为索引值!
if Training_lable[i] not in counter:
counter[Training_lable[i]] = 1
else:
counter[Training_lable[i]] += 1
return counter
关于计数功能,这里给出第二个方法:
#通过collection Counter类 实现相同效果
from collections import Counter
def count_dict2(sort_dict,Training_lable):
counter = Counter([Training_lable[i] for i in sort_dict.keys()])
return counter
#count_dict 参数是字典,键是标签、值是k个标签中对应于键的个数;
def print_count_dict(count_dict):
max_num = max(count_dict.values())
key_list = [key for key,value in count_dict.items() if value == max_num]
if len(key_list) == 1: #如果k个标签中能确定只有1个标签对应的值最大
return key_list[0] #返回该标签
else:
return tuple(key_list) #否则以元组的形式返回多个标签
到目前为止,算法的分解步骤已经完成!只要将上述def进行整理用个def封装起来(class我不会…)。最终版代码如下:(建议用jupyter)
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label'] = iris.target
#df.values 查看df的数据
#定义一个KNN函数,将部分中间过程的函数整理一下;直接对 向量x1是属于数据集的哪个标签进行判断,返回标签值;
def f1(x1,x2,p):
#两向量之间的距离
return sum(np.power(abs(x1-x2),p))**(1/p)
def KNN(x1,Training_set,Training_lable,p,k):
def distance_dict(x1,Training_set,p):
return {inx:f1(x1,val,p) for inx,val in enumerate(Training_set)}
def sort_dict(x1,Training_set,p,k):
#排序dict_distance中最小的k个数据,
Distance_dict = distance_dict(x1,Training_set,p)
Sort_Distance_dict = sorted(Distance_dict.items(),key=lambda x:x[1]) #元组形式
return dict([Sort_Distance_dict[i] for i in range(k)])
def count_dict1(sort_dict,Training_lable):
counter = {}
for i in sort_dict.keys(): #i是该字典的键,即为索引值!
if Training_lable[i] not in counter:
counter[Training_lable[i]] = 1
else:
counter[Training_lable[i]] += 1
return counter
def print_count_dict(count_dict):
max_num = max(count_dict.values())
key_list = [key for key,value in count_dict.items() if value == max_num]
if len(key_list) == 1: #如果k个标签中能确定只有1个标签对应的值最大
return key_list[0] #返回该标签
else:
return tuple(key_list) #否则以元组的形式返回多个标签
Sort_dict = sort_dict(x1,Training_set,p,k) #计算x1与数据集Trainin_set中所有向量的距离,并返回k个最小的索引,距离值的字典
Count_dict = count_dict1(Sort_dict,Training_lable) #将排序好的Sort_dict进行 数据集标签 的计数,返回字典形式
Print_count_dict = print_count_dict(Count_dict) #输出标签计数字典中值最大的键,如果最大值有多个,则以元组的形式返回多个标签
return Print_count_dict
思路
本次实践将0、1、2类标签划分为训练集和测试集两个数据集,其中训练集占比80%(0、1、2类标签数据各40条),测试集占比20%(0、1、2类标签数据各10条)
#处理数据
dataAll = df.values
dataAll_x = np.array([np.delete(i,-1) for i in dataAll])
dataAll_label = np.array([i[-1] for i in dataAll])
这里因为提前知道了鸢尾花数据,所以才这么划分!
#数据集和测试集用np.array的数据结构,而数据标签用列表的数据结构
training_set = np.array(list(dataAll_x[0:40])+list(dataAll_x[50:90])+list(dataAll_x[100:140]))
training_set_lable = list(dataAll_label[0:40])+list(dataAll_label[50:90])+list(dataAll_label[100:140])
test_set = np.array(list(dataAll_x[40:50])+list(dataAll_x[90:100])+list(dataAll_x[140:150]))
test_set_lable = list(dataAll_label[40:50])+list(dataAll_label[90:100])+list(dataAll_label[140:150])
现在判断测试集中的向量是属于哪些类别;
然后把遍历KNN函数得到的结果用列表的结果装起来,将此列表与测试集已知的标签列表进行对比,才有准确率的概念
#KNN算法中的参数:p取2 k取7
KNN_lable_list = [KNN(i,training_set,training_set_lable,2,7)for i in test_set]
KNN_lable_list
num1 = 0
for i,j in zip(KNN_lable_list,test_set_lable):
if i != j:
num1 += 1
print("KNN算法判断的类别与测试标签类别有误\n"+"判断的类别为:"+str(i)+"\n原测试集类别为:"+str(j))
accuracy = (len(test_set_lable)-num1)/len(test_set_lable)
print("准确率:"+str(accuracy))
本人非计算机专业,对于代码的优化、数据结构的应用上做的并不好!而且上面代码写完后发现标签的单词打错了…label打成了lable!
建议:
在参考此份代码的同时,一定要把函数def调出来,自己多带几个参数进去玩,同时也要去参考李航《统计学习方法》中的K近邻。