《视觉学习实践》实验一:实现K近邻分类器

《视觉学习实践》实验一:实现K近邻分类器

实验内容

  1. 数据预处理;
  2. 实现K近邻算法;
  3. 绘制图像;
  4. 运行程序,比较结果。

实验算法设计

  1. 数据预处理

将实验数据转存到data.txt中,放在data文件夹下。设计一个loadData函数,函数的输入是filepath,表示文件路径。函数的功能是读取这个文件,将数据转为浮点数,存储在一个列表中。函数的输出是列表data。代码如下:

# 读取数据
def loadData(filepath):
    data = []
    f = open(filepath, 'r')
    for line in f:
        data.append(np.array(line.split(','), dtype=np.string_).astype(np.float64))
    return data

同时,无论是对实验数据还是测试数据,都要进行归一化处理。代码如下:

# 数据归一化处理
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    m = dataSet.shape[0]
    normDataSet = dataSet - np.tile(minVals, (m, 1))
    # print normDataSet
    normDataSet = normDataSet / np.tile(ranges, (m, 1))
    # print normDataSet
    return normDataSet, ranges, minVals


# 测试数据归一化
def normTest(dataSet, ranges, minVals):
    return (dataSet - minVals) / ranges
  1. 实现K近邻算法
    函数的输入是测试样本、样本集、标签和k值。距离采用的是欧氏距离,即:

在这里插入图片描述

函数的功能是计算测试样本与样本集中各样本的距离,按逆序排序后,得到k个距离测试样本最近的样本的标签集,测试样本的标签就是标签集中出现次数最多的标签。函数的输出是测试样本的标签。代码如下:

# 分类
def classify(test, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = np.tile(test, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()

    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
  1. 绘制图像
    绘制散点图,好瓜用绿色圆点表示,坏瓜用红色圆点表示。再绘制测试样本,用星形点表示,根据前面得到的分类结果,若它是好瓜,则用绿色表示;若它是坏瓜,则用红色表示。代码如下:
# 绘图
good_melons = group[:8]
bad_melons = group[-9:]
# print(good_melons)
# print(bad_melons)
for melon in good_melons:
    plt.scatter(melon[0], melon[1], color='green')
for melon in bad_melons:
    plt.scatter(melon[0], melon[1], color='red')
if c == '是':
    plt.scatter(test[0], test[1], marker='*', color='green')
else:
    plt.scatter(test[0], test[1], marker='*', color='red')
plt.savefig('实验结果.jpg')
plt.show()
  1. 测试
    编写测试代码如下所示:
# 测试
filepath = 'data/data.txt'
data = loadData(filepath)
group = np.array(data)
labels = ['是', '是', '是', '是', '是', '是', '是', '是', '否', '否', '否', '否', '否', '否', '否', '否', '否']
normDataSet, ranges, minVals = autoNorm(group)
test = [0.61, 0.2]
normtest = normTest(test, ranges, minVals)
c = classify(normtest, normDataSet, labels, 3)
print('类别为:%s' % c)

算法及创新

K近邻(K-Nearest Neighbour,简称KNN),常用于有监督学习,是最常用的分类算法之一。算法非常简单,即给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。

下面为算法概述:

输入:训练样本集,训练样本集对应的类别标签,测试数据。
输出:测试数据对应的分类标签。

步骤1:将新数据的每个特征与样本集中的数据对应的特征进行比较;
步骤2:提取样本集中特征最相似的k个数据的分类标签;
步骤3:统计这k个标签中出现次数最多的类别,作为新数据的类别。

K近邻算法流程图如下所示:

在这里插入图片描述

本实验的创新点在于:实现了K不同取值时分类实验,分析实验结果。采用了LP距离、欧氏距离等不同距离计算验证K近邻分类结果,并分析讨论。

实验数据及结果分析

给定的数据样本是西瓜数据集3.0α,如表1所示。

编号密度含糖率好瓜
10.6970.460
20.7740.376
30.6340.264
40.6080.318
50.5560.215
60.4030.237
70.4810.149
80.4370.211
90.6660.091
100.2430.267
110.2450.057
120.3430.099
130.6390.161
140.6570.198
150.3600.370
160.5930.042
170.7190.103

设置k=3,测试样本为test = [0.61, 0.2],运行程序。程序输出类别为否。程序绘制的散点图如图2所示。

在这里插入图片描述

修改k=5,再次运行程序。程序输出类别为是。程序绘制的散点图如图3所示。

从散点图可以看出,当k=3时,程序判断测试样本是坏瓜,标记为红色;但当k=5时,程序判断测试样本是好瓜,标记为绿色。从上述实验结果可以看出,K近邻算法根据离测试样本最近的K个样本点的标签来决定它的标签,程序得到的结果是正确的。
在K近邻算法中改用LP距离(l=1,p=4),即:

# 分类
def classify(test, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = np.tile(test, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 4
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.25
    sortedDistIndicies = distances.argsort()

    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

分别令k=3,k=5,重新运行程序。当k=3时,程序判断测试样本是坏瓜,标记为红色;但当k=5时,程序判断测试样本是好瓜,标记为绿色。实验结果仍然正确。

总结

本实验实现了K近邻算法,分别将k设置为3和5,对测试样本的分类得到了不同的结果,实验效果符合预期。后面将距离的定义从欧式距离改为LP距离,重新进行实验,实验结果仍然正确。通过此次实验,很好地掌握了K近邻算法的基本原理,熟悉了Python第三方库——matplotlib和numpy的使用。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值