一.KNN算法的概述己原理
1.1概述
KNN算法是机器学习中一种常见的监督学习方法,也是一种惰性学习(懒惰学习是指训练后并不建立确定的模型,而是根据输入的数据与训练集的关系即时进行分类。)
1.2原理
- 计算已知类别数据集中的点与当前点之间的距离;
- 按照距离递增次序排序;
- 选取与当前点距离最小的k个点;
- 确定前k个点所在类别的出现频率;
- 返回前k个点出现频率最高的类别作为当前点的预测分类
二.代码实现
2.1本文选择海伦约会网站算法的实现为主
2.2实现思路,以及数据预处理
1.准备数据,分为训练集,测试集比例为10:3
2.搭建实现环境,查询资料后发现可能需要使用到pandas包进行数据读取以及matplotlib.pyplot字库对数据进行图像绘制方便直观的观察数据
因此在conda中创建python版本为3.7的环境,在pycharm中导入环境使用
3.测试数据的准备,在gitee平台寻找数据源
4.实现思路
1.首先对数据进行读取
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'Simhei'
# 读取数据集
data = pd.read_csv("C:\\Users\\23271\\Desktop\\大二下课程作业\\机器学习\\1.txt" ,sep="\t",header=None)
data.columns = ['每年飞行常客里程', '玩游戏视频所占时间比', '每周消费冰淇淋公升数', '类型']
2.测试集数据分类,将海伦非常喜欢的标记为3,一般喜欢的标记为2,不喜欢滴标记为1
(一小段数据集)
color = []
for i in range(len(data)):
type = data.iloc[i, -1] #读取每行最后一列的数据
if type == 3:
color.append('red')
elif type == 2:
color.append('green')
else:
color.append('black')
3.展示数据集,排列组合得可以得到3个俩俩相对得散点图
pl = plt.figure(figsize=(12, 8))
fig1 = pl.add_subplot(221) #221表示创建一个2*2网格,放在第一个
plt.scatter(data.iloc[:, 1], data.iloc[:, 2], marker='.', c=color) #读取data数据中得第1列和第二列绘制散点图,形状为.,颜色通过color函数实现
plt.xlabel('玩游戏视频所占时间比')
plt.ylabel('每周消费冰淇淋公升数')
fig2 = pl.add_subplot(222)
plt.scatter(data.iloc[:, 0], data.iloc[:, 1], marker='.', c=color)
plt.xlabel('每年飞行常客里程')
plt.ylabel('玩游戏视频所占时间比')
fig3 = pl.add_subplot(223)
plt.scatter(data.iloc[:, 0], data.iloc[:, 2], marker='.', c=color)
plt.xlabel('每年飞行常客里程')
plt.ylabel('每周消费冰淇淋公升数')
plt.show()
绘制完成后的散点图
4.数据准备阶段完成,接着就是实现对数据的处理,采用数据归一化处理
#归一化处理
def minmax(dataSet):
minDf = dataSet.min()
maxDf = dataSet.max()
normSet = (dataSet - minDf )/(maxDf - minDf)
return normSet
MM_data1 = pd.concat([minmax(data1.iloc[:, :3]), data1.iloc[:,3]], axis=1)
#data1.iloc[:, :3]: 选择data1 DataFrame的前三列。
#minmax(data1.iloc[:, :3]): 对这三列进行归一化处理。
#data1.iloc[:,3]: 选择data1 DataFrame的第四列
#pd.concat(...): 使用concat方法将归一化后的前三列和原始的第四列合并成一个新的DataFrame。axis=1表示沿着列方向进行合并。
MM_data2 = pd.concat([minmax(data2.iloc[:, :3]), data2.iloc[:,3]], axis=1)
print(MM_data1.iloc[0:2,0:3])
print(MM_data2.iloc[0:2,0:3])
#上面俩行是对归一化处理后的数据观测
观测结果,归一化成功。
2.3算法核心
1.查阅资料后发现,可以使用欧式距离公式来实现对测试集的标签分类
2.实现距离的计算和储存
记n为特征数,m为测试集数量
得出diff
的数据结构是一个二维数组(或矩阵),其形状为 (m, n)
。这个矩阵中的每一行都代表 train
中对应行与 test
中第 i
行之间的差值。由于是以train作减,所以可以直接用
dist_type = pd.DataFrame({"dist":dist,"labels":train.iloc[:,n]})#对应得整合数据标签
接着就是对距离差值从小到大排序,并且统计标签得频率,从最近的k个标签中选择相同标签最多的标签作为预测值
# 排序,提取前k个
sort_dist_k = dist_type.sort_values(by='dist')[:k]
# 统计频率
counts = sort_dist_k.loc[:,'labels'].value_counts()
# 获取预测值添加到结果集中
result.append(counts.index[0])
最后就是将预测标签加到test集中的最后一列与之前一列对比得出正确率
result = pd.DataFrame(result)
test['predict'] = result.values
accuracy = (test.iloc[:, -1] == test.iloc[:, -2]).mean()
print(f"模型的预测准确率为{accuracy}")
当k值为5时所得出的准确率如下
三.实验结果以及分析
1.使用matlpotlib绘制散点图如下
1.1可能性分析
1图得点分散过于集中,可能是玩游戏和冰淇淋这俩因素得组合对海伦得对象选择没有较大影响,而2,3图像相同颜色点位分布离散,可以考虑对因素比重加权处理。
2.不同k值下得准确率预测
k=1
k=2
k=3
k=4
k=5
k=10
k=100
K取值小的时候(如k==1),仅用较小的领域中的训练样本进行预测,模型拟合能力比较强。但是容易泛化能力减弱
K值取值太大时,情况相反,容易欠拟合,一般情况泛化能力强。本文所选取的测试集是从训练集中截取30%所得。可以考虑将训练集中的这部分删除或者不删除来观测模型在k值不同情况下的预测准确率。由于本文选取的训练集没有删除测试集选取的部分,所以k越大,拟合度越差。