更多:K最近邻算法…
3.1 K最近邻算法的原理
K最近邻算法的原理,正如我们本章标题所说——近朱者赤, 近墨者黑。想象一下我们的数据集里面有一半是“朱”(图中浅色的点),另一半是“墨”(图中深色的点)。现在有了一个新的数据点,颜色未知,我们怎么判断它属于哪一个分 类呢?如图3-1所示。
对于K最近邻算法来说,这个问题就很简单:新数据点离谁最近,就和谁属于同一类,从图3-1中我们可以看出,新数据点距离它8点钟方向的浅色数据点最近,那么理所应当地,这个新数据点应该属于浅色分类了,如图3-2所示。
看起来,K最近邻算法真是够简单的,这么轻松就完成了分类的工作。别急,我们还没说完。刚才只是举的最简单的例子,选的最近邻数等于1。但如果我们在模型训练过程中让最近邻数等于1的话,那么非常可能会犯了“一叶障目,不见泰山”的错误,试想一下,万一和新数据点最近的数据恰好是一个测定错误的点呢?
所以需要我们增加最近邻的数量,例如把最近邻数增加到3,然后让新数据点的分类和3个当中最多的数据点所处的分类保持一致,如图3-3所示。
从图3-3中我们看到,当我们令新数据点的最近邻数等于3的时候,也就是找出离新数据点最近的3个点,这时我们发现与新数据点距离最近的3个点中,有2个是深色, 而只有1个是浅色。这样一来,K最近邻算法就会把新数据点放进深色的分类当中。
以上就是K最近邻算法在分类任务中的基本原理,实际上K这个字母的含义就是最近邻的个数。在scikit-learn中,K最近邻算法的K值是通过n_neighbors 参数来调节的,默认值是5。
【注意】K最近算法也可以用于回归,原理和其用于分类是相同的。当我们使用K最近邻回归计算某个数据点的预测值时,模型会选择离该数据点最近的若干个训练数据集中的点,并且将它们的y值取平均值,并把该平均值作为新数据点的预测值。
3.2 K最近邻算法的用法
在这一小节中,我们会向大家展示K最近邻算法在分类和回归任务当中的应用,请大家准备好Jupyter notebook,和我们一起进行实验吧。
3.2.1 K 最近邻算法在分类任务中的应用
在scikit-learn中,内置了若千个玩具数据集(Toy Datasets) ,还有一-些API让我们可以自已动手生成一些数据集。接下来我们会使用生成数据集的方式来进行展示,请大家在Jupyter notebook中输入代码如下:
#ai8py.com # 导入数据集生成器 from sklearn.datasets import make_blobs # 导入KNN分类器 from sklearn.neighbors import KNeighborsClassifier # 导入画图工具 import matplotlib.pyplot as plt # 导入数据集拆分工具 from sklearn.model_selection import train_test_split # 生成样本数为200,分类为2的数据集 data=make_blobs(n_samples=200,centers=2,random_state=8) X,y=data # 将生成的数据集进行可视化 plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') plt.show()
在这段代码中,我们使用了scikit-learn 的make_ blobs 函数来生成-一个样本数量为200,分类数量为2的数据集,并将其赋值给X和y,然后我们用matplotlib将数据用图形表示出来,运行代码,会得到如图3-4所示的结果。
【结果分析】从图3-4中可以看出,make_blobs生成的数据集一共有两类,其中一类用深色表示,而另外一类用浅色表示。读者朋友可能有点疑惑:这不是已经进行好分类了吗?我们还需要K最近邻算法做什么呢?
这确实是初学者非常容易提出的问题,答案是这样的一我们这 里生成的数据集,可以看作机器学习的训练数据集,是已知的数据。我们就是基于这些数据用算法进行模型的训练,然后再对新的未知数据进行分类或者回归。
下面我们就使用K最近邻算法来拟合这些数据,输入代码如下:
import numpy as np clf=KNeighborsClassifier() clf.fit(X,y) # 下面的代码用于画图 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,.02),np.arange(y_min,y_max,.02)) Z=clf.predict(np.c_[xx.ravel(),yy.ravel()]) Z=Z.reshape(xx.shape) plt.pcolormesh(xx,yy,Z,cmap=plt.cm.Pastel1) plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolors='k') plt.xlim(xx.min(),xx.max()) plt.ylim(yy.min(),yy.max()) plt.title("Classifier:KNN") plt.show()
运行代码,会得到如图3-5所示的结果。
【结果分析】从图3-5中我们可以看到,K最近邻算法基于数据集创建了一个分类模型,就是图中粉色区域和灰色区域组成的部分。那么如果有新的数据输入的话,模型就会自动将新数据分到对应的分类中。
例如,我们假设有一个数据点,它的两个特征值分别是6.75和4.82,我们来试验下模型能不能将它放到正确的分类中,首先我们可以在上面那段代码中,plt.show() 之前加一行代码如下:
# 新的数据点用五星表示出来 plt.scatter(6.75,4.82,marker="*",c="red",s=200)
再次运行代码,会得到结果如图3-6所示。
【结果分析】图3-6中五角星就代表了新的数据点所在的位置,可以看到K最近邻算法将它放在了下方的区域,和浅色的数据点归为了一类。
下面我们再验证一下,输入代码如下:
# 对新数据点分类进行判断 print('\n\n\n') #这一行代码主要是为了让截图好看一些 print("代码运行结果:") print("====================") print("新数据点的分类是:",clf.predict([[6.75,4.82]])) print("====================") print('\n\n\n') #这一行代码主要是为了让截图好看一些
运行代码,我们将得到结果如图3-7所示
【结果分析】看起来,K最近邻算法的工作成果还是很不错的,不过这可能是因为我们这次的任务有点太简单了。下面我们给它增加一- 点难度一处理多元分类任务。