赞
踩
前面的一篇文章介绍了KNN算法的基本思想,接下来我们就根据B站UP主【abilityjh】老师的节奏,做一个关于KNN算法运用于“约会网站配对”的算法实现。当然,这个实践的代码是一样的,但是理解的话,我是用自己的话来阐述自己敲完这个算法后的理解,可能更多的是一些大白话,大家也可以去看这个老师的原视频,会有很多收获哦!
文本数据:
案例描述:我们需要通过这个DataText.txt文档中的数据来测试我们KNN的准确性,该文档有1000条数据,我们把其中一部分拿来做训练集,另一部分拿来做测试集,结合我们的KNN算法就可以来测试KNN算法的准确性。
如图所示:我们先用将我们txt中的文本数据,转化为对应信息的矩阵或者列表,然后我们通过txt中的数据发现“里程数”的数据比其他两项的数据大了很多,如果这样来求未知点和训练数据中点的距离的话,后两项数据太小基本,没有作用,所以这里我们通过0-1标准化对里程数据做归一化处理;然后我们把之前写的KNN算法封装成一个函数调用,再测试KNN准确性即可。(PS:虽然流程简单,但是代码实现过程中还是有很多坑!)
- def file2matrix(filename):
- fr = open(filename)
- numberOfLines = len(fr.readlines())
- # 定义一个numberOfLines行,3列的零矩阵
- # 一定要加两个括号
- returnMat = np.zeros((numberOfLines, 3))
- # 标签向量
- classLabelVector = []
- fr.close()
- fr = open(filename)
- index = 0
- for line in fr.readlines():
- # 去掉每一行的前后空格
- line = line.strip()
- # 根据tab将数据切割出来,listFromLine就成了一个字符串列表
- listFromLine = line.split("\t")
- # listFromLine[0:3]将listFromLine的前三列赋值给returnMat[]数组,因为returnMat有numberOfLines行,就会执行numberOfLines次操作
- returnMat[index, :] = listFromLine[0:3]
- # listFromLine[-1]表示最后一列
- if listFromLine[-1] == 'didntLike':
- classLabelVector.append(1)
- elif listFromLine[-1] == 'smallDoses':
- classLabelVector.append(2)
- elif listFromLine[-1] == 'largeDoses':
- classLabelVector.append(3)
- index += 1
- fr.close()
- return returnMat, classLabelVector
-
-
- datingDataMat, datingLabels = file2matrix("D:/python工具/素材处/KNN(二)/DataText.txt")
- print(datingDataMat)
- print(datingLabels)
在这段代码中,我觉得最重要的几个点就是:文件读取、对每行数据处理(确保能分割成矩阵或者列表!)。代码的理解,我都打上了注释,大家可以仔细看看。
效果:
从上面的数据,可以看出里程数的数值是很大的,然后我们用0-1标椎化做处理,将里程数的每个数据缩小在0~1之间。
- # 数据归一化处理
- # 0-1标注化
- def autoNorm(dataSet):
- # min(0)按特征的列选取,min(1)按照特征的行选取
- minVals = dataSet.min(0)
- maxVals = dataSet.max(0)
- # shape记录了dataSet的行和列
- normDataSet = np.zeros(dataSet.shape)
- normDataSet = (dataSet - minVals) / (maxVals - minVals)
- return normDataSet
-
- dataSet = autoNorm(datingDataMat)
- print(dataSet)
- print(datingLabels)
效果:
代码原理上一篇博客已经介绍
- # inX输入数据,dataSet测试数据,labels标签,k最近的点的个数
- def knn(inX, dataSet, labels, k):
- dist = (((dataSet - inX) ** 2).sum(1)) ** 0.5
- sortdDist = dist.argsort()
- classCount = {}
- for i in range(k):
- voteLabel = labels[sortdDist[i]]
- classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
- maxType = 0
- maxCount = -1
- for key, value in classCount.items():
- if value > maxCount:
- maxType = key
- maxCount = value
- return maxType
- m = 0.8
- # shape[0]表示行、shape[1]表示列
- dataSize = dataSet.shape[0]
- print("数据集的总行数:", dataSize)
- # 80%作为训练 20%作为测试
- trainSize = int(m * dataSize)
- testSize = int((1 - m) * dataSize)
- k = 5
- result = []
- error = 0
- # 调用封装好的KNN函数
- for i in range(testSize):
- # dataSet[trainSize + i - 1, :]表示dataSet矩阵中的第trainSize + i - 1行元素(包含对应的所有列)
- # dataSet[0:trainSize, :]表示一个从0~trainSize行,包含对应所有列的矩阵
- # datingLabels[0:trainSize]表示截取列表datingLabels中的0~trainSize个元素
- result = K.knn(dataSet[trainSize + i - 1, :], dataSet[0:trainSize, :], datingLabels[0:trainSize], k)
- # result != datingLabels[trainSize + i - 1]表示通过KNN算法得到的result是否与原来的datingLabels中对应下标为trainSize + i - 1是否相等
- if result != datingLabels[trainSize + i - 1]:
- error += 1
-
- print('错误率:', error / testSize)
这段代码中,我觉得对新手来说最不好理解的就是for循环中的dataSet矩阵的切片操作,我自己也是下来梳理了一下,才通顺起来,相应代码的注解放在代码中了,大家自己取用。
效果:
可见,我们1000条数据,用80%做训练集,20%做测试集,K选用为5用使用KNN算法的出错率,只有5.52%,其实还是可以的。(大家也可以改变数据,再测试一下)
PS:当然KNN算法的优缺点以及使用场景,就不止这些,大家可以下来好好探索一番,我这里就主要梳理一下代码啦!
博主作为一个新手,才开始学习机器学习而言,我觉得这篇关于KNN算法的实践,对自己帮助挺大的,让我学到了以下很多知识:
①关于文件数据的读取;
②数据的处理、归一化;
③函数的封装调用;
④矩阵和列表的一些切片操作;
最后,如果这篇文章对大家有所帮助,别忘了点赞、关注支持博主一波哦~,你们的助力,就是我持续更新的动力!
PS:如果有需要这个DataText.txt数据集的小伙伴,直接私信我,即可发送。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。