KNN算法
一,KNN算法概述
knn算法,又叫k-近邻算法。属于一个分类算法,主要思想如下:
一个样本在特征空间中的k个最近邻的样本中的大多数都属于某一个类别,则该样本也属于这个类别。其中k表示最近邻居的个数。(通俗理解:和最近的几个是一类)
二维图示:
二,算法步骤
KNN算法的具体实现
一、数据获取
Iris 鸢尾花数据集内包含 3 类分别为山鸢尾(Iris-setosa)、变色鸢尾(Iris-versicolor)和维吉尼亚鸢尾(Iris-virginica),共 150 条记录,每类各 50 个数据,每条记录都有 4 项特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这4个特征预测鸢尾花卉属于哪一品种。
iris数据集包含在sklearn库当中,具体在sklearn\datasets\data文件夹下,文件名为iris.csv。以本机为例。其路径如下:
D:\python\lib\site-packages\sklearn\datasets\data\iris.csv
其中数据如下格式:
第一行数据意义如下:
150:数据集中数据的总条数
4:特征值的类别数,即花萼长度、花萼宽度、花瓣长度、花瓣宽度。
setosa、versicolor、virginica:三种鸢尾花名
从第二行开始:
第一列为花萼长度值
第二列为花萼宽度值
第三列为花瓣长度值
第四列为花瓣宽度值
第五列对应是种类(三类鸢尾花分别用0,1,2表示)
————————————————
版权声明:本文为优快云博主「Elf.苏洛曦」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_42302831/article/details/102553007
二、具体代码的实现
// 完整代码
import csv
import random
import operator
#读取数据
with open('iris.csv','r') as file: ##打开文件'iris.csv',并命名为 file
reader = csv.DictReader(file) ##DictReader 以字典的形式读取这个文件,reader可迭代
#for row in reader:
#print(row) #可以打出每一行的值
datas = [row for row in reader] ##推导; 把每行都存到datas内。datas就是一个大的list
##分组
random.shuffle(datas) ##因给定的数据是按类别分好的,要打乱。 shuffle洗牌的意思
n = len(datas)//3 #// 表示整除 ##将数据分成三份
test_set = datas[0:n] ##测试组
train_set = datas[n:] ##训练组
##KNN
##求距离
def distance(d1, d2):
res = 0
feature = ("150","4","setosa","versicolor")
##官方的表格很是奇怪,这里根据csv文件直接进行字典匹配的特性,没有对第一行的数据进行修改
##这四个分别对应四个特征:花萼长度值,花萼宽度值,花瓣长度值,花瓣宽度值
for key in (feature): ##循环对每个特征进行相见平方
res += (float(d1[key])-float(d2[key]))**2
##csv读过来的数据都是字符串,所以要float转换成浮点型,进行运算
return res**0.5##对加和求导,就得到距离。
#开始我对距离理解v不是很好,距离不只是狭义的空间上的距离,可以理解为n维空间的距离
K = 5 ##k取5
##KNN算法
def knn(data):
#1 求距离
#2 排序——升序
#3 取前K个
#4 加权平均
#1 求距离
res = [
{"result":train['virginica'], "distance": distance(data, train)}
for train in train_set
]
##再用推导,将花的种类赋值给result,将距离赋值给distance
#2 排序——升序
#以 distance 为依据升序,距离近的排前面
res = sorted(res, key = lambda item:item['distance'])#item:将结果以列表的形式展示
#print(res) ##每一步输出防止整个程序写完出错
#3取前K个
res2 = res[0:K] ##取前K个
#print(res2)
#4 加权平均
result = {'0': 0, '1':0, '2': 0}#
##总距离
sum = 0
for r in res2: ##将K个值的总距离加起来
sum+= r['distance']
for r in res2: ##距离近的加权就越大,(距离近distance小,用1减就大了)
result[r['result']] += 1 - r['distance']/sum ##距离近权重的就会不断累加
resulutCount1= sorted(result.items(), key=operator.itemgetter(1), reverse=True)
## 依据加权结果的大小进行排序,reverse = True 为降序
return (resulutCount1[0][0])#返回最大值
##测试阶段
correct = 0 ##定义正确的个数
for test in test_set: ##测试集进行测试对比
result = test['virginica']
result2 = knn(test)
if result == result2:
correct+=1
print("正确率:{:.2f}%".format(100*correct/len(test_set)))
参考博客
视频教程:
https://www.bilibili.com/video/BV1Nt411i7oD?t=1080
KNN算法:
https://blog.youkuaiyun.com/qq_42302831/article/details/102553007
排序:
https://blog.youkuaiyun.com/u013095333/article/details/83899613