k近邻法的实现

k近邻法

模型

  • 使用的模型实际上对应于特征空间的划分.模型的三个基本要素:
    1.距离度量
    2. k值的选择
    3. 分类决策规则决定.
  • k值的选择:k值的选择,k如果选择的过小会导致过拟合,模型会变得复杂.
  • 思想脉络
  • 方法的流程简述:
    给定一个训练数据集,对于新的输入实例,在训练数据集中找到与之最临近的k个实例,这k个实例的多数属于某个类,
    就把实例分为这个类.
    这个算法没有显示的训练过程,应用的过程就是训练的过程

算法推导

  • 1 公式推导
    无显示的算法推导过程.
    要注意的是,不同的距离度量所确定的最近邻点是不同的
    欧式距离,曼哈顿距离,以及闵科夫斯基距离.
  • 2.算法实现方法
    一种是线性扫描,计算输入实例与每一个训练实例的距离,但是当训练集很大的时候,计算非常耗时.
    一种是利用特殊的结构存储训练数据.减少计算距离的次数的kd树方法.
  • kd树方法:
    减少搜索的计算量.
    我的理解就是先根据一个坐标轴的值,划分一个二叉树,然后遍历二叉树进行最小点的比较.找出距离最小的点.
    kd树的详细介绍:

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

编程实现

  • 0.自己编程实现,自己构造数据
# date&time:2018.05.23
# review :2018.09.21
# @author :Danny 
import numpy as np
def create_data():
    """
    return : the train and test data
    """
    train_data=np.array([[1.0,1.1,1],[1.0,1.0,1],[0,0,-1],[0,0.1,-1]])
    x_test=np.array([1,1])
    return train_data,x_test

def kNN(train_data,x_test,k):
    """
    type train_data:np.array([[x,y,c]])
    type k: the k values
    return the label of x_test
    """
    x=train_data[:,0:2]
    label=train_data[:,2]
    diff=x-x_test
    distance=np.sqrt(np.sum(diff**2,axis=1))
    sort_distance_index=distance.argsort()   # 将距离按大小顺序提取下标index ,这样就可以利用下标取相对应的label值.
    class_label_count={}
    # start to voting the label
    for i in range(k):
        vote_label=label[sort_distance_index[i]]
        if vote_label not in class_label_count: # 典型的字典计数办法.
            class_label_count[vote_label]=0
        class_label_count[vote_label]+=1
    return max(class_label_count,key=class_label_count.get)  # 返回字典中values值最大所对应的key ,也就是需要找的class_label

if __name__=="main":
    train_data,x_test=create()
    k=1
    result_label=kNN(train_data,x_test,k)
    print("the test_data label:{}".format(result_label))
  • 1.对于小数量集合的线性扫描的方法
"""
date&time :2018.05.23    不要浮躁,静下心来 慢慢学习.
@author:Peter 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
  • 还存在两个主要问题:
    1.K值在利用cross-validation的选择问题
    2.voting 方法的使用及编程实现.

kd树实现kNN

kd_tree实现

# 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
全部评论

相关推荐

11-22 16:49
已编辑
北京邮电大学 Java
美团 质效,测开 n*15.5
点赞 评论 收藏
分享
10-30 22:18
已编辑
毛坦厂中学 C++
点赞 评论 收藏
分享
头像
11-09 17:30
门头沟学院 Java
TYUT太摆金星:我也是,好几个华为的社招找我了
点赞 评论 收藏
分享
最近又搬回宿舍了,在工位坐不住,写一写秋招起伏不断的心态变化,也算对自己心态的一些思考表演式学习从开始为实习准备的时候就特别焦虑,楼主一开始选择的是cpp后端,但是24届这个方向已经炸了,同时自己又因为本科非92且非科班,所以感到机会更加迷茫。在某天晚上用java写出hello&nbsp;world并失眠一整晚后选择老本行干嵌入式。理想是美好的,现实情况是每天忙但又没有实质性进展,总是在配环境,调工具,顺带还要推科研。而这时候才发现自己一直在表演式学习,徘徊在设想如何展开工作的循环里,导致没有实质性进展。现在看来当时如果把精力专注在动手写而不是两只手端着看教程,基本功或许不会那么差。实习的焦虑5月,楼主...
耶比:哲学上有一个问题,玛丽的房间:玛丽知道眼睛识别色彩的原理知道各种颜色,但是她生活在黑白的房间里,直到有一天玛丽的房门打开了她亲眼看到了颜色,才知道什么是色彩。我现在最大可能的减少对非工作事情的思考,如果有一件事困扰了我, 能解决的我就直接做(去哪里或者和谁吵架等等……),解决不了的我就不想了,每一天都是最年轻的一天,珍惜今天吧
投递比亚迪等公司10个岗位 > 秋招被确诊为…… 牛客创作赏金赛
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务