K-近邻(KNN)算法

待思考的问题

  1. KNN的基本思想是什么?
  2. 举一个现实生活的例子(非机器学习领域),说明KNN的应用
  3. KNN的优点和缺点分别是什么?
  4. 不同属性的值域大小不同(如有的跨度为500,而有的跨度为0.1),会导致什么问题,应如何解决?
  5. KNN算法的时间复杂度是多少?
  6. 用什么办法可以降低其时间复杂度?

1. KNN基本思想

比较官方的说法:给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也说K个邻居), 这K个实例的多数属于某个类,就把该输入实例分类到这个类中。
比较易理解的说法:近朱者赤,近墨者黑,即根据数据的相似性进行学习。
常言道,物以类聚,人以群分。有一种说法是判别一个人是一个什么样品质特征的人,可以从他/她身边的朋友入手。如下图,若要判别图中绿色的圆是属于哪一类数据,即从其邻居入手。但是,一次性看多少个邻居呢?
在这里插入图片描述

  • 如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。
  • 如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。

由此可见,当我们没法判定当前点属于已知分类中的哪一类时,可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。

2. KNN算法流程

简单理解为:

  • 找出每个测试数据最相似的k个训练数据
  • 投票决定

具体流程:

  1. 计算已知类别数据集中的点与当前点之间的距离
  2. 按照距离递增次序排序;
  3. 选取与当前点距离最小的 k 个点;
  4. 确定前 k 个点所在类别的出现频率;
  5. 返回前 k 个点出现频率最高的类别作为当前点的预测类别

3. KNN算法三要素

  1. 距离度量
  2. 确定K值
  3. 分类规则
3.1 距离度量
  1. 曼哈顿距离

在这里插入图片描述

  1. 欧氏距离

在这里插入图片描述

  1. 闵可夫斯基距离

在这里插入图片描述
在这里插入图片描述

3.2 确定K值

K值:表示在待预测点周围取几个临近的点来预测;

对于k值的选择,一般选择一个较小的值,然后通过交叉验证选择一个合适的k值。

k值过小会使得整体模型变复杂,容易发生过拟合

k值过大会使得整体模型变简单,容易发生欠拟合

通常K是不大于20的整数

3.3 分类规则

k 近邻算法中的分类规则往往采取多数表决,即由输入实例的k个邻近的训练实例中的多数类决定输入实例的类。

4. Python实现KNN算法

4.1 鸢尾花数据集分析

首先,通过比较经典的鸢尾花(Iris)数据集来进行学习。
1. 数据集介绍
该数据集一共包含150条记录,这150条记录被平均分成了3类,其中每一条数据有4种特征(feature):花萼长度,花萼宽度,花瓣长度,花瓣宽度。我们需要通过花萼长度,花萼宽度,花瓣长度,花瓣宽度这4个特征来预测鸢尾花卉属于iris-setosa, iris-versicolour, iris-virginica3个种类中的哪一类。
2. 实现步骤

  • 首先,通过调包载入鸢尾花数据集
  • 接着,对该数据集进行划分,划分成训练集和测试集
  • 对训练集进行训练
  • 通过测试集进行测试
    需要调的包
    import sklearn.datasets, sklearn.neighbors, sklearn.model_selection
    代码实现
def sklearnKnnTest():

    """1. Load the dataset(通过调包载入数据)"""
    tempDataset = sklearn.datasets.load_iris()
    print("The number of sample and feature: ", tempDataset.data.shape)
    x = tempDataset.data
    y = tempDataset.target
    # x是一个矩阵,有150行4列,即有150个样本,每个样本都具有4种特征
    # print("x = ", x)
    # y有0,1,2三类,每类50个
    # print("y = ", y)

    """2. Split the data(划分数据集,分成训练集和测试集)"""
    # test_size表示作为测试的数据的占比,即20%作为测试,80%作为训练
    x1, x2, y1, y2 = sklearn.model_selection.train_test_split(x, y, test_size=0.2)
    # x1, y1组成了训练集
    print("x1 = ", x1)
    print("y1 = ", y1)
    # x2, y2组成了测试集
    print("x2 = ", x2)
    print("y2 = ", y2)

    """3. Indicate the training set"""
    # n_neighbors即KNN算法中的K值,此处设为5
    tempClassifier = sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)
    tempClassifier.fit(x1, y1)

    """4. Test"""
    tempScore = tempClassifier.score(x2, y2)
    print("The score is: ", tempScore)

运行截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意:由于我们每一次对测试数据和训练数据的划分是不同的,所以在预测的时候,预测的准确率也会有差别。

以上实现过程是通过调包实现的,先从 sklearn 中导入了 鸢尾花的数据集,并通过train_test_split方法对该数据集进行了划分,再通过kNN 的分类算法函数 KNeighborsClassifier 建立模型,设置最近的 K 个样本数量 n_neighbors 为 5。再 fit 训练模型,最后 predict 预测模型得到分类结果 。并且预测结果可能会因为每次划分的测试数据集的不同而不同。
虽然这种调包的方式比较简单,但是对于其内部过程的实现还需要进一步学习,对于python代码实现的内容会记录在后续的几篇博客中。

5. KNN算法的优缺点

  • 优点
    精度高、对异常值不敏感、无数据输入假定
    简单易用,且预测效果不错
  • 缺点
    计算复杂度高(对高维数据计算量很大,预测阶段可能很慢)
    空间复杂度高(对内存要求高,该算法存储了所有训练数据)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值