KNN参数设置小实验——基于mglearn人工生成数据集(结果可视化)

  • 时间:
  • 来源:互联网
  • 文章标签:

KNN的小实验

part 1

采用mglearn包中的make_forge来训练~

make_forge数据集

turple类型,是一个二分的数据集,藏着两个array
一个array是(26,2)的X
一个array是(26,1)的y

mglearn可通过加载datasets获取人工生成的数据,也就是前缀带make的,而本文的make_forge就是人工生成的,用于学习KNN的~

我们先导入基本的包!

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn

import warnings
warnings.filterwarnings('ignore')

#观察数据
X,y = mglearn.datasets.make_forge()
mglearn.discrete_scatter(X[:,0],X[:,1],y) # 作X,y的散点分布图
plt.legend(['Class 0','Class 1'],loc = 4)
plt.xlabel("First feature")
plt.ylabel("Second feature")
print("X.shape: {}".format(X.shape))

在这里插入图片描述

#尝试画出不同K值下对所有点的预测结果。
fig,axes = plt.subplots(1,3,figsize =(10,3))
for n_neighbors,ax in zip([1,3,9],axes):
        clf = KNeighborsClassifier(n_neighbors = n_neighbors).fit(X,y)
        mglearn.plots.plot_2d_separator(clf,X,fill = True,eps=0.5,ax=ax,alpha=.4)
        mglearn.discrete_scatter(X[:,0],X[:,1],y,ax=ax)
        ax.set_title("{} neighbor(s)".format(n_neighbors))
        ax.set_xlabel("feature 0")
        ax.set_ylabel("feature 1")
axes[0].legend(loc=3)

执行之后得到下图:
在这里插入图片描述

结论

分析得到下面的结论:

当K越来越大的时候,决策边界越来越平滑。换言之,使用更少的邻居对应更高的模型复杂度,而使用更多的邻居对应更低的模型复杂度。

K=1时,测试点分类精度100%,当K=3和K=9时都分错了2个。

我们思考一个有趣的问题,假设最极端的情况,如果邻居K数等于所有数据点的个数,会怎么样?




那么每个测试点的邻居都完全相同,等于所有点,分类结果也完全一致,因为它等于一个常量,即训练集中次数最多的类别。


Part II

尝试调整参数K,找到最佳K值

以K为变量,对比训练集和测试集精度。

cancer数据集

采用的是sklearn包中的breast_cancer数据集,通过load_breast_cancer().data访问数据集内容,569*30

详细代码如下:

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

#导入cancer数据集
cancer = load_breast_cancer()
print(cancer.data.shape)#(569,30)

#训练模型
X_train,X_test,y_train,y_test = train_test_split(cancer.data,cancer.target,stratify = cancer.target,random_state = 3775)
training_accuracy = []   #初始化列表保存训练集精度
test_accuracy = []  #初始化列表保存训练集精度
neighbors_settings = range(1,11)

for n_neighbors in neighbors_settings:
    clf = KNeighborsClassifier(n_neighbors = n_neighbors)
    clf.fit(X_train,y_train)
    training_accuracy.append(clf.score(X_train,y_train))
    test_accuracy.append(clf.score(X_test,y_test))
   
#绘图                            
plt.plot(neighbors_settings,training_accuracy,label = "training accuracy")
plt.plot(neighbors_settings,test_accuracy,label = "test accuracy")
plt.ylabel("Accuracy")
plt.xlabel("n_neighbors")
plt.legend()
plt.scatter(5, 0.95, color='b')     

在这里插入图片描述
随着K的增加,训练集的精度逐渐下降,测试集在K=5取得最大逐渐趋向于平稳,后续都优于训练集,这说明该训练模型的泛化能力还是很不错的~~~
还有一个好消息,也就是不管K取什么值,测试集最差的表现也达到了90%,这个结果理论上都是可以接受的。

总结

通过几个小数据集的测试,我们发现KNN的优点比较容易理解,仅有两个参数,邻居个数K和数据点之间距离的度量方法,默认是使用欧式距离,K一般3个5个就能得到比较好的预测效果。但从part 1的分析来看,KNN对大多数取值都为0的数据集(即稀疏数据集)表现不好,因为它们的邻居都太相似了(从极端情况考虑)。由于涉及到距离的计算,量纲会有较大的影响,对异常值也敏感,因此对数据进行预处理是很重要的!

本文链接http://www.taodudu.cc/news/show-83045.html