机器学习笔记(3)---K-近邻算法(1)---约会对象魅力程度分类

本文介绍了K-近邻(KNN)算法,通过实践应用在约会对象魅力程度分类上,详细讲解了算法原理、代码实现及测试过程。通过计算新数据与样本数据的距离,选取最近的k个数据确定新数据类别。文章还探讨了距离计算、归一化处理和算法准确性评估等关键点。
摘要由CSDN通过智能技术生成

参考资料

《机器学习实战》,Machine Learning in Action,本文中简称MLiA
《机器学习》周志华,本文简称西瓜书
《Web安全之机器学习》刘焱著,本文中简称WSML(Web Security in Machine Learning,该英文翻译只为记录方便,是本人杜撰的,仅限本系列文章使用)

转载请注明出处:http://blog.csdn.net/rosetta/article/details/79179004

前言

因为之前不知道怎么把机器学习的知识用起来,所以心理很没底,看了近一年的数学基础,感觉也没有什么长进,而看了《机器学习实战》第2章k-近邻算法后发现,原来机器学习也可以这么简单。
本算法真不需要什么高深的数学公式,只要会一些基础的矩阵知识就可以了。代码里Numpy ndarray相关的东西看起来挺复杂的,但打出来调试后也就不会觉得难了。
另外我发现了自己学习的方法(其实原来也发现了,只是没总结),先跟着书把代码敲一遍(或者直接复制粘贴),这个时候不要去看书上关于代码的解释,因为看不懂,看不懂会影响学习心情,所以不要看。先把代码运行一遍看结果,运行成功后再看不理解的代码,边看边调试,比看书本上关于代码的解释效果好多了。

本次学习以实践为主,理论为辅。为了加深对KNN算法的理解,我学了以下内容,虽然很多,但我相信如果大家对以下内容都理解了,那么KNN算法也就掌握了。主要内容有以下五,我会分五篇文章完成学习记录。

  1. 使用KNN算法对约会对象魅力程度分类
  2. 使用sklearn库中的KNN算法对约会对象魅力程度分类
  3. 使用KNN算法完成手写识别系统
  4. 使用KNN算法完成西瓜分类
  5. 使用KNN算法检测Linux系统异常操作

本篇文章先描述K-近邻算法核心思想,再记录使用KNN算法对约会对象魅力程度分类的代码的理解。

K-近邻算法

所谓的k-近邻算法(K-Nearest Neighbor,简称KNN)是这样的,首先要有一批已知的样本数据的特征(比如MLiA举的交友例子,交友对象的年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数),并且知道这些数据的标签(不喜欢的人、魅力一般的人和极具魅力的人),然后输入不带标签的新数据(知道这个人的年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数,但不知道它属于哪一类),拿这个新数据和样本数据比较,算出和新数据最相似的k个数据(k可自定义),然后看这k个数据中出现最多的类型,新数据就属于这一类。
所以整体思想是很简单的,但这里面会延伸出三个问题:
1. 新数据和样本数据距离计算公式是怎样的?
2. 如果某一项属性数据太大,这样在计算距离时其它属性就不起作用了,但是其它属性也是一样重要的,那怎么办?这就需要做归一化处理。
3. 如何测试算法的准确性。这里会拿样本数据的前x%用于作为直接的样本(因为k-近邻算法没有训练数据概念,这里姑且叫它训练数据),后面的1-x%数据拿来测试(叫测试数据)。

相关概念

本节内容可先跳过,如后续看的不明白可回来查看相关概念。
KNN算法中的训练数据和一般意义上的训练数据不太一样。因为在KNN中实际上是不需要训练数据的,只需要知道一些已知的带标签的数据就可以了,后续新来的数据只要和这些已知标签的数据做运算就可以了。

所以这里的相关解释如下:

  • 样本数据

    所有带标签的数据。其中一部分拿来用做训练数据(比如80%),一部分拿来当测试数据(比如剩下的20%)。

  • 训练数据

    带标签的标本数据,实际上是给KNN算法本身使用的。当测试数据或待预测数据来了时和这些数据做运算使用。

  • 测试数据

    测试数据也是带标签的,是在样本数据中预留出来的,用以检测算法正确率的。当算法已经设计好后,给算法传入这些测试数据,然后取得算法返回的预测结果,并把这些预测结果和已知的标签做对比,从而计算出算法的正确率。

使用KNN算法对约会对象魅力程度分类

先来看下最终效果,有一个直观的认识。

最终效果

最终效果如下。输入年飞行里程、玩游戏占的时间比和周消费的冰淇淋公升数,程序输出这个人的魅力程度。
最终效果

代码分析

代码分析请直接看注释。

def classifyPerson():
    resultList = ['没有魅力', '魅力一般', '极具魅力']
    ffMiles = float(input("每年飞行公里数?"))
    percentTats=float(input("打游戏耗费时间的百分比?"))
    iceCream = float(input("每周消费的冰激凌?"))

    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = np.array([ffMiles,percentTats,iceCream])
    classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)
    print("这个人:", resultList[classifierResult-1])

#从文件中获取数据,并格式化成Numpy数组。
#returnMat[]数组用于存放样本的属性。
#classLabelVector[]用于存放样本的类别
def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #1000
    returnMat = np.zeros((numberOfLines,3))        #创建numberOfLines行,3列矩阵,初始化为0.
    classLabelVector = []                       #用于存放第四列的的值。
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3] #因为index是会自增的,所以数据会往returnMat上增。
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector
# returnMat={ndarray} [[  4.09200000e+04   8.32697600e+00   9.53952000e-01]
#  [  1.44880000e+04   7.15346900e+00   1.67390400e+00]
#  [  2.60520000e+04   1.44187100e+00   8.05124000e-01]
#  ...,
#  [  2.65750000e+04   1.06501020e+01   8.66627000e-01]
#  [  4.81110000e+04   9.13452800e+00   7.28045000e-01]
#  [  4.37570000e+04   7.88260100e+00   1.33244600e+00]]
#classLabelVector={list}[3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1,……]


#归一化处理公式:newValue=(oldValue-min)/(max-min)
def autoNorm(dataSet):
    #dataSet是1000行3列的数据。
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges =
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值