K Nearest Neighbor

KNN算法

概述

KNN算法:即最邻近分类算法(K-NearestNeighbor

算法思路:如果一个样本在特征空间中的k个最相似(即特征空间中最临近)的样本中的大多数属于某一个类别 则该样本也属于这个类别 k通常是不大于20的整数 KNN算法中 所选择的邻居都是已经正确分类的对象 该方法在定义决策上只依据最邻近的一个或几个样本的类别来决定待分样本所属的类别

这里写图片描述

如上所示
绿色圆要被决定赋予哪个类,是红色三角形还是蓝色四方形?如果K=3,由于红色三角形所占比例为2/3,绿色圆将被赋予红色三角形那个类,如果K=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。由此也说明了KNN算法的结果很大程度取决于K的选择。
在kNN中,计算对象之间的距离通常使用欧氏距离。比如若是求二维平面的欧氏距离,则公式为d = sqrt[(x1 - x2)^2 + (y1 - y2)^2]
KNN算法思路总结:就是在训练集中数据和标签已知的情况下,输入测试数据 将测试数据的特征与训练集中对应的特征进行相互比较 找到训练集中与之最为相似的前K个数据 则该测试数据对应的类别就是K个数据中出现次数最多的那个分类 其算法的描述为:
1. 计算测试数据与各个训练数据之间的距离
2. 按照距离的递增关系进行排序
3. 选取距离最小的K个点
4. 确定前K个点所在类别的出现频率
5. 返回前K个点中出现频率最高的类别作为测试数据的预测分类
import numpy as np
import math
import operator
"""knn算法优化
    :param  dataSet 无量纲化
    :func   knn weight
    :return 系统体系
    other
    :knn logistic regression
"""


def createDataSet():
    group = np.array([[10, 9.2], [8.8, 7.9], [0.1, 1.4], [0.3, 3.5]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels

def normDatafunc(dataSet):
    print(dataSet)
    print(np.max(dataSet))
    print(np.min(dataSet))
    dataMax = np.max(dataSet)
    dataMin = np.min(dataSet)
    dataRange = dataMax - dataMin
    normData = (dataSet-dataMin)/dataRange
    return dataRange, dataMin, dataMax, normData

def normTest(dataMin, dataRange, testSet):
    test = (testSet-dataMin)/dataRange
    return test

def gaussian(dist, a=1, b=0, c=0.3):
    return a * np.math.e ** (-(dist - b) ** 2 / (2 * c ** 2))


def knnClassify(dataSet, Labels, testSet, k):
    nrow = np.shape(dataSet)[0]
    cdiff = np.tile(testSet, (nrow, 1)) - dataSet
    sqdiff = cdiff ** 2
    sumdiff = np.sum(sqdiff, axis=1)
    dist = np.sqrt(sumdiff)
    print('dist', dist)

    # knn加权 越近权重越大 越远权重越小 与dist排序相反
    weightDis = []
    for i in dist:
        weightDis.append(gaussian(i, a=1, b=0, c=0.3))
    print('weightDis', weightDis)
    weightDis = np.array(weightDis)
    # weightDis = []
    # for i in dist:
    #     weightDis.append(gaussian(dist=i, a=1, b=0, c=0.3))

    indexSorted = np.argsort(-weightDis) # 降序排序
    print(indexSorted)

    classCount = {}
    for i in range(k):
        vote = Labels[indexSorted[i]]
        classCount[vote] = classCount.get(vote, 0) + 1

    # maxCount = 0
    # for k, v in classCount.items():
    #     if v > maxCount:
    #         maxCount = v
    #         classes = k
    sortedLabel = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedLabel[0][0]

def main():
    dataSet, Labels = createDataSet()

    dataRange, dataMin, dataMax, normData = normDatafunc(dataSet)

    testSet = [0.0, 0.0]
    test = normTest(dataMin, dataRange, testSet)

    k = 3

    lis = {
        'A': 'big',
        'B': 'smaller'
    }
    print(lis)
    result = knnClassify(normData, Labels, test, k)
    print('result is:'+lis[result])



if __name__ == '__main__':
    main()

KNN学习及补充

import math
"""KNN
    一句话总计:近朱者赤 近墨者黑
    input:  
            经过预处理的特征向量
            对应于特征空间的点 --- 多个类
            监督分析算法
            分类时通过多数表决进行预测
            k近邻算法--没有训练过程 
                    --不具有显式的学程

    基本要素:
            k值的选择
            距离度量
            分类决策规则

    案列:
            爱情片和动作片分类
    数学原理:
            欧式距离
            计算未知与已知之间的距离
            相似度越高距离越小
            相似度越低距离越大
            k:  是自己设置的数
    训练时间为0 计算时间很多
    k值:
            交叉验证优化
    优缺点:
        缺点:
            k值小了 容易过拟合 分得过于细了
        k值大了
            可以避免过拟合
            对最终结果可能有影响
        缺点:


    分类决策规则:
            knn中求取分类最优近邻 是合理的
            距离加权
                距离近权重加大
                距离远权重减小

    # 学习误差: 
    # 估计误差: 模型估计值与实际之间的差距   训练
    # 近似误差: 模型估值与实际差距          测试集 
    消除数据的量纲大小影响---做无量纲化优化
    归一化:AutoNorm
        将你需要处理的数据经过处理限制在一定条件范围内
            方法:
                1.线性函数转化[0, 1]
                2.对数函数转化
                3.反余切函数转化
                4.输入值转为[-1, 1]
    样本数据分解:
        0.1 训练数据
        0.9 测试数据
        总体样本数据    

    用于回归:
        k个近邻的平均值

"""


"""knn 距离加权的几种方式
    1. 反函数
        该方法最简单的形式是返回距离的倒数 完全一样或非常接近的商品权重为会很大
        因此: 在距离求倒数时 在距离上加一个常量
        比如距离D 权重为:1/D
        weigh = 1/(distance + const)
      缺点: 为近邻分配很大的权重 使得算法对噪声数据变得敏感
    2.高斯函数(正态分布)
        高斯函数在距离为0的时候权重为1,随着距离增大,权重减少,但不会变为0


    计算加权knn
    1.在处理离散型数据时,将这k个数据用权重区别对待,预测结果与第n个数据的label相同的概率
    2.在处理数值型数据时,并不是对这k个数据简单的求平均,而是加权平均:通过将每一项的距离值乘以对应权重,让后将结果累加。求出总和后,在对其除以所有权重之和。

"""
# 高斯函数实现方式
def gaussian(dist, a=1, b=0, c=0.3):
    return a * math.e ** (-(dist - b) ** 2 / (2 * c ** 2))

KNN预测算法

import numpy as np
import operator

def creatDataSet():
    groups = np.array([[1, 1.1], [1, 0.99], [0.1, 0.02], [0.2, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return groups, labels

def classify(test, dataSet, labels, k):
    dataSize = dataSet.shape[0]
    diff = np.tile(test, (dataSize, 1)) - dataSet
    stdDiff = diff ** 2
    stdDis = np.sum(stdDiff, axis=1)
    sortedIndex = np.argsort(stdDis)

    classCount = {}
    for n in range(k):
        voteLabel = labels[sortedIndex[n]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1

    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

def test():
    dataSet, labels = creatDataSet()
    test = [0.9, 1]
    result = knnLR(test, dataSet, labels, 2)
    print(result)

def weight(dist, a=1, b=0, c=0.3):
    return a * np.math.e ** (-(dist - b) ** 2 / (2 * c ** 2))

# 回归预测 -- 使用权重
def knnLR(inX,dataset,labels,k):
    #1,计算距离
    dataset_size = dataset.shape[0]
    diff_mat = np.tile(inX,(dataset_size,1))-dataset
    sqdiff_mat = diff_mat**2
    sq_distances = sqdiff_mat.sum(axis=1)
    distances = sq_distances**0.5
    #2,按递增排序
    print(distances, 'distances')
    lis = []
    for i in distances:
        lis.append(weight(i, a=1, b=0, c=0.3))
    print(lis, 'lis')

    sorted_distances_index = distances.argsort()


    #3,选择距离最近的前k个点, 取其均值
    knnpredict = int()
    for i in range(k):
       knnpredict += dataset[sorted_distances_index[i]] * lis[sorted_distances_index[i]]

    knnpredict = knnpredict/k

    return knnpredict


    #4,返回前k个里面统计的最高次类别作为预测数值
    # return sorted_class_count[0][0]


if __name__ == '__main__':
    test()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值