K-近邻算法

K-近邻算法 👉 KNeighborsClassifier

原理

  如果一个样本在 特征空间中的 k个值 (即特征空间中邻近)的 样本中的 大多数 属于某一个类别 , 则该样本也属于这个类别。也理解为:离谁最近,与谁一样。找K个最近的点 , 看这k个点中 , 类别最多的那个类别。 

  特别需要注意的是 : 运行k-近邻算法之前,必须做标准化处理!!!


K-近邻算法步骤 :

我们可以从 最近邻算法 , 来推演 k近邻算法, 其步骤是 :

  • 计算已知类别数据集中的点与当前点之间的距离
  • 按照距离递增次序排序
  • 选取与当前距离最小的k个点
  • 确定前k个点所在类别的出现频率
  • 返回前k个点所在频率最高的类别作为当前点的预测分类

由此可知 , k近邻算法其实本质上并不是以最近的点为分类, 而是以最近的k个点的分类出现的概率最高为分类, 这点跟我们在spss逻辑回归中的思路是一致的。

 

k-近邻算法特点:

  • 优点
      • 简单好用, 容易理解, 精度高, 理论成熟, 既可以用来做分类也可以用来做回归; 可用于数值型数据和离散型数据; 训练时间复制为O(n); 无数据输入假定; 对异常值不敏感。
  • 缺点
      • 计算复杂性高; 空间复杂性高; 样本不平衡问题(即有些类别的样本数量很多, 而其他样本的数量很少); 一般数值很大的时候不用这个, 计算量太大。 但是单个样本数不能太少, 否则容易发生误分。 最大的缺点是无法给出数据的内在含义。

k-近邻算法API:

# 导入及参数
from sklearn.neighbors.KNeighborsClassifier(
        n_neighbors=5,  # int, 可选参数(默认为 5)
        weights='uniform',  #  参数有‘uniform’和‘distance’,可以选择调试。
        algorithm='auto',   #算法 {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, 可选参数(默认为 'auto')
        leaf_size=30,   #叶子数量 int, 可选参数(默认为 30)
        p=2,   # integer, 可选参数(默认为 2)
        metric='minkowski',   #矩阵 string or callable, 默认为 ‘minkowski’
        metric_params=None,   #矩阵参数 dict, 可选参数(默认为 None)
        n_jobs=None,   #int, 可选参数(默认为 1) 用于搜索邻居的,可并行运行的任务数量。如果为-1, 任务数量设置为CPU核的数量。
        **kwargs,   # 
)

案例( 项目说明) :  

海伦女士一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的任选,但她 并不是喜欢每一个人。
经过一番总结,她发现自己交往过的人可以进行如下分类:不喜欢的人;魅力一 般的人;极具魅力的人。 海伦收集约会数据已经有了一段时间,每个样本数据占据一行,总共有1000行。
海伦收集的样本数据主要包含以下3种特征:每年获得的飞行常客里程数;玩视频游戏所消耗时间 百分比;每周消费的冰淇淋公升数。 请通过这些数据进行机器学习,用来预测海伦对下一个约会对象的感觉。
 1 from sklearn.neighbors import KNeighborsClassifier 
 2 from sklearn.model_selection import train_test_split 
 3 from sklearn.preprocessing import MinMaxScaler
 4 # 读取数据 
 5 import pandas as pd import numpy as np
 6 data = np.loadtxt('datingTestSet.txt', dtype=np.object, delimiter='\t', encoding='gbk') df = pd.DataFrame(data)
 7 # 获取特征值 
 8 x = df.iloc[:,:3] 
 9 # 获取目标值 
10 y = df[3]
11 # 特征工程 
12 # 归一化 
13 scaler = MinMaxScaler() 
14 x = scaler.fit_transform(x)
15 # 分割数据集 
16 train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.25)
17 # knn 
18 kn = KNeighborsClassifier(n_neighbors=30) 
19 # 选择500个邻居 
20 kn.fit(train_x, train_y)
21 # 得出预测结果 
22 predict = kn.predict(test_x) 
23 print('预测结果为:', predict)
24 #  得出准确率 
25 print('------------ >测试集正确率: {0}\n'.format(round(kn.score(test_x,test_y),3))) 
26 print('------------ >训练集正确率: {0}\n'.format(round(kn.score(train_x,train_y),3))) 
27 print('------------ >全集正确率:{0}\n'.format(round(kn.score(x,y),3)))
28 # 模型的保存 
29 from sklearn.externals import joblib 
30 joblib.dump(kn, 'kn.m')
31 
32 #---------分界线-------------#
33 # 调用保存好的模型
34 from sklearn.externals import joblib
35 kn_new = joblib.load('kn.m')
36 # 预测样本归一化 
37 scaler = MinMaxScaler() 
38 s = ([12,44000,0.5],[0.1,200,0.8],[68,32000,0.3]) 
39 s = scaler.fit_transform(s)  
40 kn_new.fit(s)
案例代码

 

为什么要对预测样本做归一化?

  预测样本数据没有归一化会导致分类成为同一类别,由于维度太大,如果不采用归一化处理的话,各个点的距离值将非常大,故模型对于待测点的预测结果值都判为同一个。


K-近邻算法 总结 :

  • k值的取值问题
      • K值取多大?有什么影响?
        • k值取很小:容易受异常的影响
        • k值取很大:容易受到k值数量(类别)波动
  • 性能问题
      • 如果样本越来越大, 算法时间、空间复杂度都会越来越大
  • 优点
      • 简单, 易于理解, 易于实现, 无需估计参数, 无需训练
  • 缺点
      • 懒惰算法, 对测试样本分类时的计算量大, 内存开销大, 必须指定k值, k值选择不当则分类精确度不能保证
  • 使用场景  
      • 小数据场景,几千~几万样本, 具体场景 具体业务去测。

 

 

 

 

 

posted @ 2019-12-06 00:02  逍遥大帝  阅读(812)  评论(0编辑  收藏  举报