机器学习实战入门篇之二:kNN算法 | 她是不是你喜欢的类型?

她是不是你喜欢的类型.jpg

通过本篇博文,你可以学习到:

  1. 环境搭建,主要为python,numpy,以及matplotlib库的搭建等;
  2. k-近邻算法;
  3. k-近邻算法实战练习,使用k-近邻算法判断某个同学是不是你喜欢的类型。

理论与实战的结合,赶快打起精神,一起来学习吧!吼吼吼~~~

环境搭建

  • python:开发语言,使用广泛, 简单易学
  • NumPy:科学计算库文件,它实现了大量的向量和矩阵操作,在python中我们可以像在matlab里面一样编写非常简单易读矩阵操作代码。
  • matplotlib:绘图库文件,在python中我们可以像在matlab里面一样,方便的实现绘图功能。

python###

  1. 下载python安装文件
    https://www.python.org/downloads/ 上下载相应平台的python安装文件,本文采用的python版本为windows平台的python 2.7。下载后,点击安装,一路next。

  2. 添加环境变量
    右键“我的电脑”——属性——系统高级设置——高级——环境变量,在系统变量中找到Path,编辑此变量在后面追加 ;C:\Python27\ (python安装位置,每个人都可能不一样哦,注意前面的分号)。

  3. 如何证明python安装成功?
    打开命令提示符,输入python,能看到所安装python的版本信息即证明安装成功,如下图所示:

python安装成功示意图.png

numpy及matplotlib等库文件安装###

一个一个安装比较麻烦,如果想省事儿的话,建议使用Anaconda进行安装,Anaconda针对的痛点就是一个一个安装这些库会比较麻烦,那么他就帮大家一起集成了。

  1. 下载Anaconda安装文件
    https://www.continuum.io/downloads 下载相应版本的安装文件,双击安装即可,一路next。

  2. 环境变量设置
    Anaconda安装的过程中,会自动在path下面添加相关的环境变量,所以这步跳过。

  3. 如何证明Anaconda已经安装成功?
    在cmd里面,输入conda list可以查看Anaconda已经帮大家安装的库,如下图所示。

Anaconda安装成功示意图.png

可以自己看下我们所需要用到的numpy及matplotlib库文件也在包含在里面。

4.如何证明numpy及matplotlib已经安装成功?

numpy正常使用示意图.png
matplotlib正确安装示意图_代码.png
使用matplotlib画图.png

如上图所示,就表示能够正常的使用numpy及matplotlib。

爬过的坑###

  1. 单独下载numpy包,然后cd到相应的路径,使用python setup.py install安装numpy,报错“failed with exit status 1120”,如下图所示:
    爬过的坑1.png

产生问题的原因及解决办法:版本原因,python版本为2.7,numpy下载的版本为1.11,后来使用Anaconda下载的匹配的版本是1.10。解决方法是使用Anaconda安装。

2.安装完Anaconda之后,import matplotlib的时候,提示"no module named matplotlib"。

产生问题的原因:猜想是python无法使用Anaconda安装的库。

解决办法
在python安装目录下的lib\site-packages下面,新建一个文件anaconda.pth,文件的内容是Anaconda安装目录下的site-packages路径。

爬过的坑2.png

3.import matplotlib.pyplot as plt报错“from PyQt4 import QtCore, QtGui ImportError: DLL load failed:找不到指定的程序“,如下图所示

爬过的坑3.png

产生问题的原因:没有安装PyQt4

解决办法:安装PyQt4,下载链接https://riverbankcomputing.com/software/pyqt/download

OK!到这一步为止环境就算搭建好了,下面就开始这篇文章的正题,k-近邻算法。

k-近邻(kNN)算法概述

  • kNN算法原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似(最邻近)的分类标签。一般来说我们只选择数据集中前k个最相似的数据,这就是k-近邻算法的k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

上面写的太复杂了,其实很简单,就是计算距离,根据距离进行分类。举个栗子,吼吼,如下图所示,已知右上角的两个点属于A类,左下角的两个点属于B类,那么给定一个点如图中的小红点,那么他是属于A点还是B点呢?

kNN算法给出的解决方案是,分别计算小红点与每个点的距离,然后将距离从小到大排序,取前k位,如取前2位,如果发现这2位都是B类,那么说明这个小红点也是属于B类。

k近邻算法示例.png
  • kNN算法实现

算法流程

  1. 计算待分类点与已知类别数据集中每个点的距离;
  2. 按照距离递增次序排序;
  3. 选取与待分类点距离最小的k个点;
  4. 确定前k个点类别出现的频率;
  5. 返回前k个点出现频率最高的类别作为当前点的预测分类。

python代码实现

from numpy import *

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]

四不四很简单?吼吼吼~~~

使用k-近邻算法快速判定她是不是你喜欢的类型?

  1. 问题描述
    比如你的朋友经常上约会网站寻找自己的约会对象,你的朋友选定约会对象的时候主要看重三点“每年飞行的旅程数”、“玩游戏所耗时间百分比”、“每个月看书的数目”,你阅人无数的朋友已经约会过很多个对象了,并且把这些对象分为三类“她是我喜欢的类型”、“一般喜欢”,“她不是我喜欢的类型”,经过无数次的约会之后,你的朋友心已经很累了,他想能否输入某人的“每年飞行的旅程数”、“玩游戏所耗时间百分比”、“每个月看书的数目”这三项数据,就能判断她是不是他喜欢的类型呢?

  2. 已有资源
    为了简化问题,我们假设你的朋友,已经整理了一份数据,如下图所示:

    数据.png

    其中前三列分别表示“每年飞行的旅程数”、“玩游戏所耗时间百分比”、“每个月看书的数目”,第四列表示分类。其中“1”表示“她不是我喜欢的类型”、“2”表示“一般喜欢”,“3”表示“她是我喜欢的类型”。

  3. 如何使用kNN算法?
    在前一篇博文机器学习实战入门篇之一:机器学习中必会的基础概念!中,我们介绍了使用机器学习算法解决问题的一般步骤,我们再一次回顾一遍流程图。

开发机器学习应用程序步骤.png

下面我们将一步一步来完成。

  • 收集数据
    为简单起见,已经提供txt文本数据。

  • 数据预处理
    数据预处理中,我们得将txt文本中提供的数据放到矩阵或矢量中进行存储,然后还需要将数据进行归一化。
    (1) 把txt文本中的数据转换成矩阵或矢量进行存储

#函数名:file2matrix
#输入:文件名
#输出:returnMat为txt文本数据的前三列构成的二维数组
 #     classLabelVector为txt文本数据第四列的分类信息的一维矢量
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

(2) 数据归一化
为什么要进行数据归一化?分析下数据可以看出,飞行距离相对于其他两个特征的数据来说通常要大的多,如果不进行数据归一化,那么在计算距离的时候飞行距离对结果的影响占绝对主导性,这显然是不合理的,所以需要进行数据归一化,归一化的python代码如下所示:

#函数名:autoNorm
#输入:dataSet为原始数据二维数组
#输出:normDataSet归一化之后的二维数组,ranges为每一列最大值减去最小值的范围,minVals为每一列的最小值。
def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals
  • 分析输入数据
    可以将数据用二维散点图画出来,直观感受一下。

  • 训练算法
    此步骤不适用于kNN算法

  • 测试算法
    通常来说,我们使用数据的90%作为训练数据,10%的数据作为测试数据。测试的指标为出错率,当预测的分类和实际的分类结果不一致时,记录一个错误,错误的总数/测试的样本数即为出错率。
    python代码:

#函数名:datingClassTest
#输入:无
#输出:无,但是会打印出错个数及错误率。
def datingClassTest():
    hoRatio = 0.50      #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))
    print errorCount

运行结果:


测试程序运行结果.png

可以看出,错误率为6.4%,大家可以改变参数值k,观察下出错率的变化。

  • 应用算法
    测试出错率达到满意结果之后,我们就可以拿来用了,应用程序如下:
def classifyPerson():
    resultList = ['not like','so so','very like']
    gamePercent = float(raw_input("gaming time percent:"))
    flyMiles = float(raw_input("flying miles per year:"))
    bookNum = float(raw_input("reading books per month:"))
    datingDataMat, datingLabels = file2matrix("datingTestSet2.txt")
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArray = array([flyMiles, gamePercent, bookNum])
    classifyResult = classify0((inArray - minVals)/ranges, normMat, datingLabels, 3)
    print "prediction result is: ", resultList[classifyResult - 1]

运行结果:


运行结果.png

可以看出,具有这些特征数据的她对你吸引力一般般啦,你可以自己测试看看,看到底什么样的她才是你喜欢的类型呢?

kNN算法总结

  • 优点:简单有效
  • 缺点:经过前面的介绍可以看出,kNN算法必须保存全部的数据集,如果训练数据集很大,那么就需要耗费大量的存储空间。此外,由于必须对待分类数据计算与每一个训练数据的距离,非常耗时。

终于写好了,码字好累,欢迎志同道合的朋友留言交流,有什么写的不对的地方敬请指出!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容