KNN算法初识

一、算法介绍

KNN算法中文名称叫做K近邻算法,全称是k-NearestNeighbor。KNN是众多机器学习算法里面最基础入门的算法。它是一个有监督的机器学习算法,既可以用来做分类任务也可以用来做回归任务。KNN算法的核心思想是未标记的样本的类别,由距离他最近的K个邻居投票来决定。下面我们来看个例子加深理解一下:



如上图所描述张三要参加一家公司的面试,他通过各种渠道了解到了一些工作年限和工资之间对应的关系以及在这种条件下他们是否获取到了offer的情况。让我们来预测一下张三是否能够拿到他这家公司的offer吧?当K-近邻中的K选择为1的时候我们看下结果。张三不可以拿到offer。



当我们选择K的值为3的时候,张三拿到了offer。

同理当我们选择K的值为5的时候呢?张三被分类到了拿不到offer的类别上了。


KNN算法的优点是原理简单易懂和天然可处理多分类的问题。但是它的缺点也非常明显,在所有的计算都在预测的时候进行,属于”急切学习“会比较耗内存,由于算法假设采样密度足够大,所以当维度比较多时,样本量需求会比较大,计算距离都会比较困难,当然这属于所有机器学习方法的共同问题,被称为”维度灾难“,但是由于KNN把所有的计算都放到了一起,所以问题可能会更为突出。所以可以采用降维的方法来处理。

说到这里是不是感觉和Kmeans很像?但是他们两个是有区别的:


那么我们就来看看KNN的伪代码吧:

# 根据距离计算方法(method)计算距离
def get_distance(data_x,input_X,method):
    compute distance 
    return data['d']

# 计算到所有的距离
def compute_distance(data,input_X,method):
    data['d'] = get_distance(data_x,input_X,method = method)
    return data['d']

# 获取 knn
def get_knn(data,input_X,k,x_columns):
    data['d'] =  compute_distance(data[x_columns],input_X,method)
     data_knn = get_knn_data(data,k)
     return data_knn

# 整合结果,计算出现的类别或者均值
def get_final_result(data,input_X,k,x_columns,y_column ):
    data_knn = get_knn(data,input_X,k)
    data_result = data_knn[y_column].count().sorted()[-1] 
    # data_result = data_knn[y_column].means()
    # 输出最终结果
    print(data_result)
# 主函数
def main():
    x_columns = ['a','b','c']
    y_column = ['hia']
    get_final_result(data,input_X,k,x_columns,y_column )

二、KNN算法代码实现

#-*-coding:utf-8 -*-
from sklearn import datasets  
#导入内置数据集模块                      
from sklearn.neighbors import KNeighborsClassifier 
#导入sklearn.neighbors模块中KNN类
import numpy as np 
np.random.seed(0)  
#设置随机种子,不设置的话默认是按系统时间作为参数,因此每次调用随机模块时产生的随机数都不一样设置后每次产生的一样
iris=datasets.load_iris() 
#导入鸢尾花的数据集,iris是一个类似于结构体的东西,内部有样本数据,如果是监督学习还有标签数据
iris_x=iris.data   
 #样本数据150*4二维数据,代表150个样本,每个样本4个属性分别为花瓣和花萼的长、宽
iris_y=iris.target  
#长150的以为数组,样本数据的标签
indices = np.random.permutation(len(iris_x)) 
#permutation接收一个数作为参数(150),产生一个0-149一维数组,只不过是随机打乱的,当然她也可以接收一个一维数组作为参数,结果是直接对这个数组打乱
iris_x_train = iris_x[indices[:-10]]
 #随机选取140个样本作为训练数据集
iris_y_train = iris_y[indices[:-10]] 
#并且选取这140个样本的标签作为训练数据集的标签
iris_x_test  = iris_x[indices[-10:]]
 #剩下的10个样本作为测试数据集
iris_y_test  = iris_y[indices[-10:]] 
#并且把剩下10个样本对应标签作为测试数据及的标签

knn = KNeighborsClassifier() 
#定义一个knn分类器对象
knn.fit(iris_x_train, iris_y_train)  
#调用该对象的训练方法,主要接收两个参数:训练数据集及其样本标签

iris_y_predict = knn.predict(iris_x_test) 
 #调用该对象的测试方法,主要接收一个参数:测试数据集
probility=knn.predict_proba(iris_x_test)  
 #计算各测试样本基于概率的预测
neighborpoint=knn.kneighbors(iris_x_test[-1],5,False)
#计算与最后一个测试样本距离在最近的5个点,返回的是这些样本的序号组成的数组
score=knn.score(iris_x_test,iris_y_test,sample_weight=None)
#调用该对象的打分方法,计算出准确率

print('iris_y_predict = ')  
print(iris_y_predict)  
#输出测试的结果

print('iris_y_test = ')
print(iris_y_test)    
#输出原始测试数据集的正确标签,以方便对比
print ('Accuracy:',score)  
#输出准确率计算结果
print('neighborpoint of last test sample:',neighborpoint)
 
print('probility:',probility)
***********************************
结果输出:
iris_y_predict = 
[1 2 1 0 0 0 2 1 2 0]
iris_y_test = 
[1 1 1 0 0 0 2 1 2 0]
Accuracy: 0.9
neighborpoint of last test sample: [[ 75  41  96  78 123]]
probility: [[ 0.   1.   0. ]
        [ 0.   0.4  0.6]
        [ 0.   1.   0. ]
        [ 1.   0.   0. ]
        [ 1.   0.   0. ]
        [ 1.   0.   0. ]
        [ 0.   0.   1. ]
        [ 0.   1.   0. ]
        [ 0.   0.   1. ]
        [ 1.   0.   0. ]]

三、使用KNN算法需要注意的地方

1、大数吞小数

在进行距离计算的时候,有时候某个特征的数值会特别的大,那么计算欧式距离的时候,其他的特征的值的影响就会非常的小被大数给覆盖掉了。所以我们很有必要进行特征的标准化或者叫做特征的归一化。

2、如何处理大数据量

一旦特征或者样本的数目特别的多,KNN的时间复杂度将会非常的高。解决方法是利用KD-Tree这种方式解决时间复杂度的问题,利用KD树可以将时间复杂度降到O(logDNN)。D是维度数,N是样本数。但是这样维度很多的话那么时间复杂度还是非常的高,所以可以利用类似哈希算法解决高维空间问题,只不过该算法得到的解是近似解,不是完全解。会损失精确率。

3、怎么处理样本的重要性

利用权重值。我们在计算距离的时候可以针对不同的邻居使用不同的权重值,比如距离越近的邻居我们使用的权重值偏大,这个可以指定算法的weights参数来设置。

四、总结

KNN是一个比较简单的算法,它适合在低维度空间中使用,数据量太大预测时间高,所以需要对大数据量进行一定的处理。

你可能感兴趣的:(KNN算法初识)