《机器学习实战》kNN算法及约会网站代码详解
发布日期:2022-04-01 13:25:19
浏览次数:25
分类:博客文章
本文共 4775 字,大约阅读时间需要 15 分钟。
使用kNN算法进行分类的原理是:从训练集中选出离待分类点最近的 个点,在这 个点中所占比重最大的分类即为该点所在的分类。通常 不超过
kNN算法步骤:
- 计算数据集中的点与待分类点之间的距离
- 按照距离升序排序
- 选出距离最小的 个点
- 计算这 个点所在类别出现的频率(次数)
- 返回出现频率最高的点的类别
代码的实现:
首先导入numpy
模块和operator
模块,建立一个数据集
from numpy import *import operatordef createDataSet(): group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) labels = ['A', 'A', 'B', 'B'] return group, labels
kNN算法的核心代码
# inX-用于分类的输入向量;dataSet-训练样本集;labels-标签向量;k-选择最近邻居的个数# 实现kNN算法def classify0(inX, dataSet, labels, k): # shape返回各个维度的维数,shape[0]表示最外围的数组的维数,shape[1]表示次外围的数组的维数,数字不断增大,维数由外到内。 # 例如:二维数组中,shape[0]表示行数,shape[1]表示列数 dataSetSize = dataSet.shape[0] # tile([n1,n2](a,b))表示在行的方向上重复[n1,n2]a次,在列的方向上重复b次 # 两个矩阵大小相同的矩阵相减 diffMat = tile(inX, (dataSetSize, 1)) - dataSet # 对应位置的元素直接相乘 # 如果需要矩阵乘法,使用dot(a,b) sqDiffMat = diffMat ** 2 # sum(axis=1)表示按行(第二维度)相加,axis=0表示按列(第一维度)相加 # 此处得到inX到dataSet各点的距离的平方 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances ** 0.5 # 升序排序后返回其下标 sortedDistIndicies = distances.argsort() classCound = {} for i in range(k): # 当前点的标签 voteIlabel = labels[sortedDistIndicies[i]] # 将点的标签数+1 classCound[voteIlabel] = classCound.get(voteIlabel, 0) + 1 # 将字典分解成元组列表,并按照第二个元素进行降序排序 sortedClassCount = sorted(classCound.items(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0]
使用K-近邻算法改进约会网站的配对效果
数据集的处理
首先我们需要处理数据集,将其转换成训练样本矩阵和类标签向量
约会网站的数据集对应的文件名是datingTestSet2.txt
,每列对应的标签分别是:每年获得的飞行常客里程数;玩视频游戏所耗时间百分比;每周消费的冰淇淋公升数;属于哪一类型的人
# 将文本记录转换成Numpy的解析程序def file2matrix(filename): fr = open(filename) arrar0Lines = fr.readlines() # 获得文件行数 number0fLines = len(arrar0Lines) # 创建一个number0fLines行3列的全是0的矩阵 retrunMat = zeros((number0fLines, 3)) classLabelVector = [] index = 0 for line in arrar0Lines: line = line.strip() listFromLine = line.split('\t') # 选取每行的前三个元素放入returnMat中 retrunMat[index, :] = listFromLine[0:3] # 将所属类别放入classLabelVector classLabelVector.append(int(listFromLine[-1])) index += 1 return retrunMat, classLabelVector
使用Matplotlib创建散点图
在命令行环境中,输入:
import kNNfrom numpy import *import matplotlibimport matplotlib.pyplot as pltdatingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')# 创建一个画布fig=plt.figure()# 111的含义是将画布分割成1行1列,画像在从左到右,从上到下第一块ax=fig.add_subplot(111)# 以第二列和第三列为x,y轴画出散列点,给予不同的颜色和大小# scatter(x,y,s=1,c="g",marker="s",linewidths=0)# s:散列点的大小,c:散列点的颜色,marker:形状,linewidths:边框宽度ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))plt.show()
此时,可以得到数据集的散点图:(横坐标是玩视频游戏所耗时间百分比
,纵坐标是每周消费的冰淇淋公升数
)
归一化数据
可以看出,在计算点的距离时,里程数对于距离的影响特别大,为了减小这个影响,需要将所有的数据范围处理到 到 或 到 之间,利用下面的公式,可以实现将特征值转化为 区间内的值:
代码如下:# 归一化特征值def autoNorm(dataSet) # 按列查找最大值和最小值 minVals = dataSet.min(0) maxVals = dataSet.max(0) ranges = maxVals - minVals # 创建一个和dataSet大小相同的全是0的数组 normDataSet = zeros(shape(dataSet)) m = dataSet.shape[0] # 获得值为oldValue-min的数组 normDataSet = dataSet - tile(minVals, (m, 1)) # 归一化的数组 normDataSet = normDataSet / tile(ranges, (m, 1)) return normDataSet, ranges, minVals
分类器针对约会网站的测试代码
使用数据集中的 的数据作为测试数据,剩余的 作为数据集
# 对于数据的测试# 选出10%作为测试数据,剩余90%作为数据集def datingClassTest(): hoRatio = 0.10 datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] # 获得测试数据的组数 numTestVecs = int(m * hoRatio) errorCount = 0.0 for i in range(numTestVecs): classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])) if (classifierResult != datingLabels[i]): errorCount += 1.0 print("the total error rate is: %f" % (errorCount / float(numTestVecs)))
约会网站预测函数
def classifyPerson(): resultList = ['not at all', 'in small doses', 'in large doses'] percentTats = float(input("percentage of time spent palying video games?")) ffMiles = float(input("fregunt flier miles earned per year?")) iceCream = float(input("liters of ice cream consumed per year?")) datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') normMat, ranges, minVals = autoNorm(datingDataMat) inArr = array([ffMiles, percentTats, iceCream]) classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3) print("You will probably like this person: ", resultList[classifierResult - 1])
转载地址:https://www.cnblogs.com/Friends-A/p/11054970.html 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2024年04月08日 07时39分53秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
虚拟机ping不通主机,但是主机可以ping通虚拟机
2019-04-25
idea中创建maven文件时,maven路径是自己设置的
2019-04-25
使用FFmpeg将pcm数据编码为aac
2019-04-25
使用FFmpeg将S16格式音频数据重采样为FLTP格式
2019-04-25
推荐系统实践学习系列(七)推荐系统实例
2019-04-25
推荐系统实践 学习总结
2019-04-25
Python3 Flask+nginx+Gunicorn部署(下)
2019-04-25
python 爬取fcoin比特币交易市场
2019-04-25
python 爬取fcoin比特币交易市场 下文
2019-04-25
python scrapy爬取全部豆瓣电影(可能是54万数据)
2019-04-25
centos7 安装jdk1.8
2019-04-25
python3调用js的库之execjs
2019-04-25
python3 爬取36氪新闻网页
2019-04-25
程序员个性注释专属(保存下)
2019-04-25
广州八月份面试(一篇为断更写抱歉的小总结)
2019-04-25
mysql表复制操作
2019-04-25
【Android面试题】Activity的生命周期
2019-04-25
【Android面试】Activity的四种启动模式
2019-04-25