繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

【机器学习】k近邻分类与回归实战

作者/外汇老法师 2019-05-10 07:00 0 来源: FX168财经网人物频道

在这一节中,可以了解到K近邻算法,并应用于分类与回归的例子。

k近邻又称作k-NN算法,是最简单的机器学习算法。非常的适合小白入门了解机器学习原理。k-NN会保存训练的数据,在面对新的数据时,算法会在训练数据集中找到最近的数据点,这也就是为什么被叫作“最近邻”的原因。

本节的数据将基于上一章节的数据,如有疑问,请查看上一章节。

备注:mgleran中的数据是用来展示的,不与机器学习的sklern模块相重叠。

*mgleran请使用pip install mglearn命令。

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

k近邻分类

k-NN 算法最简单的版本是只考虑一个最近邻,即被预测的新的数据点离训练的数据集中的哪个点最近,它将被归类为哪个类别。

在mglearn的forge中,内置了此种情况,如下图为单一最近邻模型对forge数据集的预测结果,五角星为被预测的数据点,根据其离得最近的训练数据集,通过设置参数n_nei*ors=1来设定“最近邻”的个数。

mglearn.plots.plot_knn_classification(n_nei*ors=1)

从上图我们就能明白,新数据离得谁最近,他就会被归类为哪一类。

左上角的五角星其实应该属于三角星一类,为了提高准确率,这里可以提高“最近邻”个数,即n_nei*ors值。再来看一下当n_nei*ors=3时的情况:

mglearn.plots.plot_knn_classification(n_nei*ors=3)

当提高“最近邻”的个数后,可以看到,对于新数据的预测更准确了,左上角的五角星近相近的是一个圆和两个三角星,因此它被归类于三角一类。

下面来看看如何通过 scikit-learn 来应用 k 近邻算法。

# 导入 train_test_splitfrom sklearn.model_selection import train_test_split# 导入二分类数据集X, y = mglearn.datasets.make_forge()# 将数据打乱,并分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

上面的代码提供了数据集,接下来,需要实例化k-NN对象。

# 导入k-NN模型from sklearn.nei*ors import KNei*orsClassifier# 将k-NN模型实例为对象,并指定最近邻个数clf = KNei*orsClassifier(n_nei*ors=3)

现在,我们就有了最近邻算法模型实例化的对象了,该对象的引用被保存到了变量clf中。

接下来,我们使用该对象对训练集数据进行训练,以得出一个模型结果。

clf.fit(X_train, y_train)
KNei*orsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_nei*ors=3, p=2,
           weights='uniform')

对于训练集训练的结果,会被保存在k-NN对象中,所以,该对象会对新数据在此基础上进行预测。

接下来,对测试集进行预测,并查看预测结果。

# 预测测试集数据clf.predict(X_test)
array([1, 0, 1, 0, 1, 0, 0])
# 评估模型的泛化能力clf.score(X_test, y_test)
0.8571428571428571

可以看到,模型的精度为86%,也就是说,该模型对于测试数据的预测,有86%的结果是正确的。

接下来要做的,是在多张图表中展示不同“最近邻”参数下,模型对于数据的分类能力的体现。而这种分类,采用决策边界来展示。

接下来将分析“最近邻”分另为1、3、9的情况。

# 通过subplots创建一个幕布,在幕布上创建三个绘图区,幕布大小为10*3fig, axes = plt.subplots(1, 3, figsize=(10,3))# 通过zip函数,将两个集体打包并成对的返回for n_nei*ors, ax in zip([1, 3, 9], axes):# fit方法返回对象本身,所以我们可以将实例化和拟合放在一行代码中clf = KNei*orsClassifier(n_nei*ors=n_nei*ors).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('n_nei*ors{}'.format(n_nei*ors))# 设置横坐标标签ax.set_xlabel('feature 0')# 设置纵坐标标签ax.set_ylabel('feature 1')# 在第一张图上显示图例axes[0].legend(loc=3)
plt.show()

从上图可以发现,“最近邻”的个数变大后,决策边界将变得更加的平缓,曲线也变得更加的简单。这种更简单的情形,比较适合于大多数的数据。

这种结论也能说明,更简单的模型,泛化能力更好。

接下来认证一下模型复杂度与泛化能力之间的关系

这次将使用乳腺癌数据集,对该数据用不同的“最邻近”个数进行训练与测试,然后对于评估结果展示一个线性的结果。

# 导入乳腺癌数据集模块from sklearn.datasets import load_breast_cancer# 加载数据cancer = load_breast_cancer()# 将数据分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=66)# 创建两个列表,分别用来记录不同“最近邻”参数下模型的训练集精度和测试集精度training_accuracy = []
test_accuracy = []# n_nei*ors 取值从1到10nei*ors_settings = range(1, 11)# 循环测试不同“最近邻”参数for n_nei*ors in nei*ors_settings:# 构建模型 clf = KNei*orsClassifier(n_nei*ors=n_nei*ors)# 训练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(nei*ors_settings, training_accuracy, label="training accuracy")# 画出测试集的曲线图plt.plot(nei*ors_settings, test_accuracy, label="test accuracy")# 设置x与y轴标签plt.xlabel('n_nei*ors')
plt.ylabel('Accuracy')# 展示图例plt.legend()
plt.show()

能过上图的展示发现,训练集的泛化精度随着“最近邻”个数的增加,精度越来越低。而测试集的泛化精度随着“最近邻”个数的增加,先上长后下降。两者的最佳取值大概在n_nei*ors=6这个位置。

也就是说,当“最近邻”个数过小的时候,模型过于复杂,不适用于新数据。而“最近邻”个数过大,则模型会变得过于简单,性能也会变差。

k近邻回归

k近邻算法还适用于回归。在mglearn的w*e中内置了一个回归数据集。现在,在该数据集上再添加三个测试点,利用单一“最近邻”参数来预测目标的结果值。如下:

mglearn.plots.plot_knn_regression(n_nei*ors=1)

再来看下“最近邻”个数为3时的预测值。

mglearn.plots.plot_knn_regression(n_nei*ors=3)

上面两个图例是现成的模型,在 scikit-learn 中的 KNei*orsRegressor 类用于回归算法的实现,它的用法与 KNei*orsClassifier 的用法相似。

# 导入 KNei*orsRegressor 模块from sklearn.nei*ors import KNei*orsRegressor# 加载40个回归数据集X, y = mglearn.datasets.make_w*e(n_samples=40)# 将w*e数据集分为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)# 模型实例化,并将邻居个数设置为3reg = KNei*orsRegressor(n_nei*ors=3)# 利用训练数据和训练目标值为拟合模型reg.fit(X_train, y_train)
KNei*orsRegressor(algorithm='auto', leaf_size=30, metric='minkowski',
          metric_params=None, n_jobs=1, n_nei*ors=3, p=2,
          weights='uniform')

然后对测试集进行预测:

reg.predict(X_test)
array([-0.05396539,  0.35686046,  1.13671923, -1.89415682, -1.13881398,       -1.63113382,  0.35686046,  0.91241374, -0.44680446, -1.13881398])

评估一下模型的泛化精度:

reg.score(X_test, y_test)
0.8344172446249604

对于回归模型,scroe方法返回的是R的平方数,也叫做决定系统,是回归模型预测的优度度量,位于0到1之间。R的平方等于1对应完美预测,R的平方等于0对应常数模型,即总是预测训练集响应(y_train)的平均值。

分析 KNei*orsRegressor

同样,这里来展示“最近邻”个数分别为1、3、9下的泛化能力。

fig, axes = plt.subplots(1, 3, figsize=(15, 4))# 创建1000个数据点,在-3和3之间均匀分布line = np.linspace(-3, 3, 1000).reshape(-1, 1)for n_nei*ors, ax in zip([1, 3, 9], axes):# 利用1、3、9个邻居分别进行预测reg = KNei*orsRegressor(n_nei*ors=n_nei*ors)
    reg.fit(X_train, y_train)# 展示预测曲线与训练集和测试集的关系ax.plot(line, reg.predict(line))
    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('{} nei*or(s)\n train score: {:.2f} test score: {:.2f}'.format(n_nei*ors, 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')
plt.show()

从图中可以看出,仅使用单一“最近邻”参数,训练集中的第个点都对预测结果有显著影响,非常不稳定。

而更大的“最近邻”个数所对应的预测结果也更平滑,但对训练数据的拟合不好。

总结:

一般来说,KNei*ors分类器有2个重要参数:邻居的个数与数据点之间距离的度量方法,在实践中,使用较小的邻居个数(比如3或5)往往可以得到比较好的结果。

k-NN的优点之一是比较容易理解,比较适合机器学习小白入门,但如果数据量特别大,该模型的表现就会很差。

在这一节中,可以了解到K近邻算法,并应用于分类与回归的例子。

k近邻又称作k-NN算法,是最简单的机器学习算法。非常的适合小白入门了解机器学习原理。k-NN会保存训练的数据,在面对新的数据时,算法会在训练数据集中找到最近的数据点,这也就是为什么被叫作“最近邻”的原因。

本节的数据将基于上一章节的数据,如有疑问,请查看上一章节。

备注:mgleran中的数据是用来展示的,不与机器学习的sklern模块相重叠。

*mgleran请使用pip install mglearn命令。

# 在学习之前,先导入这些常用的模块import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport mglearn

k近邻分类¶

k-NN 算法最简单的版本是只考虑一个最近邻,即被预测的新的数据点离训练的数据集中的哪个点最近,它将被归类为哪个类别。

在mglearn的forge中,内置了此种情况,如下图为单一最近邻模型对forge数据集的预测结果,五角星为被预测的数据点,根据其离得最近的训练数据集,通过设置参数n_nei*ors=1来设定“最近邻”的个数。

mglearn.plots.plot_knn_classification(n_nei*ors=1)
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:77: DeprecationWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
  warnings.warn(msg, category=DeprecationWarning)

从上图我们就能明白,新数据离得谁最近,他就会被归类为哪一类。

左上角的五角星其实应该属于三角星一类,为了提高准确率,这里可以提高“最近邻”个数,即n_nei*ors值。再来看一下当n_nei*ors=3时的情况:

mglearn.plots.plot_knn_classification(n_nei*ors=3)
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:77: DeprecationWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
  warnings.warn(msg, category=DeprecationWarning)

当提高“最近邻”的个数后,可以看到,对于新数据的预测更准确了,左上角的五角星近相近的是一个圆和两个三角星,因此它被归类于三角一类。

下面来看看如何通过 scikit-learn 来应用 k 近邻算法。

# 导入 train_test_splitfrom sklearn.model_selection import train_test_split# 导入二分类数据集X, y = mglearn.datasets.make_forge()# 将数据打乱,并分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
C:\Users\Administrator\Anaconda3\lib\site-packages\sklearn\utils\deprecation.py:77: DeprecationWarning: Function make_blobs is deprecated; Please import make_blobs directly from scikit-learn
  warnings.warn(msg, category=DeprecationWarning)

上面的代码提供了数据集,接下来,需要实例化k-NN对象。

# 导入k-NN模型from sklearn.nei*ors import KNei*orsClassifier# 将k-NN模型实例为对象,并指定最近邻个数clf = KNei*orsClassifier(n_nei*ors=3)

现在,我们就有了最近邻算法模型实例化的对象了,该对象的引用被保存到了变量clf中。

接下来,我们使用该对象对训练集数据进行训练,以得出一个模型结果。

clf.fit(X_train, y_train)
KNei*orsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_nei*ors=3, p=2,
           weights='uniform')

对于训练集训练的结果,会被保存在k-NN对象中,所以,该对象会对新数据在此基础上进行预测。

接下来,对测试集进行预测,并查看预测结果。

# 预测测试集数据clf.predict(X_test)
array([1, 0, 1, 0, 1, 0, 0])
# 评估模型的泛化能力clf.score(X_test, y_test)
0.8571428571428571

可以看到,模型的精度为86%,也就是说,该模型对于测试数据的预测,有86%的结果是正确的。

接下来要做的,是在多张图表中展示不同“最近邻”参数下,模型对于数据的分类能力的体现。而这种分类,采用决策边界来展示。

接下来将分析“最近邻”分另为1、3、9的情况。

# 通过subplots创建一个幕布,在幕布上创建三个绘图区,幕布大小为10*3fig, axes = plt.subplots(1, 3, figsize=(10,3))# 通过zip函数,将两个集体打包并成对的返回for n_nei*ors, ax in zip([1, 3, 9], axes):# fit方法返回对象本身,所以我们可以将实例化和拟合放在一行代码中clf = KNei*orsClassifier(n_nei*ors=n_nei*ors).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('n_nei*ors{}'.format(n_nei*ors))# 设置横坐标标签ax.set_xlabel('feature 0')# 设置纵坐标标签ax.set_ylabel('feature 1')# 在第一张图上显示图例axes[0].legend(loc=3)plt.show()

从上图可以发现,“最近邻”的个数变大后,决策边界将变得更加的平缓,曲线也变得更加的简单。这种更简单的情形,比较适合于大多数的数据。

这种结论也能说明,更简单的模型,泛化能力更好。

接下来认证一下模型复杂度与泛化能力之间的关系¶

这次将使用乳腺癌数据集,对该数据用不同的“最邻近”个数进行训练与测试,然后对于评估结果展示一个线性的结果。

# 导入乳腺癌数据集模块from sklearn.datasets import load_breast_cancer# 加载数据cancer = load_breast_cancer()# 将数据分为训练集与测试集X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=66)# 创建两个列表,分别用来记录不同“最近邻”参数下模型的训练集精度和测试集精度training_accuracy = []test_accuracy = []# n_nei*ors 取值从1到10nei*ors_settings = range(1, 11)# 循环测试不同“最近邻”参数for n_nei*ors in nei*ors_settings:# 构建模型 clf = KNei*orsClassifier(n_nei*ors=n_nei*ors)# 训练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(nei*ors_settings, training_accuracy, label="training accuracy")# 画出测试集的曲线图plt.plot(nei*ors_settings, test_accuracy, label="test accuracy")# 设置x与y轴标签plt.xlabel('n_nei*ors')plt.ylabel('Accuracy')# 展示图例plt.legend()plt.show()

能过上图的展示发现,训练集的泛化精度随着“最近邻”个数的增加,精度越来越低。而测试集的泛化精度随着“最近邻”个数的增加,先上长后下降。两者的最佳取值大概在n_nei*ors=6这个位置。

也就是说,当“最近邻”个数过小的时候,模型过于复杂,不适用于新数据。而“最近邻”个数过大,则模型会变得过于简单,性能也会变差。

k近邻回归¶

k近邻算法还适用于回归。在mglearn的w*e中内置了一个回归数据集。现在,在该数据集上再添加三个测试点,利用单一“最近邻”参数来预测目标的结果值。如下:

mglearn.plots.plot_knn_regression(n_nei*ors=1)

再来看下“最近邻”个数为3时的预测值。

mglearn.plots.plot_knn_regression(n_nei*ors=3)

上面两个图例是现成的模型,在 scikit-learn 中的 KNei*orsRegressor 类用于回归算法的实现,它的用法与 KNei*orsClassifier 的用法相似。

# 导入 KNei*orsRegressor 模块from sklearn.nei*ors import KNei*orsRegressor# 加载40个回归数据集X, y = mglearn.datasets.make_w*e(n_samples=40)# 将w*e数据集分为训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)# 模型实例化,并将邻居个数设置为3reg = KNei*orsRegressor(n_nei*ors=3)# 利用训练数据和训练目标值为拟合模型reg.fit(X_train, y_train)
KNei*orsRegressor(algorithm='auto', leaf_size=30, metric='minkowski',
          metric_params=None, n_jobs=1, n_nei*ors=3, p=2,
          weights='uniform')

然后对测试集进行预测:

reg.predict(X_test)
array([-0.05396539,  0.35686046,  1.13671923, -1.89415682, -1.13881398,
       -1.63113382,  0.35686046,  0.91241374, -0.44680446, -1.13881398])

评估一下模型的泛化精度:

reg.score(X_test, y_test)
0.8344172446249604

对于回归模型,scroe方法返回的是R的平方数,也叫做决定系统,是回归模型预测的优度度量,位于0到1之间。R的平方等于1对应完美预测,R的平方等于0对应常数模型,即总是预测训练集响应(y_train)的平均值。

分析 KNei*orsRegressor¶

同样,这里来展示“最近邻”个数分别为1、3、9下的泛化能力。

fig, axes = plt.subplots(1, 3, figsize=(15, 4))# 创建1000个数据点,在-3和3之间均匀分布line = np.linspace(-3, 3, 1000).reshape(-1, 1)for n_nei*ors, ax in zip([1, 3, 9], axes):# 利用1、3、9个邻居分别进行预测reg = KNei*orsRegressor(n_nei*ors=n_nei*ors)reg.fit(X_train, y_train)# 展示预测曲线与训练集和测试集的关系ax.plot(line, reg.predict(line))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('{} nei*or(s)\n train score: {:.2f} test score: {:.2f}'.format(n_nei*ors, 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')plt.show()

从图中可以看出,仅使用单一“最近邻”参数,训练集中的第个点都对预测结果有显著影响,非常不稳定。

而更大的“最近邻”个数所对应的预测结果也更平滑,但对训练数据的拟合不好。

总结:¶

一般来说,KNei*ors分类器有2个重要参数:邻居的个数与数据点之间距离的度量方法,在实践中,使用较小的邻居个数(比如3或5)往往可以得到比较好的结果。

k-NN的优点之一是比较容易理解,比较适合机器学习小白入门,但如果数据量特别大,该模型的表现就会很差。

 
分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2184文章4145粉丝45

    暂无个人简介信息

  • 梁孟梵

    人气2176文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 指导老师

    人气1864文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2320文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 刘钥钥1

    人气2024文章3119粉丝34

    专业从事现货黄金、现货白银模似实盘操作分析指导

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2328文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4760文章8329粉丝119

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...

FX168财经

FX168财经学院

FX168财经

FX168北美