[Tech] 机器学习之一. k-近邻算法

机器学习是人工智能发展的助燃剂,人工智能如同一辆迟迟不来的列车,然而一旦当其前来,便会以令人瞠目的速度驰骋。而在人工智能的洪流之中,人类却如苇草,渺小如你我,有且只有顺应时代的潮流。

一、特点

刚开始学k-近邻算法的时候,立马就想起高中学的求二象限及三象限中两点的距离。只不过k-近邻算法将象限值扩大了一些,但总的来说原理还是类似的。
k-近邻算法易于掌握(高中数学基础)就可以轻松理解其原理,但计算复杂度比较高,相对而言它的精度也比较高哦。

二、栗子

举一个栗子让大家更好的理解k-近邻算法。我喜欢喝Coco的金桔柠檬,主要就是因为它的甜度和酸度控制得非常合我口味,当我考量其它家的金桔柠檬时,就需要将其的甜度和酸度和Coco家的做个对比,对比结果越小,就越合我口味。
下面,我们来画一张图,横轴表示酸度,纵轴表示甜度,将Coco家的金桔柠檬的甜度和酸度都量化为5。

随便说说的评测

那么该如何评判其它家金桔柠檬在我心里的地位呢?学过函数的你一定会想到根据其他家金桔柠檬酸甜度的量化结果求与Coco家酸甜度的距离吧,以x代表酸度,y代表甜度,那么这个距离就是√[(x-5)^2 +(y-5)^2]
。距离越短就说明这个口味越合我意。
在实际的数据分析中,可能不止甜度和酸度两个特征值,这种情况下就需要算出多维度下亮点的距离了,如有5个特征值,则(1,0,2,1,0)与(3,2,1,5,6)的距离计算公式就是:
√[(3-1)^2 +(2-0)^2 +(1-2)^2 +(5-1)^2+ (6-0)^2]

三、更多的样本

在以上栗子中,我按照酸度和甜度与Coco家金桔柠檬的匹配程度去衡量我对其它品牌金桔柠檬的喜爱程度。这样的结果是否符合呢?

相信读者已经提出异议了吧。

首先,仅凭我对一家金桔柠檬的喜爱程度(一个样本)就去分析我对其它家金桔柠檬的喜爱未免太过武断,因为我对金桔柠檬的喜好程度并不仅仅取决于甜度与酸度,还会有其它干扰因素比如茶的颜色、包装之类,有可能我喜欢Coco家的金桔柠檬和它的甜度酸度没有太大关系,仅仅是因为它家的包装呢?

另一方面,我对甜度酸度均为5的金桔柠檬非常喜爱,也不能得出我对甜度为3酸度为4的金桔柠檬的喜爱程度。

所以,想让结果更准确的话,我们还需要做两个小小的改善:第一,多喝几家的金桔柠檬,并记录这些金桔柠檬的甜度酸度以及我对这些金桔柠檬的喜爱程度,样本扩大之后,就能够减少对某家非甜度和酸度两个因素影响的喜爱程度产生的结果偏差;第二,将喜爱程度量化或分类,量化就是指对金桔柠檬茶打分,分类就是指对金桔柠檬茶的喜好程度进行一个分类,比如“非常喜欢”,“一般喜欢”,“普通喜欢”,“不喜欢”。

于是乎,我又尝试了其它家的金桔柠檬茶,并记录下它们的甜度、酸度并且对它们进行了打分。

酸度 甜度 打分
5 5 5
7 3 4
5 6 5
3 6 3
2 3 3
6 5 5
7 8 3

以上的数据我们将其称为训练样本,接着我们就可以尝试测试一下我们的k-近邻算法啦,大致的思路是这样的,得到某个测试样本的酸度与甜度,并计算出其与所有品尝过的样本的距离,取出距离最小的前k个样本与其对应的标签,得到出现次数最多的标签,即为结果。

什么意思呢?比如说我得到一款新的金桔柠檬,然后测量出它的甜度与酸度,我用上述方法计算出其与所有品尝过的样本的酸甜度距离,然后得出酸甜度距离最小的前三家,也就是酸甜口味最相似的前三家,然后统计出那三家中喜好分数出现的次数,得出出现次数最多的那个分数,就是预测的我对这款新品的喜好程度。

四、上代码

第一步,我们将训练样本解析成特征值数组以及标签数组。

将训练样本的txt文件转换为 特征值数组returnMat 以及相应的同长度的标签数组 classLabelVector

def file_to_matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())  # get the number of lines in the file
    returnMat = zeros((numberOfLines, 2))  # 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:2]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector
        

我们得到了两个数组:

returnMat = [[5,5], [7,3], [5,6], [3,6], [2,3], [6,5], [7,8]]  
classLabelVector = [5, 4, 5, 3, 3, 5, 3]

第二步,当得到了训练样本以及其对应标签后,我们就可以计算出测试数据与每个样本的距离,随后我们可以选取前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]

其中,inX是输入的测试特征值数组,dataSet是训练特征值数组,labels是训练标签数组,k是用户定义的距离最小的样本标签数量。

我将新产品的甜度酸度[5,3]作为inX参数传入,dataSet和labels就是第一步得到的returnMat和classLabelVector,我取k为3,执行。

结果为5,非常喜欢,Done!

五、更多优化

使用上述方法,得到了结果,但是我们有没有可以优化的地方呢?
我的想法是,可以将打分结果从离散值转换为连续值,然后按照一定的权重去求得距离。
第二点就是,在这个栗子中我们的甜度和酸度的数值范围是相似的,如果我们以mg/L和ph值来定义甜度和酸度的时候,就需要做一个归一化处理。

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

推荐阅读更多精彩内容