最新版学习笔记---Python机器学习基础教程(2)k近邻(K-NN)算法---附完整代码

正在学习书上的内容,书上有部分代码没有给全,注解不详细,且随着版本原因出现的问题有所调整,所以写下学习笔记供大家参考。

1.环境搭建

python版本最好是3.6.x及以上,我这里用的是3.7.1版本
安装有机器学习库sklearn、mglearn、matplotlib、numpy,若没有用pip安装

pip install sklearn
pip install mglearn
pip install matplotlib
pip install numpy

2.目前会出现的问题

因为是否维护和函数迭代的原因,会出现下面情况:
D:\Python37\lib\site-packages\sklearn\externals\six.py:31: FutureWarning: The module is deprecated in version 0.21 and will be removed in version 0.23 since we’ve dropped support for Python 2.7. Please rely on the official version of six (https://pypi.org/project/six/).
“(https://pypi.org/project/six/).”, FutureWarning)
D:\Python37\lib\site-packages\sklearn\externals\joblib_init_.py:15: FutureWarning: sklearn.externals.joblib is deprecated in 0.21 and will be removed in 0.23. Please import this functionality directly from joblib, which can be installed with: pip install joblib. If this warning is raised when loading pickled models, you may need to re-serialize those models with scikit-learn 0.21+.
warnings.warn(msg, category=FutureWarning)
D:\Python37\lib\site-packages\sklearn\utils\deprecation.py:87: FutureWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
warnings.warn(msg, category=FutureWarning)

  • 目前不用理会,因为这里提示的是未来错误提示,也就是有的函数未来不会再使用或者维护,会出现进阶版的函数替换,到时候根据说明文档更改,或者直接pip install --upgrade XXX 下载最新版就可以了,现在不用处理。

我们再来理解一下几个基本概念:

  • 泛化:一个模型能够对没见过的数据做出准确预测,就说模型能够从训练集泛化(generalize)到测试集
  • 过拟合:模型过于复杂.过分关注训练集的细节,得到在训练集上表现过好,但不能泛化到新数据上.
  • 欠拟合:模型过于简单,在训练集上的表现就很差

3.可视化将要处理的样本数据集

3.1 forge数据集

一个模拟的二分类数据集示例是forge数据集,它本身有两个特征。
运行代码如下:

import mglearn
import matplotlib.pyplot as plt
#生成数据集
X,y=mglearn.datasets.make_forge()
#数据集绘图
#将输入X的第一列作为x轴,第二列作为y轴,输出y的作用是根据x轴与y轴坐标区别类别
mglearn.discrete_scatter(X[:,0],X[:,1],y)
#给图像加上图例,传入参数loc的值从0开始,设置图例的位置,感兴趣的可以自己试试
plt.legend(["Class 0","Class 1"],loc=0)
#定义x轴与y轴标签,这里分别对应两个特征
plt.xlabel("First feature")
plt.ylabel("Secong feature")
plt.show()

效果图:
在这里插入图片描述

3.2 wave数据集

wave数据集用来说明回归算法。它本身只有一个输入特征和一个连续的目标变量(或响应),后者是模型想要预测的对象。
运行代码如下:

import mglearn
import matplotlib.pyplot as plt
#生成数据集
X,y=mglearn.datasets.make_wave(n_samples=40)#生成点的数
plt.plot(X,y,'o')
plt.ylim(-3,3)
plt.xlabel("Feature")
plt.ylabel("Target")
plt.show()

其中

plt.plot(X,y,‘o’)——>plt.plot(x,y,format_string,**kwargs)

传入参数format_string具体用法加下表:

字符 作用 字符 作用
r 红色 ‘^’ 上三角标记
g 绿色 ‘>’ 右三角标记
b 蓝色 ‘<’ 左三角标记
y 黄色 ‘1’ 下花三角标记
k 黑色 ‘2’ 上花三角标记
w 白色 ‘3’ 左花三角标记
#000000 RGB颜色 ‘4’ 右花三角标记
‘0.8’ 灰度值字符串 ‘s’ 实心方形标记
‘_’ 实线 ‘p’ 实心五角标记
‘_ _’ 破折线 ‘*’ 星型标记
‘_.’ 点画线 ‘h’ 竖六边形标记
‘:’ 虚线 ‘H’ 横六边形标记
‘’ ‘’ 无线条 ‘+’ 十字标记
‘.’ 点标记 ‘x’ x标记
‘,’ 像素标记 ‘D’ 菱形标记
‘o’ 是实心圈标记 ‘d’ 瘦菱形标记
‘v’ 倒三角标记 ‘!’ 垂直线标记

效果图:
在这里插入图片描述

4.k近邻

K-NN算法可以说是最简单的机器学习算法,构建模型只需要保存训练集就行。
想要对新数据做出预测,算法会在训练集中找到最近的数据点,也就是”最近邻“。

4.1 k近邻分类

这种分类方法应用在forge数据集上。

  • 单一最近邻模型对forge数据集的预测结果

运行代码如下:

import mglearn
import matplotlib.pyplot as plt
mglearn.plots.plot_knn_classification(n_neighbors=1)
plt.show()

效果图:

在这里插入图片描述
这里我们新加了3个五角星数据点,对于每个数据点,我们标记了训练集中与他最近的点。单一最近邻的预测算法就是那个点的标签。

  • 3近邻模型对forge数据集的预测结果

运行代码如下:

import mglearn
import matplotlib.pyplot as plt
mglearn.plots.plot_knn_classification(n_neighbors=3)
plt.show()

效果图:
在这里插入图片描述
我们将3个近邻中占多数的类别作为预测结果。

下面让我们看一下用scikit-learn来应用k近邻算法,运行代码如下:

import mglearn
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
X,y=mglearn.datasets.make_forge()#加载数据
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)#分离数据
clf = KNeighborsClassifier(n_neighbors=3)#设置近邻数
clf.fit(X_train,y_train)#构建模型
print("Test set accuracy : {:.2f}".format(clf.score(X_test,y_test)))#评估模型

输出:

Test set accuracy : 0.86

4.2 分析k近邻分类(KNeighborsClassifier)

怎么分析呢,就是在xy平面上画出所有可能的测试点的预测结果,然后根据平面中的每一个点的所属类别对平面进行着色。这样可以查看决策边界,即算法对类别0和类别1的分界线。
运行代码如下:

import mglearn
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
#参数1和3分别代表子图的行数和列数,1行3个15x7大小的子图
fig,axes=plt.subplots(1,3,figsize=(10,3))#函数返回一个figure图像和子图ax的array列表。
#加载数据
X,y=mglearn.datasets.make_forge()
for n_neighbors,ax in zip([1,3,9],axes):
    clf=KNeighborsClassifier(n_neighbors=n_neighbors).fit(X,y)#构建模型
    #第一个参数为模型,第二个参数X为训练数据,fill参数设置为填充可见,eps参数决定图像的填充度,
    #初始值为X的标准差/2,这里我们经过实验设置为0.4,ax参数为选择哪一个子图,
    #alpha参数决定透明度,初始值为1
    mglearn.plots.plot_2d_separator(clf,X,fill=True,eps=0.5,ax=ax,alpha=0.4)
    mglearn.discrete_scatter(X[:,0],X[:,1],y,ax=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)#设置第一张子图的图例位置
plt.show()

效果图:
在这里插入图片描述
从图中我们可以看出,邻居的个数越多,决策边界越平滑。也就是说,更少的邻居对应更高的模型复杂度,更多的邻居对应更少的模型复杂度。

下面我们来研究一下模型复杂度与模型的泛化能力之间的关系。
我们在现实中的乳腺癌数据集上进行研究。
运行代码如下:

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
cancer=load_breast_cancer()
#传入参数stratify作用为以分层方式分割数据,保持测试集与整个数据集里cancer.target的数据分类比例一致,
#默认值为None,例如:cancer.target分两类:0和1,其中0有400个,1有600个,即数据分类的比例为4:6。
#则训练集和测试集中的数据分类比例将与cancer.target一致,也是4:6,
#结果就是在训练集中有300个0和450个1;测试集中有100个0和150个1
X_train,X_test,y_train,y_test=train_test_split(
    cancer.data,cancer.target,stratify=cancer.target,random_state=0)#分离数据
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="trianing accuracy")
plt.plot(neighbors_settings,test_accuracy,'--',label="test accuracy")
plt.xlabel("n_neighbors")
plt.ylabel("Accuracy")
plt.legend()
plt.show()

效果图:
在这里插入图片描述

图像的x轴为邻居个数,y轴为精度。从图中可以发现,最佳性能在7到8的某处,邻居个数大约为7;最差性能约为88%的精度,这个结果也可以接受。

4.3 k近邻回归

k近邻算法还可以用于回归,这种回归算法应用在wave数据集上。

  • 单一近邻回归对wave数据集的预测结果

运行代码如下:

import mglearn
import matplotlib.pyplot as plt
mglearn.plots.plot_knn_regression(n_neighbors=1)
plt.show()

效果图:在这里插入图片描述

同样,也可以用多个近邻进行回归,预测结果为这些邻居的平均值。

  • 3个近邻回归对wave数据集的预测结果

运行代码如下:

import mglearn
import matplotlib.pyplot as plt
mglearn.plots.plot_knn_regression(n_neighbors=3)
plt.show()

效果图:
在这里插入图片描述

下面让我们看一下用于回归的k近邻算法在scikit-learn中的实现,运行代码如下:

import mglearn
from sklearn.neighbors import KNeighborsRegressor
from sklearn.model_selection import train_test_split
X,y=mglearn.datasets.make_wave(n_samples=40)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
reg=KNeighborsRegressor(n_neighbors=3)
reg.fit(X_train,y_train)
print("Test seet R^2: {:.2f}".format(reg.score(X_test,y_test)))

输出:

Test seet R^2: 0.83

对于回归问题,score方法返回的是R²分数,也叫决定系数,是回归模型预测的优度度量,位于0和1之间。R²等于0对应完美预测,R²等于0对应常数模型。

4.4 分析k近邻回归(KNeighborsRegressor)

对于我们的一位数据集,可以查看所有特征取值对应的预测结果。为了方便绘图,我们创建一个有许多点组成的测试数据集。运行代码如下:

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsRegressor
import matplotlib.pyplot as plt
import numpy as np
import mglearn
#读取数据
X,y=mglearn.datasets.make_wave(n_samples=40)
#分离数据
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
#创建图形
fig,axes=plt.subplots(1,3,figsize=(15,4))
#创建1000个数据点,在-3和3之间均匀分布
#构造等差数列 开始值,结束值,共几个数字,包含终止值,可以通过endpoint=False设置不包含终止值
#reshape(-1,1)将生成的等差数列列表转化为任意行一列的二维数组
#例如:line=np.arange(1,10).reshape((3,3)) 将1到9的列表,转化为3行3列的二维数组
line =np.linspace(-3,3,1000).reshape(-1,1)
for n_neighbors,ax in zip([1,3,9],axes):
    reg = KNeighborsRegressor(n_neighbors=n_neighbors)
    reg.fit(X_train,y_train)
    #以line为x轴,以line预测的结果为y轴
    ax.plot(line,reg.predict(line))
    #参数c作用是改变标记颜色,为0.0~1.0,转化为RGB形式,为非必要传入参数,可不写
    ax.plot(X_train,y_train,'^',c=mglearn.cm2(0),markersize=8)
    ax.plot(X_test,y_test,'v',c=mglearn.cm2(1),markersize=8)
    ax.set_title("{} neighbor(s)\n train score:{:.2f} test score: {:.2f}".format(
    	n_neighbors,reg.score(X_train,y_train),reg.score(X_test,y_test)))
    ax.set_xlabel("Feature")
    ax.set_ylabel("Target")

axes[0].legend(["Model predictions","Training data/target","Test data/target"],loc="best")

效果图:
在这里插入图片描述
从图中可以看出,若是仅考虑一个邻居,则训练集中的每个点都对预测结果有显著影响,预测结果的图像经过所有数据点。这就导致了预测结果非常的不稳定。但是若考虑更多的邻居之后,预测结果变得更加平滑,但是对训练数据的拟合不是很好。

  • k-NN的优点:模型容易理解,构建模型速度快
  • k-NN的缺点:预测速度慢,不能处理具有许多特征的数据集

到这里k–NN算法就学完了。

  • 完整代码都在文章里面全部可以运行
  • 有不懂得地方和问题请留言
  • 大家可以收藏一下以后学习可能用得到

猜你喜欢

转载自blog.csdn.net/zhu_rui/article/details/105913257
今日推荐