机器学习之k-近邻算法

机器学习、python


算法流程

对未知类别属性的数据集中的每个点依次执行以下操作:
step1:计算已知类别数据集中的点与当前点之间的距离
step2:按照距离递增持续排序
step3:选取与当前点距离最小的k个点
step4:确定前k个端所在类别的出现频率
step5:返回前k个点出现频率最高的类别作为当前点的预测分类

详细讲解

首先对这个算法举个例子,一个样本距离一个标记点的距离在所有的标记点中是最近的,我们当然可以把这个样本点和这个标记点归于一类,但是这个叫做最近邻算法。k-近邻算法的意思是找出这个样本点距离所有标记点的距离并进行排序,选择其中距离最短的k个数据,根据出现的频率进行分类。很明显这样的分类更具有正确性。
下面放出一段利用kNN算法的代码,具体的讲解都在注释里:

# -*- coding: UTF-8 -*-
import numpy as np
import operator

#构造数据集
def createDataSet():
    #四组二维数据
    group = np.array([[1, 101],[5, 89],[108, 5],[115, 8]])
    #特征标签
    labels = ['爱情片','爱情片','动作片','动作片']
    return group, labels

#kNN算法实现
def classify0(inX, dataSet, labels, k):
    #numpy函数shape[0]返回dataSet的行数
    dataSetSize = dataSet.shape[0]
    #在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    #二维特征相减后平方
    sqDiffMat = diffMat**2
    #sum()所有元素相加,sum(0)列相加,sum(1)行相加
    sqDistances = sqDiffMat.sum(axis=1)
    #开方,计算出距离
    distances = sqDistances**0.5
    #返回distances中元素从小到大排序后的索引值
    sortedDistIndices = distances.argsort()
    #定一个记录类别次数的字典
    classCount = {}
    for i in range(k):
        #取出前k个元素的类别
        voteIlabel = labels[sortedDistIndices[i]]
        #dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
        #计算类别次数
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    #python3中用items()替换python2中的iteritems()
    #key=operator.itemgetter(1)根据字典的值进行排序
    #key=operator.itemgetter(0)根据字典的键进行排序
    #reverse降序排序字典
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    #返回次数最多的类别,即所要分类的类别
    return sortedClassCount[0][0]


if __name__ == '__main__':
    #创建数据集
    group, labels = createDataSet()
    #打印数据集
    print(group)
    print(labels)

    #测试集
    test= [101, 20]

    #kNN分类
    test_class = classify0(test, group, labels, 3)
    print(test_class)

我们从这里可以看出,k-近邻算法没有进行数据的训练、没有学习的过程,只是直接武断的将未知的数据根据特征并于已有的类型当中。

k-近邻算法实战(约会网站配对效果判定)

基本功能

一名女士对自己交往的人进行如下分类:不喜欢的人、魅力一般的人、极具魅力的人,然后根据他们的喜好选出了自己的指标(特征):每年获得的飞行常客里程数、玩视频游戏所消耗时间百分比、每周消费的冰淇淋公升数.下面代码就是先将数据文件从datingTestSet.txt里面导入,然后将数据格式更改为分类器可以接受的格式(特征矩阵和响应的分类标签向量)

# -*- coding: UTF-8 -*-
import numpy as np


def file2matrix(filename):
    fr= open(filename)
    arrayOflines=fr.readlines()
    numberOflines=len(arrayOflines)
    returnMat = np.zeros((numberOflines, 3))

    classLabelVector=[]

    index=0
    for line in arrayOflines:
        # s.strip(rm),当rm空时,默认删除空白符(包括'\n','\r','\t',' ')
        line = line.strip()
        # 使用s.split(str="",num=string,cout(str))将字符串根据'\t'分隔符进行切片。
        listFromLine = line.split('\t')
        returnMat[index, :] = listFromLine[0:3]
        if listFromLine[-1] == 'didntLike':
            classLabelVector.append(1)
        elif listFromLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        elif listFromLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        index += 1
    return returnMat, classLabelVector

if __name__ == '__main__':
    #打开的文件名
    filename = "datingTestSet.txt"
    #打开并处理数据
    datingDataMat, datingLabels = file2matrix(filename)
    print(datingDataMat)
    print(datingLabels)

输出结果如下:


输出结果.png

是不是根本不知道这些数据是干什么的,是的,这就是我们为什么需要进行图像化处理的原因。

数据可视化

我们需要利用matplotlib库进行绘图,最后结果图是这样的:

输出结果2.png

图像的完整代码可以看我的github

进阶思考

但是仔细思考一下,这样利用欧氏距离将三个特征的差值平方和相加后,进行样本的分类是否可取呢?我认为不是的,比如一组数据中某个特征的差值比较大,这样必然会影响整体的数据,进而影响分类。从题干中我们也知道,这位女士是视她定的三个标准是同样的,所以我们必须要对数据进行处理。这也是我们在拿到数据后经常做的事:数据归一化。什么叫数据归一化?意思就是消除诸如量纲、大小等明显会造成误差的因素:
newValue = (oldValue - min) / (max - min)
这里我们将所有的数据(特征值)转化为0到1区间内的值。
调整后我们进行检测,一般的检测方法就是在训练集中选择10%-30%的数据作为检验集,剩下的作为学习集;这里我们选用10%作为测试,得到的结果为:

输出结果3.png

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

推荐阅读更多精彩内容