第三章 K 近邻法 (kNN 以及kd-tree)

k近邻法

基础知识

1 模型

使用的模型实际上对应于特征空间的划分.模型的三个基本要素:

距离度量 , k值的选择 , 分类决策规则决定.

思想脉络

1 方法的流程简述

给定一个训练数据集,对于新的输入实例,在训练数据集中找到与之最临近的k个实例,这k个实例的多数属于某个类,
就把实例分为这个类.

这个算法没有显示的训练过程,应用的过程就是训练的过程

算法推导

1 公式推导

无显示的算法推导过程.

要注意的是,不同的距离度量所确定的最近邻点是不同的

欧式距离,曼哈顿距离,以及闵科夫斯基距离.

2.算法实现方法

一种是线性扫描,计算输入实例与每一个训练实例的距离,但是当训练集很大的时候,计算非常耗时.

一种是利用特殊的结构存储训练数据.减少计算距离的次数, kd树方法.

kd树方法:

减少搜索的计算量.

我的理解就是先根据一个坐标轴的值,划分一个二叉树,然后遍历二叉树进行最小点的比较.找出距离最小的点.

kd树的详细介绍:
kd树是每个节点均为k维数值点的二叉树,每个节点代表一个超平面,朝平面垂直于当前划分维度的坐标轴,在该维度上
将空间划分为两个部分,一部分在右子树,一部分在左子树.

编程实现

1.对于小数量集合的线性扫描的方法

"""
date&time :2018.05.23    不要浮躁,静下心来 慢慢学习.
@author:DengShuo and Danny

kNN  implement with kd_tree.

in the first place ,follow the machine learning in action  kNN algorithms,and comprehensions the principle.
"""
# classify function
from numpy import *
import operator
import os
def classify(inX,dataSet,labels,k):
    """
    :param inX: vector to compare to existing dataset (1xN)
    :param dataSet: size m data set of known vectors (NxM)
    :param labels:  data set labels (1xM vector)
    :param k: number of neighbors to use for comparison (should be an odd number)
    :return: sortedClassCount
    """
    dataSetSize=dataSet.shape[0]
    diffMat=tile(inX,(dataSetSize,1))-dataSet
    sqDiffMat=diffMat**2
    sqDistances=sqDiffMat.sum(axis=1)
    Distance=sqDistances**0.5
    sortedDistances=Distance.argsort()     # return a distance elements index in sorted
    classCount={}                          # define a dictionary
    for i in range(k):
        voteIlabel=labels[sortedDistances[i]]   # don't how to extract the label
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
    sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]          # return the voting label

# construct dataSet
def createDataSet():
    """
    :return: the group and labels
    """
    group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels=['A','A','B','B']
    return group,labels

if __name__=='__main__':
    group,labels=createDataSet()
    result=classify([1.0,1.2],group,labels,3)
    print("the label :{}".format(result))
    print("\n dating site with kNN \n")
the label :A

 dating site with kNN 

主要还算理解这个方法的内在计算原理

有意思的是看见一个实现两点之间距离公式的函数
能不能应用到上面的函数中:

points=[(1,2),(3,4),(5,6),(7,8)] # tuple
import math 
def distance(p1,p2):
   x1,y1=p1
   x2,y2=p2
   return math.hypot(x2-x1,y2-y1)

2.kd树实现kNN

# kd 树的构建代码
def kd_tree(points,depth):
    if len(points)==0:
        return None
    cutting_dim=depth%len(points[0]) # 切分的维度数
    # 这一段构建代码不是很懂.
    medium_index=len(points)//2
    points.sort(key=itemgetter(cutting_dim))
    node=Node(points[medium_index])
    node.left=kd_tree(points[:medium_index],depth+1)
    node.right=kd_tree(points[medium_index+1:],depth+1)
    return node

# 寻找最小坐标值点,利用递归

def findmin(n,depth,cutting_dim,min):
    if min is None:
        min=n.location
    if n is None:
        return min 
    current_cutting_dim=depth%len(min)
    if n.location[cutting_dim]<min[cuting_dim]:
        min=n.location
    if cutting_dim==current_cutting_dim:
        return findmin(n.left,depth+1,cutting_dim,min)
    else:
        leftmin=findmin(n.left,depth+1,cutting_dim,min)
        rightmin=findmin(n.right,depth+1,cutting_dim,min)
        if leftmin[cutting_dim]>rightmin[cutting_dim]:
            return rightmin
        else:
            return leftmin

先理解概念,等到需要的时候再进行学习.知识点太多,有点看不完.
链接:https://leileiluoluo.com/posts/kdtree_algorithm
当然 sklearn 也可以进行实现.

这里还有一份打印出的文档,基本没咋看懂.kd_tree 可以结合决策树那一版块来进行学习.

猜你喜欢

转载自blog.csdn.net/qq_37904945/article/details/80495948