• KNN最近邻算法


    算法概述

    K最近邻(K-Nearest Neighbor,KNN)算法,是著名的模式识别统计学方法,在机器学习分类算法中占有相当大的地位。它是一个理论上比较成熟的方法。既是最简单的机器学习算法之一,也是基于实例的学习方法中最基本的,又是最好的文本分类算法之一。

    基本思想

    如果一个实例在特征空间中的K个最相似(即特征空间中最近邻)的实例中的大多数属于某一个类别,则该实例也属于这个类别。所选择的邻居都是已经正确分类的实例。
    该算法假定所有的实例对应于N维欧式空间中的一个点。通过计算一个点与其他所有点之间的距离,取出与该点最近的K个点,然后统计这K个点里面所属分类比例最大的,则这个点属于该分类。
    该算法涉及3个主要因素:实例集、距离或相似的衡量、k的大小。
    一个实例的最近邻是根据标准欧氏距离定义的。更精确地讲,把任意的实例x表示为下面的特征向量:

    (x1,x2,x3....,xn)其中xi表示为该实例的第i个属性。

    基本思想

    如果一个实例在特征空间中的K个最相似(即特征空间中最近邻)的实例中的大多数属于某一个类别,则该实例也属于这个类别。所选择的邻居都是已经正确分类的实例。
    该算法假定所有的实例对应于N维欧式空间Ân中的点。通过计算一个点与其他所有点之间的距离,取出与该点最近的K个点,然后统计这K个点里面所属分类比例最大的,则这个点属于该分类。
    该算法涉及3个主要因素:实例集、距离或相似的衡量、k的大小。
    一个实例的最近邻是根据标准欧氏距离定义的。更精确地讲,把任意的实例x表示为下面的特征向量:

    kNN算法图例

    简单来说,KNN可以看成:有那么一堆你已经知道分类的数据,然后当一个新数据进入的时候,就开始跟训练数据里的每个点求距离,然后挑离这个训练数据最近的K个点看看这几个点属于什么类型,然后用少数服从多数的原则,给新数据归类。

    KNN算法的决策过程

    下图中有两种类型的样本数据,一类是蓝色的正方形,另一类是红色的三角形,中间那个绿色的圆形是待分类数据:

    KNN算法的决策过程图例

    如果K=3,那么离绿色点最近的有2个红色的三角形和1个蓝色的正方形,这三个点进行投票,于是绿色的待分类点就属于红色的三角形。而如果K=5,那么离绿色点最近的有2个红色的三角形和3个蓝色的正方形,这五个点进行投票,于是绿色的待分类点就属于蓝色的正方形

    距离加权最近邻算法

    对k-最近邻算法的一个显而易见的改进是对k个近邻的贡献加权,根据它们相对查询点xq的距离,将较大的权值赋给较近的近邻。加权欧氏距离公式。在传统的欧氏距离中,各特征的权重相同,也就是认定各个特征对于分类的贡献是相同的,显然这是不符合实际情况的。同等的权重使得特征向量之间相似度计算不够准确, 进而影响分类精度。加权欧氏距离公式,特征权重通过灵敏度方法获得(根据业务需求调整,例如关键字加权、词性加权等)

    如果使用按距离加权,那么允许所有的训练样例影响xq的分类事实上没有坏处,因为非常远的实例对(xq)的影响很小。考虑所有样例的惟一不足是会使分类运行得更慢。如果分类一个新的查询实例时考虑所有的训练样例,我们称此为全局(global)法。如果仅考虑最靠近的训练样例,我们称此为局部(local)法。

    KNN的优缺点

    (1)优点

    ①简单,易于理解,易于实现,无需参数估计,无需训练;
    ②精度高,对异常值不敏感(个别噪音数据对结果的影响不是很大);
    ③适合对稀有事件进行分类;
    ④特别适合于多分类问题(multi-modal,对象具有多个类别标签),KNN要比SVM表现要好.
    (2)缺点
    ①对测试样本分类时的计算量大,空间开销大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本;
    ②可解释性差,无法给出决策树那样的规则;
    ③最大的缺点是当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进;
    ④消极学习方法。

    对k-近邻算法的说明

    按距离加权的k-近邻算法是一种非常有效的归纳推理方法。它对训练数据中的噪声有很好的鲁棒性,而且当给定足够大的训练集合时它也非常有效。注意通过取k个近邻的加权平均,可以消除孤立的噪声样例的影响。
    问题一:近邻间的距离会被大量的不相关属性所支配。
    应用k-近邻算法的一个实践问题是,实例间的距离是根据实例的所有属性(也就是包含实例的欧氏空间的所有坐标轴)计算的。这与那些只选择全部实例属性的一个子集的方法不同,例如决策树学习系统。
    比如这样一个问题:每个实例由20个属性描述,但在这些属性中仅有2个与它的分类是有关。在这种情况下,这两个相关属性的值一致的实例可能在这个20维的实例空间中相距很远。结果,依赖这20个属性的相似性度量会误导k-近邻算法的分类。近邻间的距离会被大量的不相关属性所支配。这种由于存在很多不相关属性所导致的难题,有时被称为维度灾难(curse of dimensionality)。最近邻方法对这个问题特别敏感。
    解决方法:当计算两个实例间的距离时对每个属性加权。
    这相当于按比例缩放欧氏空间中的坐标轴,缩短对应于不太相关属性的坐标轴,拉长对应于更相关的属性的坐标轴。每个坐标轴应伸展的数量可以通过交叉验证的方法自动决定。
    问题二:应用k-近邻算法的另外一个实践问题是如何建立高效的索引。因为这个算法推迟所有的处理,直到接收到一个新的查询,所以处理每个新查询可能需要大量的计算。
    解决方法:目前已经开发了很多方法用来对存储的训练样例进行索引,以便在增加一定存储开销情况下更高效地确定最近邻。一种索引方法是kd-tree(Bentley 1975;Friedman et al. 1977),它把实例存储在树的叶结点内,邻近的实例存储在同一个或附近的结点内。通过测试新查询xq的选定属性,树的内部结点把查询xq排列到相关的叶结点。

    Python实现KNN

    import numpy as np
    
    
    class KNearestNeighbor(object):
        def __init__(self, datas=None, targets=None, predict_sample=None, k=3):
            self.datas = datas
            self.targets = targets
            self.predict_sample = predict_sample
            self.k = k
            self.dis = np.zeros(self.targets.shape)
            self.distance()
            self.k_dis = {}
            self.predict_label = self.predict()
            print(self.predict_label)
    
        def distance(self):
            for i in range(len(self.targets)):
                self.dis[i] = sum([x * x for x in (self.datas[i] - self.predict_sample)])
    
        def predict(self):
            loc = np.argsort(self.dis)[:self.k]
            for i in range(len(loc)):
                if self.targets[loc[i]] in self.k_dis.keys():
                    self.k_dis[self.targets[loc[i]]] += 1
                else:
                    self.k_dis[self.targets[loc[i]]] = 1
            key, value = self.targets[loc[0]], self.k_dis[self.targets[loc[0]]]
            for k, v in self.k_dis.items():
                if value < v:
                    key, value = k, v
            return key

    用python实现的knn代码处理一下sklearn中的iris数据集

    #! /usr/bin/env python
    # -*- coding:utf-8 -*-
    import numpy as np
    from sklearn.datasets import load_iris
    
    
    class KNearestNeighbor(object):
        def __init__(self, datas=None, targets=None, predict_sample=None, k=3):
            self.datas = datas
            self.targets = targets
            self.predict_sample = predict_sample
            self.k = k
            self.dis = np.zeros(self.targets.shape)
            self.distance()
            self.k_dis = {}
            self.predict_label = self.predict()
            print(self.predict_label)
    
        def distance(self):
            for i in range(len(self.targets)):
                self.dis[i] = sum([x * x for x in (self.datas[i] - self.predict_sample)])
    
        def predict(self):
            loc = np.argsort(self.dis)[:self.k]
            for i in range(len(loc)):
                if self.targets[loc[i]] in self.k_dis.keys():
                    self.k_dis[self.targets[loc[i]]] += 1
                else:
                    self.k_dis[self.targets[loc[i]]] = 1
            key, value = self.targets[loc[0]], self.k_dis[self.targets[loc[0]]]
            for k, v in self.k_dis.items():
                if value < v:
                    key, value = k, v
            return key
    
    
    def main():
        datas, targets = load_iris().data, load_iris().target
        error_times = 0
        for i in range(len(datas)):
            predict_sample = datas[i]
            knn = KNearestNeighbor(datas, targets, predict_sample)
            print(targets[i])
            print("***************")
            if knn.predict_label != targets[i]:
                error_times +=1
        print("error times: ", error_times)
    
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    利用拦截器与自定义注解实现未登录拦截
    消息中间件activeMQ
    linux中redis的安装配置,后门漏洞修复及其攻击方法整合
    hibernate二级缓存
    初级程序员实战面试宝典(二)
    spring定时任务之-quartz调度器
    【微信小程序推广营销】教你微信小程序SEO优化,让你的小程序快人一步抢占先机
    ajax——CORS跨域调用REST API 的常见问题以及前后端的设置
    后台管理UI的选择
    微信小程序如何引入外部字体库iconfont的图标
  • 原文地址:https://www.cnblogs.com/pythonlearing/p/9955315.html
Copyright © 2020-2023  润新知