k近邻(k-Nearest Neighbor,简称k-NN)学习是一种常用的监督学习方法,是懒惰学习的著名代表(没有显式的训练过程,在训练阶段仅仅把样本保存起来,训练时间开销为0,待收到测试样本时再进行处理),是非参数方法。
工作机制:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个的信息来进行预测。对于分类任务:使用投票法,即选择这k个样本中出现最多的类别标记作为预测结果;对于回归任务:使用平均法,即将这k个样本的实值输出标记的平均值作为预测结果。还可以基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。
错误率:, 其中是贝叶斯最优分类器的错误率。且在k<<N, N很大时,k越大,Pk越小。
不足:1.需要巨大的存储和计算(需要存储所有的训练样本;需要和所有的样本作比较); 2.投票法会很危险,比如有噪声样本时。(改进:当投票过于近时拒绝,带有权重的投票); 3.训练集样本量N太小时效果不好。
k-NN python实现举例(sklearn):
sklearn中已经实现了KNN算法,其模型函数是KNeighborsClassifier()
函数及参数说明:
#函数中的参数值皆为默认值
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, weights=’uniform’, algorithm=’auto’, leaf_size=30,p=2, metric=’minkowski’, metric_params=None, n_jobs=1, **kwargs)
#参数说明:
1)n_neighbors int型参数;knn算法中指定以最近的几个最近邻样本具有投票权。
2)weights str参数;即每个拥有投票权的样本是按什么比重投票,'uniform'表示等比重投
票,'distance'表示按距离反比投票,[callable]表示自己定义的一个函数,这个函数接收一个距离数组,返回一个权值数组。
3)algorithm='auto' str参数;即内部采用什么算法实现,['auto', 'ball_tree', 'kd_tree', 'brute']。
'brute':暴力搜索;默认'auto':自动根据数据选择合适的算法。一般低维数据用kd_tree速度
快,用ball_tree相对较慢。超过20维的高维数据用kd_tree效果不佳,而ball_tree效果好。
4)leaf_size int参数;基于以上介绍的算法,此参数给出了kd_tree或者ball_tree叶节点规模,叶节点的
不同规模会影响数的构造和搜索速度,同样会影响储树的内存的大小。
5)matric str参数或者距离度量对象;即怎样度量距离。默认是闵氏距离minkowski。
6)p int参数;就是以上闵氏距离各种不同的距离参数,默认为2,即欧氏距离。p=1代表曼哈顿距离等
7)metric_params 距离度量函数的额外关键字参数,一般不用管,默认为None。
8)n_jobs int参数;指并行计算的线程数量,默认为1表示一个线程,为-1的话表示为CPU的内核数,也可指定为其他数量的线程。
代码示例(以k, weight两个参数为例选取使得结果最好的参数):
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.neighbors import KNeighborsClassifier
#读取训练集数据并归一化处理,得train_features,train_labels
my_matrix = pd.read_csv('E:/ACourse/MachineLearning/homework/Computer_exercise1/Ex1_20200916/data1/train_hf_data.csv',header=0)
scaler = MinMaxScaler()
scaler.fit(my_matrix)
data = scaler.transform(my_matrix)
train_features = data[0::,1::]
raw_data_labels = pd.read_csv('E:/ACourse/MachineLearning/homework/Computer_exercise1/Ex1_20200916/data1/train_hf_label.csv',header=0)
data_labels = raw_data_labels.values
train_labels = data_labels[0::,1]
#读取测试集并归一化处理,得test_features,data_test_labels
my_matrix_test = pd.read_csv('E:/ACourse/MachineLearning/homework/Computer_exercise1/Ex1_20200916/data1/test_hf_data.csv',header=0)
data_test = scaler.transform(my_matrix_test)
test_features = data_test[0::,1::]
test_data_labels = pd.read_csv('E:/ACourse/MachineLearning/homework/Computer_exercise1/Ex1_20200916/data1/test_hf_label.csv',header=0)
data_labels = test_data_labels.values
data_test_labels = data_labels[0::,1]
# 用训练集构建kNN,根据测试集寻找最好的k,weights,输出测试集正确率
best_k=-1
best_score=0
best_method=''
for method in ['uniform','distance']:
for i in range(1,11):
knn_clf=KNeighborsClassifier(n_neighbors=i,weights=method)#多个超参
knn_clf.fit(train_features,train_labels)
scores=knn_clf.score(test_features,data_test_labels)
if scores>best_score:
best_score=scores
best_k=i
best_method=method
print('最好的k为:%d,最好的得分为:%.4f,最好的方法%s'%(best_k,best_score,best_method))