K近邻算法

 

K近邻算法简单概述

K近邻算法采用测量不同特征值之间的距离方法进行分类

该方法的思路是:如果一个样本在特征空间中与k个实例最为相似(即特征空间中最邻近),那么这k个实例中大多数属于哪个类别,则该样本也属于这个类别。

其中,计算样本与其他实例的相似性一般采用距离衡量法。离得越近越相似,离得越远越不相似。

  • 优点:精度高,异常值不敏感,无数据输入假定
  • 缺点:计算复杂度高,空间复杂度高
  • 适用数据范围:数值型和标称型

 K近邻简述:遍历计算测试集的每个子集与训练集的距离,然后取距离最近的前K个值,再通过这K个值对应的训练集的标签(多数赞同)来决定这个子集的标签

 K近邻算法机器学习实战源码(缺点:参数只能测试集的一个数据与欧氏距离的计算)

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]  # 训练集数据个数4个
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet
    # np.tile函数
    # 瓦铺函数
    # 将inX的shape为(1,1)的拉伸为(4,2)

    sqDiffMat = diffMat ** 2  # x^2,y^2
    sqDistance = sqDiffMat.sum(axis=1)  # x^2+y^2

    distances = sqDistance ** 0.5  # 开根

    sortedDistIndicies = distances.argsort()
    # 返回其排序好的索引,索引的取值是由小到大的

    classCount = {}  # 创建分类字典
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]

        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        # 相当于 classCount[voteIlabel] = classCount[voteIlabel] +1
        # 使用get 是为了键不存在时取值为0而不是None

    sortedClassCount = sorted(classCount.items(),
                              key=operator.itemgetter(1),
                              reverse=True)
    # 最后一步:根据字典的值最多的返回其键
    # 字典无序,需要遍历 ,此行代码封装的好,但易读性弱,不建议使用
    return sortedClassCount[0][0]

 

 

 K近邻自改源码(缺点:参数只能为测试集的单一数据)

  

def classify1(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]  # 训练集数据个数
    distances = []
    for i in range(0,dataSetSize):
        d = linalg.norm(inX-dataSet[i],ord=2)
        distances.append(d)
    distances = array(distances)
    sortedDistIndicies = distances.argsort()

    classCount = {}  # 创建分类字典
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]

        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        # 相当于 classCount[voteIlabel] = classCount[voteIlabel] +1
        # 使用get 是为了键不存在时取值为0而不是None

    sortedClassCount = sorted(classCount.items(),
                              key=operator.itemgetter(1),
                              reverse=True)
    # 最后一步:根据字典的值最多的返回其键
    # 字典无序,需要遍历 ,此行代码封装的好,但易读性弱,不建议使用
    return sortedClassCount[0][0]

 

K近邻自改可适用于一个测试数据集,返回为预测结果

class KNearestNeighbor:
    def __init__(self):
        pass

    def train(self,X,y):
        self.X_train = X
        self.y_train = y

def predict(self, X, k=1):
    # 计算L2距离
    num_test = X.shape[0]  #测试样本个数
    num_train = self.X_train.shape[0]  #训练样本个数
    # because(X - X_train)*(X - X_train) = -2X*X_train + X*X + X_train*X_train, so
    d1 = -2 * np.dot(X, self.X_train.T)    # shape (num_test, num_train)
    d2 = np.sum(np.square(X), axis=1, keepdims=True)    # shape (num_test, 1)
    d3 = np.sum(np.square(self.X_train), axis=1)    # shape (1, num_train)
    dist = np.sqrt(d1 + d2 + d3)
    # 根据K值,选择最可能属于的类别
    y_pred = np.zeros(num_test)
    for i in range(num_test):
        dist_k_min = np.argsort(dist[i])[:k]    # dist[i]根据每个测试集i,
                                                # 取每个测试集与所有训练集的欧氏距离,返回k个训练集上的索引
                                                 # 最近邻k个实例位置
        y_kclose = self.y_train[dist_k_min]     # 最近邻k个实例对应的标签
        y_pred[i] = np.argmax(np.bincount(y_kclose.tolist()))    # 找出k个标签中从属类别最多的作为预测类别

    return y_pred

 

 

 

posted @ 2018-10-01 20:23  Python少年  阅读(290)  评论(0编辑  收藏  举报