机器学习一:k-近邻算法

一、k-近邻算法的概念及距离计算公式:

1.概念

  • k-近邻算法是一种常用的监督学习方法,其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。
  • 通常,在分类任务中可以使用“投票法”,即选择这k个样本中出现最多的类别标记作为预测结果;在回归任务重可以使用“平均法”,即将这k个样本的实值输出标记的平均值作为预测结果;还可以基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。
  • 显然,参数k是一个重要参数,不同的参数k可能导致结果显著不同;另外,采用不同的计算方式,则找出的“近邻”可能有显著差别,从而也会导致分类结果有显著不同

2.距离计算公式

  • 欧氏距离
  • 曼哈顿距离
  • 切比雪夫距离
  • 闵可夫斯基距离
  • 标准化欧氏距离
  • 马氏距离
  • 夹角余弦
  • 汉明距离
  • 杰卡德距离&杰卡德相似系数
  • 相关系数&相关距离
  • 信息熵

二、举例

以一个二维的二分类任务为例,距离计算公式选择欧氏距离

我们用一条小狗每天的摄入量与睡觉时间来判断一条小狗是胖狗还是瘦狗,在判断之前,我们必须要有一定数量的样本来作为依据
设小狗a每天摄入1.5g食物,睡8小时,是瘦狗,即(1.5, 7, ‘yes’)
小狗b每天摄入1.6g食物,睡9小时,是瘦狗,即(1.7,, 9, ‘yes’)
小狗c每天摄入2.3g食物,睡12小时,是胖狗,即(2.3, 12, ‘no’)
小狗d每天摄入2.5g食物,睡10小时,是胖狗,即(2.5, 10. ‘no’)
在这里插入图片描述

现在我们用k-近邻法来判断小狗e(2.4, 11)是胖狗还是瘦狗

在这里插入图片描述

k为离目标点距离最近的点的数目, 这里我们选定k = 2,由图可知,离目标点e最近的两点为c点和d点,而c、d都是胖狗,所以e也是胖狗

三、k-近邻算法的流程

1.此时算法
2.准备数据
3.分析数据
4.测试算法(计算错误率)
5.使用算法

四、python实现k-近邻算法

import numpy as np
import operator

class kNN():

    def createDataSet(self): # 创建数据集
        group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
        lables = ['A', 'A', 'B', 'B']
        return group, lables

    def classify0(self, inX, dataSet, labels, k):
        dataSetSize = dataSet.shape[0] # 样本数
        diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # 对inX的行重复dataSetSize次,列重复一次
        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]] # 取得距离最短的前k个样本的标签
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 对应标签的样本数
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # 对标签书倒序排序
        return sortedClassCount[0][0]

测试

if __name__ == '__main__':
    inX = [0, 0]
    c = kNN()
    group, lables = c.createDataSet()
    print(c.classify0(inX, group, lables, 3))
>>>B    

实例:利用k-近邻算法实现约会网站的配对

我们通过三个属性:每年获得的飞行常客里程数, 每天花在游戏和视频上的百分比, 每周消费的冰淇淋公斤数来判断对一个人的好感度’not at all’, ‘in small doses’, ‘in large doses’
数据集:
百度网盘链接
提取码: zkf7
从文本文件中解析数据:

    def file2matrix(self, filename): # 文件操作
        fr = open(filename)
        arrayOLines = fr.readlines()
        numberOfLines = len(arrayOLines)
        returnMat = np.zeros((numberOfLines, 3)) # 初始化矩阵
        classLabelVector = []
        index = 0
        for line in arrayOLines:
            line = line.strip()
            listFromLine = line.split('\t')
            returnMat[index, :] = listFromLine[0:3] # 填充矩阵
            classLabelVector.append(int(listFromLine[-1])) # 标签向量
            index += 1
        return returnMat, classLabelVector

分析数据

    def dataVisible(self, datingDataMat,datingLabels):
        fig = plt.figure(figsize=(5, 4), dpi=500)
        ax = fig.add_subplot(111) # 1×1网格的第一个图
        ax.scatter(datingDataMat[:, 0], datingDataMat[:, 1], 15.0*np.array(datingLabels), 15.0*np.array(datingLabels)) # 第三个参数是尺寸,第四个参数是色彩
        plt.show()

在这里插入图片描述归一化数值
由于数字差直大的属性对计算结果影响大,所以需要将数据归一化
newValue = (oldValue - min)/(max - min)

    def autoNorm(self, dataSet): # 归一化new = old - min/max - min
        minVals = dataSet.min(0) # 每列最小的元素
        maxVals = dataSet.max(0) # 每列最大的元素
        ranges = maxVals - minVals
        # normDataSet = np.zeros(dataSet.shape) # 初始化矩阵
        m = dataSet.shape[0]
        normDataSet = dataSet - np.tile(minVals, (m, 1)) # old - min
        normDataSet = normDataSet / np.tile(ranges, (m, 1)) #old - min/max - min
        return normDataSet, ranges, minVals

测试算法,计算错误率

    def datingClassTest(self): # test
        hoRatio = 0.10 # 抽取百分之十的样本作为测试集
        datingDataMat, datingLabels = self.file2matrix('/home/cxd/下载/machinelearninginaction/Ch02/datingTestSet2.txt')
        normMat, ranges, minVals = self.autoNorm(datingDataMat) # 归一化
        m = normMat.shape[0] # m组样本
        numTestVecs = int(m * hoRatio)
        errorCount = 0.0
        for i in range(numTestVecs):
            classifierResult = kNN().classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) # 前百分之十作为测试集
            print('分类结果是 %d ,正确答案是 %d ' % (classifierResult, datingLabels[i]))
            if classifierResult != datingLabels[i] : errorCount += 1.0
        print('总的错误率是: %f' % (errorCount/float(numTestVecs)))

使用算法

    def classifyPerson(self):
        resultList = ['not at all', 'in small doses', 'in large doses']
        percentTats = float(input('pecentage of time spent playing video games?'))
        ffMiles = float(input('frequent flier miles earned per year?'))
        iceCream = float(input('liters of ice cream consumed per year?'))
        datingDataMat, datingLabels = self.file2matrix('/home/cxd/下载/machinelearninginaction/Ch02/datingTestSet2.txt')
        normMat, ranges, minVals = self.autoNorm(datingDataMat)
        inArr = np.array([ffMiles, percentTats, iceCream])
        classifierResult = kNN().classify0((inArr - minVals)/ranges, normMat, datingLabels, 3)
        print('You will probably like this person:', resultList[classifierResult - 1])

结果:

if __name__ == '__main__':
    a = Appointment()
    a.classifyPerson()
>>>
pecentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice cream consumed per year?0.4
You will probably like this person: in small doses    

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值