zoukankan      html  css  js  c++  java
  • 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("
     dating site with kNN 
    ")
    
    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
    
    不要用狭隘的眼光看待不了解的事物,自己没有涉及到的领域不要急于否定. 每天学习一点,努力过好平凡的生活.
  • 相关阅读:
    Theme.AppCompat.Light报错
    在Eclipse添加Android兼容包( v4、v7 appcompat )
    如何从Eclipse导入github上的项目源码
    一个C#多线程的工作队列
    是否需要手动执行DataContext的Dispose方法?
    Unity3d 销毁
    Unity3d 碰撞检测
    unity3d 鼠标事件
    Unity3d 刚体
    unity3d 让物体移动到点击位置
  • 原文地址:https://www.cnblogs.com/GeekDanny/p/9220616.html
Copyright © 2011-2022 走看看