K邻近分类(python实现)

导入

  • 今天学习了《统计学习方法》中的K邻近法,参考刘建平老师的博客,使用python进行分类实现。
  • 推荐一下刘建平老师写的K邻近法总结,写的真的很好。
  • 这里对K邻近法的原理不再赘述,感兴趣的读者可以自行学习。
  • 本人学术水平有限,有错误的地方还请大家指出。

算法实现

导入包

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import make_blobs
# 忽略警告
import warnings 
warnings.filterwarnings("ignore")

数据准备

  • 这里使用make_blobs()函数产生数据集。函数中各参数含义如下表:
参数含义
n_features每一样本包含的特征值
n_samples样本的个数
centers聚类中心点的个数,可以理解为label的种类数
random_state随机种子,可以固定的数据
cluster_std设置每个类别的方差
  • 我这里X为样本特征,Y为样本类别输出;共1000个样本,每个样本2个特征,输出有3个类别,没有冗余特征,每个类别一个簇,随机种子为40。
X, Y = make_blobs(n_samples=1000, 
                  n_features=2,
                  cluster_std=1, 
                  centers=3, 
                  random_state = 40)
plt.scatter(X[:, 0], X[:, 1], marker='o', c=Y)
#plt.savefig('随机样本散点图.png')
plt.show()

输出:
请添加图片描述

建立KNN分类模型并调参

  • KNN算法中各类参数的作用参考刘建平老师的博客:scikit-learn K近邻法类库使用小结
  • 根据《统计学习方法》k邻近法的三个要素:k值的选择距离度量分类决策,这里使用GridSearchCV函数进行网格最优参搜索
    • k值(n_neighbors):以10为初始值,步长为10,终值为100
    • 近邻权(weights)uniformdistance
    • 使用的算法(algorithm)brute
    • 距离度量(metric)euclidean(欧式距离),manhattan(曼哈顿距离),minkowski(闵可夫斯基距离)
  • 10折交叉检验训练,这里需要注意的是GridSearchCV函数中的scoring参数,即评估模型分数指标,我这里选择的是f1_microF1值中的一种变体。也可以选择其他评估模型的方法,比如准确率accuracy
  • 分类算法模型评估方法(scoring参数)
参数含义
accuracymetrics.accuracy_score
average_precisionmetrics.average_precision_score
f1metrics.f1_score
f1_micrometrics.f1_score
f1_macrometrics.f1_score
f1_weightedmetrics.f1_score
f1_samplesmetrics.f1_score
neg_log_lossmetrics.log_loss
precision etc.metrics.precision_score
recall etc.metrics.recall_score
roc_aucmetrics.roc_auc_score
  • 回归算法模型评估方法(scoring参数)
参数含义
neg_mean_absolute_errormetrics.mean_absolute_error
neg_mean_squared_errormetrics.mean_squared_error
neg_median_absolute_errormetrics.median_absolute_error
r2metrics.r2_score
from sklearn import neighbors
from sklearn.model_selection import GridSearchCV
param_grid = [{'n_neighbors' : np.arange(10,101,10),
               'weights' : ['uniform','distance'],
               'algorithm' : ['brute'],
               'metric' : ['euclidean','manhattan','minkowski']}]
KNN_class = neighbors.KNeighborsClassifier()
grid_search = GridSearchCV(KNN_class,
                           param_grid,
                           cv = 10,
                           scoring = 'f1_micro',
                          return_train_score = True)
grid_search.fit(X,Y)

输出:

GridSearchCV(cv=10, estimator=KNeighborsClassifier(),
             param_grid=[{'algorithm': ['brute'],
                          'metric': ['euclidean', 'manhattan', 'minkowski'],
                          'n_neighbors': array([ 10,  20,  30,  40,  50,  60,  70,  80,  90, 100]),
                          'weights': ['uniform', 'distance']}],
             return_train_score=True, scoring='f1_micro')

最优模型参数

  • 显示最优模型参数
final_model = grid_search.best_estimator_
grid_search.best_params_

输出:

{'algorithm': 'brute',
 'metric': 'euclidean',
 'n_neighbors': 80,
 'weights': 'uniform'}
  • 可以看到各最优参分别为:k值:80,距离度量:euclidean,权重:uniform,算法:brute

显示网格搜索模型分数

  • 网格搜索中各参数的组合应该有 10 × 3 × 2 = 60 10 \times 3 \times 2 = 60 10×3×2=60种,即分数也有60个,这里由于篇幅原因仅展示部分。
cvres = grid_search.cv_results_
for f,params in zip(cvres["mean_test_score"],cvres["params"]):
    print("{:.2}".format(f),params)

输出:

0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 10, 'weights': 'uniform'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 10, 'weights': 'distance'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 20, 'weights': 'uniform'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 20, 'weights': 'distance'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 30, 'weights': 'uniform'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 30, 'weights': 'distance'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 40, 'weights': 'uniform'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 40, 'weights': 'distance'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 50, 'weights': 'uniform'}
0.99 {'algorithm': 'brute', 'metric': 'euclidean', 'n_neighbors': 50, 'weights': 'distance'}
...

预测

  • 这里首先确认训练集的边界,然后生成随机数组使用最优模型进行预测
from matplotlib.colors import ListedColormap
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])

#确认训练集的边界
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
#生成随机数据来做测试集,然后作预测
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                         np.arange(y_min, y_max, 0.02))
# final_model为最优模型
Z = final_model.predict(np.c_[xx.ravel(), yy.ravel()])

可视化

  • 使用matplotlib包对预测情况进行可视化。
# 画出测试集数据
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)

# 也画出所有的训练集数据
plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=cmap_bold)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("3-Class classification (k = 80, weights = 'uniform')" )
#plt.savefig('预测效果.png')

输出:

请添加图片描述

结语

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羽星_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值