[机器学习实战]kNN

原理

kNN(k近邻算法)的基本思想就是选择距离待分类点最近的K个点,统计这K个点中出现的分类的概率, 出现概率最高的分类即为待分类点的分类

源码

from numpy import *
import operator

def createDataSet():    # create data set
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group,labels

def classify0(inX, dataSet, labels, k): #k-NN classify
    """
    :param inX: 用于分类的输入向量
    :param dataSet: 输入的训练样本集
    :param labels: 标签向量
    :param k: 用于选择最近邻居的数目
    :return:
    """

    # 用欧氏距离计算当前点与样本集中所有点的距离
    dataSetSize = dataSet.shape[0]  #获取数组维度的长度 (列或行数)
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet # tile是重复次数,如tile([0,0],(2,3)),是在重复行2次,列3次,结果是[[0 0 0 0 0 0] [0 0 0 0 0 0]]
    sqDiffMat = diffMat ** 2    # 所有元素平方
    sqDistances = sqDiffMat.sum(axis = 1) # axis = none 表示所有元素相加, axis = 0表示每一列所有元素相加, axis = 1表示每一行所有元素相加
    distances = sqDistances**0.5    # 开方得到待求点到数据集中所有点的距离
    sortedDistIndicies = distances.argsort()    # 返回的是从小到大排序后的原数据的索引, 如原数据为[1, 5, 3, 0], 调用argsort()方法返回的是[3, 0, 2, 1]
    classCount = {}

    # 选择距离最小的k个点
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]] # 得到前k个标签
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 统计label出现的次数,默认值为0

    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)  # 根据标签出现次数从高到低排序
    return sortedClassCount[0][0]

if __name__ == "__main__":
    group, labels = createDataSet()
    result = classify0([0, 0], group, labels, 3)
    print(result)

加权kNN

有一个问题就是该算法给所有的近邻分配相等的权重,这个还可以这样改进,就是给更近的邻居分配更大的权重(你离我更近,那我就认为你跟我更相似,就给你分配更大的权重),而较远的邻居的权重相应地减少,取其加权平均。需要一个能把距离转换为权重的函数,gaussian函数是一个比较普遍的选择,下图可以看到gaussian函数的衰减趋势。

高斯函数

这里写图片描述

高斯函数的图形在形状上像一个倒悬着的钟。参数a指高斯曲线的峰值,b为其对应的横坐标,c即标准差(有时也叫高斯RMS宽值),它控制着“钟”的宽度。

这里写图片描述

交叉验证

使用交叉验证进行算法模型评估以及k值的选取

猜你喜欢

转载自blog.csdn.net/vi_nsn/article/details/78896891