K-近邻算法(一):k近邻算法的初步学习

k近邻算法初步学习

介绍

这是我第一次写博客,闲来无事记录一下刚实践过的算法程序。

步入正题

我们今天所进入的内容–KNN算法,是一种有监督学习。

不清楚机器学习的一些分类概念可以自行学习下面网站
https://www.jianshu.com/p/429320f81d61

样本集合
在监督学习当中,我们会将数据集分为两部分来运作:训练集和测试集。
学习程序开始运行时,使用训练样本集作为算法的输人,训练完成之后输人测试样本。输人测试
样本时并不提供测试样本的目标变量,由程序决定样本属于哪个类别。
实例分析
下面是一个关于电影的数据集,共有两个特征值:打斗镜头和接吻镜头。
我们可以根据两个特征来判断电影的类型到底是爱情片还是动作片。
数据集
在这里插入图片描述
即使不知道未知电影属于哪种类型,我们也可以通过某种方法计算出来。首先计算未知电影 与样本集中其他电影的距离,按照距离递增排序,可以找到K个距离最近的电影.这样说可能不是很明白,后面会有具体的一个简单程序有助于我们理解K近邻算法。
先介绍一下K-近邻算法的一般流程:
(1)收集数据:可以使用任何方法。
(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。
(3)分析数据:可以使用任何方法。
(4)训练算法:此步驟不适用于K近邻算法。
(5)测试算法:计算错误率。
(6)使用算法:首先需要输入样本数据和结构化的输出结果,
然后运行K-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理.

下面介绍一下KNN算法的一般步骤:

对未知类别属性的数据集中的每个点依次执行以下操作:
(1)计算已知类别数据集中的点与当前点之间的距离;
(2)按照距离递增次序排序;
(3)选取与当前点距离最小的走个点;
(4)确定前K个点所在类别的出现频率;
(5)返回前K个点出现频率最高的类别作为当前点的预测分类。
从步骤中,我们也可以看出,所谓的K-近邻算法也就是通过输入向量与数据集元素的距离计算,来判断预测输入向量的所属类别。
小程序实践

from numpy import *
import operator
def createDataset():
    # 创建数据集和标签信息
    group = array([[1, 1.1], [1, 1], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels
    # group: 
 [[1.  1.1]
 [1.  1. ]
 [0.  0. ]
 [0.  0.1]]



def classify(inX, dataSet, labels, k):
    # 得到数据集的行数
    dataSetSize = dataSet.shape[0]
    # 计算数据集中 两点之间的距离 d = ((x1 - x2 )**2 + (y1 - y2 )**2)**0.5
    # ** 次方
    # tile函数:将数据复制 inX应为输入向量
    # 输入向量为一行单个数据  但为了要与数据集中的每一个数据都要相减从而计算距离
    # 我们需要把输入向量也构造成与数据集同行数的数据集   用到tile函数
    # 此处训练集数据我们只用到了两个特征向量 因此直接在两个数组做减法 后再平方最后开方就可以了
    # 不需要单独拉某两个数据出来依此做减法
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2
    sqDistances = sqDiffMat.sum(axis=1)
    # 默认axis为None,表示将所有元素的值相加
    # 对于二维数组
    # axis=1表示按行相加 , axis=0表示按列相加
    distance = sqDistances ** 0.5
    # 将开方后得出的最终距离值 按从小到大的顺序依此排序(排序后得到的是数据的索引值)
    SortedDisIndicies = distance.argsort()
    classCount = {}
    # 选择距离最近的k个点
    for i in range(k):
        # 取出数据集中相应索引值的标签向量
        voteIlabel = labels[SortedDisIndicies[i]]
        # 将取出的标签向量保存
        # get(key,default=none):查找键的值 没有返回默认值
        # get()一般用与字典的key-value中value的检查
        # 这里我们用的是数组 也就是都没有value 也就是返回0值
        # 但是我们实现定义了一个空的字典classcount
        # 每次循环时 我们可以将第K个标签向量的value都+1
        # 这样我们可以通过最终字典中标签向量的value值的大小知道那个数据出现的次数最多(也就是最接近)
        classCount[voteIlabel] = classCount.get(voteIlabel, 0)+1
        print(classCount)
        # {'B': 1}
        # {'B': 2}
        # {'B': 2, 'A': 1}
    # 排序
    # classCount.items():将字典中的每一元素迭代成元组 最终储存在列表中(元组列表)
    # classCount.iteritems() 原来函数是有items()、iteritems()的
    # 现在python3已经没有第二个 直接将items函数整合为一个了
    # 因为字典是无序的 所以迭代的列表中的每一个元组也是无序的
    # key=operator.itemgetter(1):获取域中的值 此处表示得到我们classcount字典中索引为1的值也就是value值
    # 依据key值大小函数进行排序 reverse 默认按照降序
    # 最终我们到列表中的第一个值 也就预测结果
    sortedClasscount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    print(sortedClasscount)     # [('B', 2), ('A', 1)]
    print(sortedClasscount[0])  # ('B', 2)
    return sortedClasscount[0][0]
    # eg: 对字典排序
    # >>> d = {'data1':3, 'data2':1, 'data3':2, 'data4':4}
    # >>> sorted(d.iteritems(), key=itemgetter(1), reverse=True)
    # [('data4', 4), ('data1', 3), ('data3', 2), ('data2', 1)]
    # sort(): 默认升序,加上reverse=True,直接降序排序
    
if __name__ == '__main__':
    data, label = createDataset()
    print("data", label)
    print("输入向量的预测结果为:", classify([0, 0], data, label, 3))
    # 最终结果列表 [('B', 2), ('A', 1)]
    # 输入向量的预测结果为: B

程序中我们发现,在邻近的K个结果中,B类型出现两次,我们预测新数据的类型为B类型。

K-近邻算法优缺点

优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高、 K值的合理性也直接关系到预测结果的正确性。
适用数据范围:数值型和标称型。
数值型:固定数字
标称型:是或不是 (二值化)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值