龙空技术网

机器学习:K临近分类算法的原理分析

GreatMan 214

前言:

眼前同学们对“分类算法的时间复杂度”大约比较关心,我们都想要学习一些“分类算法的时间复杂度”的相关文章。那么小编同时在网上搜集了一些有关“分类算法的时间复杂度””的相关知识,希望大家能喜欢,各位老铁们快快来了解一下吧!

KNN算法是最简单的机器学习算法。

构建它时只需要利用训练数据集即可。当有新的数据输送到算法中时,KNN算法会在训练集中找到与新数据最近的数据点。

解析

scikit-learn框架里提供了 mglearn这个类,它里面包含了许多函数可以帮助我们很快很方便的给到我们一些原理图,方便我们对机器学习算法进行学习和理解。

import mglearn# plot的目的就是给出原理图,knn classification 的意思是 K临近分类# 参数 n_eighbors 表示KNN算法里的近邻的个数mglearn.plots.plot_knn_classification(n_neighbors=1)

星星表示新的数据,三角形和圆形表示训练集数据,颜色代表这些数据属于不同的类型。显然这个训练集被分类为了 2 类,橙色代表一类,蓝色代表另外一类。

当新的数据进入到KNN算法里面后,算法会依据新数据的特点,在训练集里找到与这个新数据最近接的那一个数据。上图里的连线就是帮助我们理解这个过程和原理的。

还可以画出 4 个近邻的 KNN 算法的例子

mglearn.plots.plot_knn_classification(n_neighbors=4)

把近邻参数修改为 4,就可以更明白KNN算法的原理了。

查看上图的左上方的一个情况:新的数据(星型)进入到算法中后,算法根据这个新数据的值,在坐标系里找到与这个新数据距离最近的 4 个训练集里的数据(3 个三角形 & 1 个圆形)。下一步就开始在找到的这 4 个训练集数据里进行比较,距离最近的 4 个训练集数据里,有 3 个数据属于“橙色三角类”,有 1 个数据属于“蓝色圆形类”,“少数服从多数”,那么这个新数据样本就属于“橙色三角类”。

实例

现在开始用一个数据集开始一次完成的KNN算法的构建。因为这里主要的讨论方向是机器学习的算法,暂时不对数据工程进行讨论,所以直接使用 scikit-learn 提供的实例数据。

# train_test_split 这个函数可以方便的将原始的数据划分为训练集、测试集、训练集标签、测试集标签from sklearn.model_selection import train_test_split# 这里通过调用 make_forge 函数达到scikit-learn提供的实例数据集和标签,X 是所有的数据集,y是对应的标签X, y = mglearn.datasets.make_forge()

# X_train 训练集,X_test 测试集,y_train 训练集标签,y_test 测试集标签# 在使用 train_test_split函数对原始数据进行划分的时候,最好设置 random_state 这个参数。因为这个函数是随机的将原始数据划分为训练集和测试集,如果不设置这个参数,那么当每次重新运行这个函数时,随机划分出的数据就会不一样,这样会影响下面的结果。设置了这个参数后,每次运行这个函数后,划分出的数据都是一样的了。X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)# 这个数据集很小,划分出的训练集和测试集的数据的形状如下# 训练集有 19 个样本, 2 个特征# 测试集有 7 个样本, 2 个特征print(X_train.shape)print(y_train.shape)print(X_test.shape)print(y_test.shape)print()print(X_train)# 标签有 1 和 0 两种print(y_train)

(19, 2)

(19,)

(7, 2)

(7,)

[[ 8.92229526 -0.63993225]

[ 8.7337095 2.49162431]

[ 9.32298256 5.09840649]

[ 7.99815287 4.8525051 ]

[11.0329545 -0.16816717]

[ 9.17748385 5.09283177]

[11.563957 1.3389402 ]

[ 9.15072323 5.49832246]

[ 8.34810316 5.13415623]

[11.93027136 4.64866327]

[ 8.1062269 4.28695977]

[ 8.67494727 4.47573059]

[ 9.67284681 -0.20283165]

[ 9.50169345 1.93824624]

[ 8.69289001 1.54322016]

[ 9.96346605 4.59676542]

[ 9.50048972 -0.26430318]

[ 9.25694192 5.13284858]

[ 8.68937095 1.48709629]]

[0 0 1 1 0 1 0 1 1 1 0 1 0 0 0 1 0 1 0]

# 调用KNN分类对象from sklearn.neighbors import KNeighborsClassifier# 实例化出来一个KNN对象,同时定义这个算法里的近邻为 3clf = KNeighborsClassifier(n_neighbors=3)
# 几乎每一个机器学习类里都有fit这个函数,它的作用就是对训练集进行拟合,学习训练集里的特征。俗话讲就是“用数据训练模型,让算法学到数据里的特点”clf.fit(X_train, y_train)# 当用训练集把模型拟合完成后,可以调用KNN对象的predict 方法对测试集进行预测。得到的结果是这个KNN算法预测出的标签,要么是 0 要么是 1clf.predict(X_test)

array([1, 0, 1, 0, 1, 0, 0])

# 最后还需要评估一下这个模型的泛化能力的好坏,就是调用 KNN 算法对象的 score 方法# 这个函数与上面的predict方法不同了。predict方法因为是在进行预测,所以只需要给它数据样本,然后它会预测出标签。而 score 方法是对算法进行评价,它也就是要拿着真正的标签和预测出的标签进行比较,然后给出一个分值,来评价模型的还坏。print("模型在测试集上的正确率:{:.2f}".format(clf.score(X_test, y_test)))

模型在测试集上的正确率:0.86

得分为 86 分,基本上还能接受。

以上就是一个最简单最基本的机器学习的过程。

分析 KNN 算法的特性

现在用一个二维平面,展现出不同的近邻设置,KNN算法的决策边界的不同

import matplotlib.pyplot as pltfig, axes = plt.subplots(1, 3, figsize=(10, 3))for n_neighbors, ax in zip([1, 3, 9], axes):    #     因为KNN的类里的fit方法会返回KNN的对象本身,所以可以将KNN对象的实例化和拟合的操作都放在一行代码里。    clf = KNeighborsClassifier(n_neighbors=n_neighbors).fit(X, y)    #     用mglearn对象里的 plot_2d_separator 方法,可以方便的画出一幅带有决策边界的图像来。顾名思义 separator就表示分隔,也就是用不同的颜色区域将数据分为两类。    # ax表示当前的画布,alpha表示填充的颜色的不透明度    mglearn.plots.plot_2d_separator(clf, X, fill=True, ax=ax, alpha=0.4)    #     discrete_scatter 表示用散点图的方式把数据点画在画布上    mglearn.discrete_scatter(X[:, 0], X[:, 1], y, ax=ax)    ax.set_title("{} neighbors".format(n_neighbors))    ax.set_xlabel("feature 0")    ax.set_ylabel('feature 1')axes[0].legend(loc=3)

如果只使用单一的邻居(图一),那么决策边界就会紧挨着训练集数据,而且也存在算法的过拟合情况,这也说明当前的这个算法的复杂度过高。那么这个算法模型对新的数据的判断正确率可能会下降。因为算法对训练集数据拟合的非常好,没有一个错误的判断,这就很可能存在过拟合的状况。

后面两个图,逐渐的增加了近邻的个数(从 3 增加到 9),虽然出现了一些分类判断的错误,但是决策点变得更加的平缓,过拟合的情况也有了好转。那么将来这个算法对新的数据进行分类时的正确率也可能会更高,即算法的泛化能力更强。

标签: #分类算法的时间复杂度