首页 >> 大全

K-近邻分类算法的python实现及案例分析

2023-11-15 大全 28 作者:考证青年

文章目录 2,处理分类问题 二、约会网站配对效果判定 三、手写数字识别 总结

一、电影类别分类 k-近邻算法是一种基本分类与回归方法,我们可以使用k-近邻算法分类一个电影是是爱情片还是动作片。 1.准备电影数据

以下是我们已有的数据集合,也就是训练样本,假如有一部未看过的电影,如何确定它是爱情片还是动作片呢,我们可以使用kNN来解决这个问题。

电影名称打斗场景接吻镜头电影类型

Man

104

爱情片

He 's Not into Dudes

100

爱情片

Woman

81

爱情片

Kevin

101

10

动作片

Robo

99

动作片

Amped

98

动作片

1.创建数据集

首先,使用numpy创建我们所需的数据集代码,

import numpy as np
import operator
"""
group - 数据集
labels - 分类标签
"""
# 创建数据集
def createDataSet():group = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']return group, labelsif __name__ == '__main__':# 创建数据集group, labels = createDataSet()print(group)print(labels)

运行结果如下

2,处理分类问题

根据欧式距离公式计算出两点之间的距离,并返回前K个点的分类结果。

2.1分类代码

代码如下:

"""
parameters:inX - 用于分类的数据(测试集)dataSet - 用于训练的数据(训练集)labels - 分类标签k - kNN算法参数,选择距离最小的k个点
returns:sortedClassCount[0][0] - 分类结果
"""
# 分类
def classifyo(inX,dataSet,labels,k):dataSetSize = dataSet.shape[0]     # shape[0] 返回dataSet的行数diffMat = np.tile(inX, (dataSetSize, 1))-dataSet# 二维特征相减后平方sqDiffMat = diffMat ** 2# sum(0)列相加,sum(1)行相加sqDistances = sqDiffMat.sum(axis=1)# 开方计算出距离distances = sqDistances ** 0.5# 返回distances中元素从小到大排序后的索引值sortedDistIndicies = distances.argsort()# 定一个记录类别次数的字典classCount = {}for i in range(k):# 取出前k个元素的类别voteIlabel = labels[sortedDistIndicies[i]]classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]
if __name__ == '__main__':# 创建数据集group, labels = createDataSet()# 测试集test = [18, 90]# kNN分类test_class = classifyo(test, group, labels, 3)# 打印分类结果print(print(test_class)

运行结果如下

二、约会网站配对效果判定 1. 收集数据

海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人。经过一番总结,她发现曾交往过三种类型的人:

海伦收集约会数据巳经有了一段时间,她把这些数据存放在文本文件.tet中,每个样本数据占据一行,总共有1000行。海伦的样本主要包含以下3种特征:

2. 准备数据 2.1 从文本文件中解析数据

将上述特征数据输入到分类器之前,还需将待处理数据的格式转换为分类器可以接受的格式。创建名为的函数,该函数输入为文件名字符串,输出为训练样本矩阵和类标签向量。

import numpy as np
def file2matrix(filename):fr = open(filename)arrayOLines = fr.readlines()numberOfLines = len(arrayOLines)#返回的NumPy矩阵,解析完成的数据:numberOfLines行,3列returnMat = np.zeros((numberOfLines, 3))classLabelVector = []index = 0for line in arrayOLines:line = line.strip()listFromLine = line.split('\t')returnMat[index, :] = listFromLine[0:3]if listFromLine[-1] == 'didntLike':classLabelVector.append(1)elif listFromLine[-1] == 'smallDoses':classLabelVector.append(2)elif listFromLine[-1] == 'largeDoses':classLabelVector.append(3)index += 1return returnMat, classLabelVectorif __name__ == '__main__':# 打开的文件名filename = "datingTestSet.txt"# 打开并处理数据datingDataMat, datingLabels = file2matrix(filename)print(datingDataMat)print(datingLabels)

运行结果

从结果可以分析出已经将文本文件导入了数据,并将其转换了想要的格式,接下来就可以采用图形化的方式直观地展示数据。

2.2 可视化数据

_近邻算法的应用_python最近邻算法

我们使用制作了文本数据的散点图,我们可以根据图形实现数据的分析。


from numpy import *
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.patches import Rectanglen = 1000   # number of points to create
xcord1 = []
ycord1 = []
xcord2 = []
ycord2 = []
xcord3 = []
ycord3 = []
markers = []
colors = []
fw = open('testSet.txt', 'w')
for i in range(n):[r0, r1] = random.standard_normal(2)myClass = random.uniform(0, 1)if (myClass <= 0.16):fFlyer = random.uniform(22000, 60000)tats = 3 + 1.6*r1markers.append(20)colors.append(2.1)classLabel = 1       # 'didntLike'xcord1.append(fFlyer)ycord1.append(tats)elif ((myClass > 0.16) and (myClass <= 0.33)):fFlyer = 6000*r0 + 70000tats = 10 + 3*r1 + 2*r0markers.append(20)colors.append(1.1)classLabel = 1      # 'didntLike'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord1.append(fFlyer); ycord1.append(tats)elif ((myClass > 0.33) and (myClass <= 0.66)):fFlyer = 5000*r0 + 10000tats = 3 + 2.8*r1markers.append(30)colors.append(1.1)classLabel = 2    # 'smallDoses'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord2.append(fFlyer); ycord2.append(tats)else:fFlyer = 10000*r0 + 35000tats = 10 + 2.0*r1markers.append(50)colors.append(0.1)classLabel = 3    # 'largeDoses'if (tats < 0): tats = 0if (fFlyer < 0): fFlyer = 0xcord3.append(fFlyer)ycord3.append(tats)fw.close()
fig = plt.figure()
ax = fig.add_subplot(111)
# ax.scatter(xcord,ycord, c=colors, s=markers)
type1 = ax.scatter(xcord1, ycord1, s=20, c='red')
type2 = ax.scatter(xcord2, ycord2, s=30, c='green')
type3 = ax.scatter(xcord3, ycord3, s=50, c='blue')
ax.legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
ax.axis([-5000, 100000, -2, 25])
plt.xlabel('Frequent Flyier Miles Earned Per Year')
plt.ylabel('Percentage of Time Spent Playing Video Games')
plt.show()

![在这里插入图片描述](,,,ogpY=,,,t_70,g_se,x_16

2.3 归一化数据

表2-3给出了提取的四组数据,如果想要计算样本三和样本四之间的距离可以采用下面的方法。

我们很容易发现,上面方程中数字差值最大的属性对计算结果的影响最大,也就是说,每年获取的飞行常客里程数对于计算结果的影响将远远大于表2.1中其他两个特征-玩视频游戏所耗时间占比和每周消费冰淇淋公斤数的影响。而产生这种现象的唯一原因,仅仅是因为飞行常客里程数远大于其他特征值。但海伦认为这三种特征是同等重要的,因此作为三个等权重的特征之一,飞行常客里程数并不应该如此严重地影响到计算结果。

在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化,如将取值范围处理为0到1或者-1到1之间。下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:

newValue = (oldValue - min) / (max - min)

其中min和max分别是数据集中的最小特征值和最大特征值。虽然改变数值取值范围增加了分类器的复杂度,但为了得到准确结果,我们必须这样做。

import numpy as np
def autoNorm(dataSet):minVals = dataSet.min(0)maxVals = dataSet.max(0)ranges = maxVals - minValsnormDataSet = zeros(shape(dataSet))m = dataSet.shape[0]normDataSet = dataSet - tile(minVals, (m, 1))normDataSet = normDataSet/tile(ranges, (m, 1))   # element wise dividereturn normDataSet, ranges, minValsif __name__ == '__main__':#打开的文件名filename = "datingTestSet.txt"#打开并处理数据datingDataMat, datingLabels = file2matrix(filename)normDataSet, ranges, minVals = autoNorm(datingDataMat)print(normDataSet)print(ranges)print(minVals)

运行代码,结果如下:

根据运行结果得出,我们已经得出了数据的取值范围和数据的最小值。

2.4 测试算法:验证分类器

接下来将要测试分类器的效果,若分类器的正确率满足要求,海伦就可以用这个软件来处理约会网站提供的名单了。

def datingClassTest():filename = "datingTestSet.txt"datingDataMat, datingLabels = file2matrix(filename)hoRatio = 0.10normMat, ranges, minVals = autoNorm(datingDataMat)m = normMat.shape[0]numTestVecs = int(m * hoRatio)errorCount = 0.0for i in range(numTestVecs):classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :],datingLabels[numTestVecs:m], 4)print("the classifier came back with :%d\t the real answer is :%d" % (classifierResult, datingLabels[i]))if classifierResult != datingLabels[i]:errorCount += 1.0print("错误率:%f%%" % (errorCount/float(numTestVecs)*100))

根据运行结果分析,该分类器处理约会数据集的错误率为4.0%,接下来我们可以改变函数 内变量和变量k的值,检测错误率是否随着变量值的变化而增加。依赖于分类算法、数据集和程序设置,分类器的输出结果可能有很大的不同。

2.5 使用算法:构建完整可用系统

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了