KNN算法 (K最近邻算法)(K-Nearest Neighbors)

一。工作原理

存在一个样本数据集合,也称作训练样本数据集,并且样本集中每个数据都存在标签,机我们知道样本集中每一个数据所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般呢来说,我们只选择样本数据集中前k个最相似 的数据,选择k个最相似数据中出现次数最多的分类,作为新数据的分类,

二。概述(伪代码)

(1)计算已知类别数据集中的点与当前点之间的距离

(2)按照距离递增次序排序

(3)选取与当前点距离最小的k个点

(4)确定前k个点所在 的类别的出现的频率

(5)返回前k个点出现频率最高的类别作为当前点的类别

三。KNN注意事项

1.k的值应当根据实际情况进行取值。如果K过大可能导致计算机运行时间过长,并且可能导致欠拟合的情况;如果K的值过小,可能导致过拟合。

2.计算样本之间的距离可以使用不同的函数,例如欧式距离,曼哈顿距离等等。

欧式距离:

y= ^{^{\sqrt{\left (x1-x2 \right )+(y1-y2))}}}

曼哈顿距离:

y=\left | x1-x2 \right |+\left | y1-y2 \right |

四。KNN基础代码

1.引用库
from numpy import * 
import operator
import numpy as np
2.创建训练集
def createDataSet():
    group=array([[1.0,1.1],[1.0,1.1],[0,0],[0,0.1]])
    #创建二维数组,表示点在坐标系上的距离
    labels = ['A','A','B','B']
    #表示不同点代表的不同类别
    return group,labels
3.KNN算法
def classify0(inx,dataSet,labels,k):
    #本次使用了欧式距离计算了点之间的距离
    dataSetSize=dataSet.shape[0]
    #获取dataSet的行数
    diffMax=np.tile(inx,(dataSetSize,1))-dataSet
    #tile函数的作用是将输入的数组或矩阵沿指定的轴进行重复拓展。其中,(dataSetSize, 1)表示将inx进行重复的次数。在这里,inx是一个一维数组,(dataSetSize, 1)表示将inx在行方向上重复 dataSetSize 次,在列方向上重复 1 次。
    #diffMax计算了 inx 与 dataSet 中每个样本的差异,即将inx扩展为和dataSet相同尺寸的数组,并逐元素相减,得到差异矩阵。
    sqDiffMat=diffMax**2
    #差异矩阵的平方
    sqDistances=sqDiffMat.sum(axis=1)
    #sqDiffMat.sum(axis=1) 将对 sqDiffMat 中的每一行进行求和,生成一个新的一维数组 sqDistances,该数组的长度与 sqDiffMat 的行数相同。
    #这一步的目的是计算每个样本与输入向量 inx 之间的差异的平方和,即沿着列方向求和。
    distances=sqDistances**0.5
    #平方根
    sortedDistIndicies=distances.argsort()
    #argsort()函数是对distances进行排序,并返回排序后的索引值即【2,3,0,1】
    classCount={}
    #字典
    for i in range (k):
        voteIlabel=labels[sortedDistIndicies[i]]
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
        #classCount为字典,voteIlabel作为键值,classCount.get(voteIlabel,0)是一个字典的方法,用于获取字典中以voteIlabel作为键的对应值。如果键存在,则返回对应的值,如果键不存在则创建该键并返回默认值0
    sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    #classCount.items() 返回一个由字典的键值对组成的可迭代对象。
    #sorted() 是 Python 内置函数,用于对可迭代对象进行排序。通过指定 key=operator.itemgetter(1),表示按照每个键值对的第二个元素(即值)进行排序。
    #reverse=True 表示按照降序排列。
    return sortedClassCount[0][0]
4.调用KNN进行实验
#开始调用KNN算法
group,labels=createDataSet()
print("(0,0)点的类别为"+classify0([0,0],group,labels,3))
5.调用KNN的过程中的数据验算(可以不看)

根据给定的代码,当调用 print(classify0([0,0],group,labels,3))

步骤如下:

  1. 根据 createDataSet() 函数,得到 group 和 labels 的值,分别为 [[1.0, 1.1], [1.0, 1.1], [0, 0], [0, 0.1]] 和 ['A', 'A', 'B', 'B']

  2. 在 classify0() 函数中,输入向量 inx 为 [0, 0],数据集 dataSet 为 group

  3. 计算 diffMax,即 np.tile(inx, (dataSetSize, 1)) - dataSet,其结果为 [[[-1.0, -1.1]], [[-1.0, -1.1]], [[0, 0]], [[0, -0.1]]]

  4. 计算 sqDiffMat,即 diffMax**2,其结果为 [[[1.0, 1.21]], [[1.0, 1.21]], [[0, 0]], [[0, 0.01]]]

  5. 沿着轴1求和,即 sqDiffMat.sum(axis=1),其结果为 [2.21, 2.21, 0, 0.01]

  6. 计算平方根,即 sqDistances**0.5,其结果为 [1.486, 1.486, 0.0, 0.1]

  7. 对 distances 进行排序,并返回排序后的索引,即 distances.argsort(),其结果为 [2, 3, 0, 1]

  8. 根据参数 k=3,统计前 k 个最近邻样本的标签,并记录它们出现的次数,结果为 {'B': 2, 'A': 1}

6.预期结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值