KNN 鸢尾花分类:使用 Python 实现 K 近邻算法
import random
import csv # csv 包可以读写 csv 文件
K = 5
# 数据读取
with open('iris.csv', 'r') as file: # 打开 iris.csv 文件
reader = csv.DictReader(file) # 使用 csv 包的 DictReader() 方法读取文件内容,将 csv 文件转换为字典形式,每一行数据都是一个字典
datas = [row for row in reader] # 将每一行数据的字典存储到一个列表中
# 分组
random.shuffle(datas) # 将数据集打乱顺序,相当于洗牌
n = len(datas) // 3 # 整除,避免小数的出现
# 2/3 是训练集 1/3 是测试集
test_set = datas[0:n] # 取列表中的前 n 个作为测试集
train_set = datas[n:] # 取列表中的第 n 个及以后的数据作为训练集
# 定义一个函数,用于计算两个数据点之间的距离
def distance(d1, d2):
res = 0 # 定义距离初始值为 0
for key in ('sepal_length', 'sepal_width', 'petal_length', 'petal_width'): # 循环遍历每一个要计算距离的属性
res += (float(d1[key]) - float(d2[key])) ** 2 # 将每个属性的差值平方后累加,得到两个数据点之间的总距离
return res ** 0.5 # 返回两个数据点之间的欧氏距离
# 定义一个函数,用于预测测试集中每一个数据点对应的分类结果
def knn(data):
# KNN 算法过程
# 1. 求距离
# 2. 排序——升序
# 3. 取前 K 个
# 4. 加权平均
# 1. 求距离
res = [
{'result': train['species'], 'distance': distance(data, train)} # 计算测试集中每一个数据点与训练集中每一个数据点之间的距离,将结果存储为字典
for train in train_set
]
# 排序-升序
res = sorted(res, key=lambda item: item['distance']) # 将结果列表按照距离从小到大进行排序,使用 lambda 表达式指定按照字典中的 distance 键值进行排序
# 取前 K 个
resK = res[0:K] # 取排序后的结果列表中前 K 个,即距离最近的 K 个数据点
# 4. 加权平均(离的近的权重高,离得远的权重低)
result = {'setosa': 0, 'versicolor': 0, 'virginica': 0} # 定义一个字典,用于存储每个分类的权重
# 算前 K 个的总距离
sum_distance = 0 # 定义前 K 个数据点中的总距离
for r in resK: # 循环遍历前 K 个数据点
sum_distance += r['distance'] # 将每个数据点的距离累加
for r in resK: # 循环遍历前 K 个数据点
result[r['result']] += 1 - r['distance'] / sum_distance # 计算每个分类的权重,离得近的数据点权重高,离得远的数据点权重低
return (sorted(result, key=lambda x: result[x])[-1]) # 返回字典中最大 value 对应的 key,即预测的分类结果
# 对测试集中的每一个数据点进行分类预测,并计算准确率
correct = 0 # 定义初始正确分类的数据点数为 0
for test in test_set: # 循环遍历测试集中的每一个数据点
result = test['species'] # 获取该数据点的真实分类结果
result_predict = knn(test) # 对该数据点进行分类预测
if result == result_predict: # 如果预测分类结果与真实分类结果一致,则正确分类的数据点数加 1
correct += 1
score = correct / len(test_set) # 计算准确率
print('test Accuracy:{:.2f}'.format(score)) # 输出准确率,保留两位小数
原文地址: https://www.cveoy.top/t/topic/mzLs 著作权归作者所有。请勿转载和采集!