机器学习系列-K-NearestNeighbo



这是记录自学的过程,目前的理论基础就是:大学高等数学+线性代数+概率论。编程基础:C/C++,python

在观看机器学习实战这本书,慢慢介入。相信有读过以上三门课的人完全可以开始自学机器学习了,当然我上面这三门课学的一般,所以你只知道有这么一个公式或名词,不懂可以百度之深究之。在写这篇文章的时候作者机器学习还没学完,故文章中的错误还请不吝指出。再次声明,系列文章只是分享学习过程,学习点滴,不能保证文章的技术含量。后续再技术的不断完善中,我会重新再捋一遍这个学习过程,纠正其中错误。

目前的学习方法如下:

理论:斯坦福Andrew NG machine learning,系列课程。

代码实战:引用书籍 机器学习实战(python)。

真枪实战: 研究一个案例,建模选择合适的机器学习算法,分析数据。

演变:基于C/C++ 在linux下实现部分机器学习过程。将在学习中期阶段去实现。


一、K近邻算法的概念



 K近邻算法(kNN)属于一种分类的算法,与逻辑回归属于同一种。它的工作原理是:存在一组样本数据,它们的每一个样本的组成由若干个特征和一个既定的label与之对应,label也就是标明了这个样本点属于哪个分类,如果是简单的二元分类,那么label可以假设为1或0,以此类推。如果输入新的数据,而算法的目的就是输出新的数据的标签。这个新的数据将会和样本集合中的每个数据进行对比(求两个样本点之间的距离),对比的结果从小排到大,取前k个对比结果,当中出现次数最多的分类就是该新数据的分类。



近邻算法的优缺点:

1.优点:

精度高,对异常值不敏感,无数据输入的假定

2.缺点:

计算复杂度高,空间复杂度高。

3.使用数据范围:

数值型和标称型。

二、k近邻算法简单例子

伪代码:

1.计算样本集合中的已知点与当前点之间的距离

2.按照距离递增的顺序排序

3.选择排序中与当前点距离最近的前k个样本数据

4.计算出每个分类的样本个数并计算频率

5.返回k个点中出现频率最高的点的分类类别作为当前点的预测分类。

下面看一下这个简单的例子说明是如何求两点之间的欧氏距离的:

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (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.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

==深入分析:==

1.dataSetSize = dataSet.shape[0].计算出dataSet 矩阵的行数。

2.diffMat = tile(inX, (dataSetSize,1)) - dataSet 这边主要是将输入数据分别与样本进行相减,这边pyth tile的用法我用自己的理解总结了一下:



上网查了下tile用法的教程,发现看的有点吃力,于是自己亲自研究了一下然后发现可以这理解,与大家分享一下,有什么错误的地方请大家指出:

1.tile的用法总结:

定义:tile(A,R),A和R都可以是数组或者普通单个数据。结果是将A重复R,具体有以下几种机制:

假设:

tile([a1,a2,…,an],[r1,r2,…,rn])=B

得到的结果B的一些属性是由R来决定的,B的第一维数就是r1,第二维数就是r2,…..,B的每一维由重复A数组rn遍的结果组成。当R的长度为1时(类似(1,2)长度2,(1,2,3)长度3,(3)长度为1),此时R控制维数。

例子1.

tile([1,2],2)=

array([1,2],

   [1,2]);

tile([1,2],4)=

array([1,2],

[1,2],

[1,2],

[1,2]);

tile([1,2],(1,2))= //1决定结果只是一维,2决定重复A(1,2)两遍

array([[1,2,1,2]])

tile([1,2],(3,3))= //3决定结果是三维,后面的三决定将重复(1,2)三遍

array([[1,2,1,2,1,2],

[1,2,1,2,1,2],

[1,2,1,2,1,2]])

tile([1,2],(2,2,2)) //第一个2决定结果将是一个2维,第二个2决定2为中的每一维都是一个2维,最后一个2决定最里面的维度的元素将是重复两遍A(1,2)的结果,层层嵌套。

结果:

array([[[1, 2, 1, 2],

    [1, 2, 1, 2]], //这里是维度分界线,注意中括号个数

   [[1, 2, 1, 2],
    [1, 2, 1, 2]]])

以此类推。


3.sqDiffMat = diffMat**2 //把刚才得到的结果求平方
4.sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5  //这两句的意思是将求平方后的结果相加,然后结果开方
5.sortedDistIndicies = distances.argsort()  //把求到的输入数据和每个点之间的距离进行递增排序,argsort返回的是每个数据的index。

6.for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
        //总体的作用选取距离最小的K个点。for循环中的第一句:sortedDistIndicies[i]记录着一排index比如(2,3,0,1)
        //2代表dataSet中的index为2的数据距离输入数据距离最短,以此类推,1代表最长。由于dataSet和labels是对应
        //的,所以当i从0>>k时,会找到最小的那几个数据所对应的lable值。第二行就进行对这些label进行分类计数,并
        //保存在classCount中  

7.sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
//以上是对一个有多个类型的数据进行排序的函数,总之作用就是把刚才得到的保存有距离最短的k个数据中每一个label出现
//个数的数组进行从大到小排序,最后结果被保存在sortedClassCount中,第一个元素就是前K个数据中频率最高的label  sortedClassCount[0][0]  ,关于sorted的用法详见附录1.

三、k近邻算法的实际应用-约会网站的预测

背景我就不细细描述了,总之目的就是输入一个数据,这个数据包含三个特征:1.每年获得的飞行常客里程数2.玩视频游戏所耗时间百分比3.每周消费的冰淇淋公升数。通过这三个特征对数据进行分类,当然原理还是计算这个数据和其他数据的距离,不同的是这次是三维空间中的距离了。

1.第一步:解析数据。

我们先看下数据的特点:

第一列是飞行里程数,第二列是游戏时间所占百分比,第三列是吃冰淇淋的公升数。第四列是lable值,有三种:不喜欢,魅力一般,极具魅力。书中提供了解析数据的代码,目的就是把这些数据规律性的输入到一个数组中,方便后面处理,具体代码:


def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split(‘\t‘)
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector


上面代码运行过程如下:

输入:datingDataMat,dataingLabels = kNN.file2matrix(‘datingTestSet2.txt’) 记住这边参数是datingTestSet2.txt,书本那种会报错误:

==ValueError: invalid literal for int() with base 10: ‘largeDoses’ ==

然后在看看换算的结果:

datingDataMat:

label的结果:

这样子数据就从文件导成我们需要的格式了,后面就开始用算法来处理这些数据。

2.第二步:归一化数值:

如上图数据所示第一列数据与后面两列差了10的4次方级别,这会导致在求点和点的距离的时候,加减运算时,第二第三列的数据影响效果大大减小,甚至不起作用。所以这边要把所有数据之按照一定的计算方式归一化到0-1之间,这样数据之间的加减运算才会有意义。

下面的公式可以将数据转化到0-1之间:

newValue = (oldValue - minValue)/(maxValue - minValue)

其中minValue和maxValue分别是数据中的最小值和最大值。

用python代码实现如下:

def autoNorm(dataSet):
    minVals = dataSet.min(0) //获得dataSet中每列的最小值保存到minVals
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1)) //oldValue-minValue
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals

运行结果如下:

3.第三步:测试算法

直接撸代码:

def datingClassTest():
    hoRatio = 0.10      #hold out 10%
    datingDataMat,datingLabels = file2matrix(‘datingTestSet2.txt‘)       #load data setfrom file
    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))

前面两句主要是从文件加载数据然后再进行归一化转换。m = normMat.shape[0] 算出来的是数据的总个数,后面取出的测试数据的个数就是由 numTestVecs = m*hoRatio ,这边hoRatio为0.1也就是说测试数据取10%。然后将测试数据和已有的数据还有label值分别输入分类器classfy0中,这个函数前面已经分析过。这边输入的第一个参数为待测试的数据:normMat[i,:],这个表达式的意思是取normMat的第i行数据,直到numTestVecs比如:

normMat[0,:]

array([ 0.44832535, 0.39805139, 0.56233353])

normMat[1,:]

array([ 0.15873259, 0.34195467, 0.98724416])

第二个参数:datingLabels[numTestVecs:m],表示一直数据从第numTestVecs行开始取知道结尾,前面的都是待测数据。

下面是运行的结果:

可以看到最后的错误率是6.4%,这是一个不错的结果。在此,我们可以通改变hoRotio和变量k的值,来观察错误率的变化情况。

上述只是测试算法,数据直接从现有的数据中取出来的,下面构建完整的算法系统:

下面是完整代码:

def classifyPerson():
    resultList = [‘not at all‘,‘in small doses‘,‘in large doess‘]
    percentTats = float(raw_input("percentage of time spent playing video games?"))
    ffMiles = float(raw_input("frequent flier miles earned per year?"))
    iceCream = float(raw_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]

第一行是标签数组化,有三个类别。

2-4行 分别要求输入玩游戏占用时间比、飞行里程数、消费冰淇淋公升数。

接下来两行就是将数据从文件中转化出来并归一化保存的过程。

最后就是输入分类器进行分类,返回分类结果。

下面是运行结果:

附录1:

sorted

sorted函数

Python内置的排序函数sorted可以对list或者iterator进行排序,官网文档见:http://docs.python.org/2/library/functions.html?highlight=sorted#sorted,该函数原型为:

sorted(iterable[items[], cmp, key, reverse)

参数解释:

(1)iterable指定要排序的list或者iterable,不用多说;

(2)cmp为函数,指定排序时进行比较的函数,可以指定一个函数或者lambda函数,如:

  students为类对象的list,没个成员有三个域,用sorted进行比较时可以自己定cmp函数,例如这里要通过比较第三个数据成员来排序,代码可以这样写:
  students = [(‘john‘, ‘A‘, 15), (‘jane‘, ‘B‘, 12), (‘dave‘, ‘B‘, 10)]
  sorted(students, key=lambda student : student[2])

(3)key为函数,指定取待排序元素的哪一项进行排序,函数用上面的例子来说明,代码如下:

sorted(students, key=lambda student : student[2])

  key指定的lambda函数功能是去元素student的第三个域(即:student[2]),因此sorted排序时,会以students所有元素的第三个域来进行排序。

有了上面的operator.itemgetter函数,也可以用该函数来实现,例如要通过student的第三个域排序,可以这么写:

sorted(students, key=operator.itemgetter(2))

sorted函数也可以进行多级排序,例如要根据第二个域和第三个域进行排序,可以这么写:

sorted(students, key=operator.itemgetter(1,2))

即先跟句第二个域排序,再根据第三个域排序。

(4)reverse参数就不用多说了,是一个bool变量,表示升序还是降序排列,默认为false(升序排列),定义为True时将按降序排列。

时间: 2024-10-01 12:19:33

机器学习系列-K-NearestNeighbo的相关文章

机器学习系列(6)_从白富美相亲看特征预处理与选择(下)

作者:viewmode=contents">龙心尘 &&寒小阳 时间:2016年1月. 出处: http://blog.csdn.net/longxinchen_ml/article/details/50493845. http://blog.csdn.net/han_xiaoyang/article/details/50503115 声明:版权全部,转载请联系作者并注明出处 1. 剧情一:挑螃蟹的秘密 李雷与韩梅梅的关系发展得不错.趁国庆休假一起来天津玩. 今天,李雷十分

Spark2.0机器学习系列之8: 聚类分析(K-Means,Bisecting K-Means,LDA,高斯混合模型)

在写这篇文章之前,先说一些题外话. 许多机器学习算法(如后面将要提到的LDA)涉及的数学知识太多,前前后后一大堆,理解起来不是那么容易. 面对复杂的机器学习模型,尤其是涉及大量数学知识的模型,我们往往要花费大量的时间和精力去推导数学算法(公式),如果过分沉湎于此会忽略了很多背后也许更重要的东西,正所谓只见树木,不见森林,而这是缺乏远见,是迷茫的. 我们需要深入理解模型背后的逻辑和所蕴含的或简或繁的思想.某些思想甚至可能是很美的思想,很伟大的思想.这些理解,使得面对复杂的问题时候,面对陌生问题时,

spark机器学习系列:(三)用Spark Python构建推荐系统

上一篇博文详细介绍了如何使用Spark Python进行数据处理和特征提取,本系列从本文开始,将陆续介绍用Spark Python对机器学习模型进行详细的探讨. 推荐引擎或许是最为大众所知的一种机器学习模型.人们或许并不知道它确切是什么,但在使用Amazon.Netflix.YouTube.Twitter.LinkedIn和Facebook这些流行站点的时候,可能已经接触过了.推荐是这些网站背后的核心组件之一,有时还是一个重要的收入来源. 推荐引擎背后的想法是预测人们可能喜好的物品并通过探寻物品

机器学习系列-Logistic Regression(1)

机器学习 这是记录自学的过程,目前的理论基础就是:大学高等数学+线性代数+概率论.编程基础:C/C++,python在观看机器学习实战这本书,慢慢介入.相信有读过以上三门课的人完全可以开始自学机器学习了,当然我上面这三门课学的一般,所以你只知道有这么一个公式或名词,不懂可以百度之深究之.在写这篇文章的时候作者机器学习还没学完,故文章中的错误还请不吝指出.再次声明,系列文章只是分享学习过程,学习点滴,不能保证文章的技术含量.后续再技术的不断完善中,我会重新再捋一遍这个学习过程,纠正其中错误. 目前

机器学习系列(7)_机器学习路线图(附资料)

作者: 龙心尘 && 寒小阳 时间:2016年2月. 出处:http://blog.csdn.net/longxinchen_ml/article/details/50749614 http://blog.csdn.net/han_xiaoyang/article/details/50759472 声明:版权所有,转载请联系作者并注明出处 1. 引言 也许你和这个叫『机器学习』的家伙一点也不熟,但是你举起iphone手机拍照的时候,早已习惯它帮你框出人脸:也自然而然点开今日头条推给你的新闻

Spark 机器学习系列(一):入门介绍

前言 最新的情况是国内BAT已经都上了spark,而且spark在hadoop上的应用,大有为大象插上翅膀的效果.个人估计在未来两到三年,spark大有代替hadoop的mapreduce的趋势.应该说spark的在使用上面的经济成本,性能优势,一站式解决能力,一定会使其大放异彩. 因为个人对spark很感兴趣,加上项目中需要使用它解决一些机器学习的问题,在网上搜集资料时发现,spark machine learning这块的资料确实太缺少了,所以决定写一spark machine learni

机器学习系列(9)_机器学习算法一览(附Python和R代码)

本文资源翻译@酒酒Angie:伊利诺伊大学香槟分校统计学同学,大四在读,即将开始计算机的研究生学习.希望认识更多喜欢大数据和机器学习的朋友,互相交流学习. 内容校正调整:寒小阳 && 龙心尘 时间:2016年4月 出处:http://blog.csdn.net/han_xiaoyang/article/details/51191386 http://blog.csdn.net/longxinchen_ml/article/details/51192086 声明:版权所有,转载请联系作者并注

机器学习系列1-学习资料和学习路线

该系列是学习机器学习的系列博客,主要用于记录和分享学习机器学习(和深度学习)过程中的各种知识和问题,希望能够将自己学习到的知识.方法论转化为文字,分享给更多有志于从事机器学习相关工作或学习的同学. 学习资源 目前网上关于机器学习的资源已经非常丰富,现在分享笔者学习过程中接触到的学习资源: 书籍: <机器学习>-周志华 链接:http://pan.baidu.com/s/1bo7j7SN 密码:47wi<Deep Learning>-花书 链接:http://pan.baidu.co

机器学习系列(17)_Yelper推荐系统

原文地址:yelper recommendation system 原文翻译与校对:@酒酒 && @寒小阳 时间:2016年10月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/52778321 声明:版权所有,转载请联系作者并注明出 1. 我们为什么需要推荐系统? "推荐"可是个当红话题.Netflix愿意用百万美金召求最佳的电影推荐算法,Facebook也为了登陆时的推荐服务开发了上百个项目,遑论现在市场