11月17, 2019

KNN分类算法经典案例——鸢尾花

推荐书籍

title

这是我从大量算法书籍中精心筛选出来的,它

  • 重视算法原理的理解,
  • 用生动的例子替代晦涩的公式证明,
  • 绘图也非常有趣,

​对非专业开发者十分友好​。 我的算法教程,也是以《算法图解》 为蓝本展开​。

获取渠道

除了购买纸质图书外,你还可以从微信读书搜索到,领用无限读书券非常划算。

准备开始

本节我们参考的是《算法图解》第 10 章。 KNN 是机器学习领域的入门算法之一,KNN 就是 K 个最临近(Nearest)邻居(Neighbors),原理非常简单,通过对数据所在空间内统计附近若干元素来解决分类问题。我们的老祖宗也用一句话表述了类似的算法:物以类聚,人以群分。

我们会使用 scikit-learn,你可以使用

pip install scikit-learn 

安装。

鸢[yuān]尾花数据

鸢尾花分类问题,是 KNN 算法的一个非常经典的案例,scikit-learn 库中已经自带了标记好的鸢尾花数据,共 150 条,包含:萼片和花瓣的长、宽。

我们将这些数据打乱以后,按照比例 3:1 分为 2 组,一组作为训练数据,一组作为测试数据。训练数据的作用,是生成 KNN 模型。计算机辛勤的生成模型,总需要对生成的结果进行评估,确定模型的有效性,这时测试数据就派上用场了。将测试数据通过模型计算得到结果,再与这些数据本身的分类进行比较,就可以得到模型的准确率了。

特别需要注意一点,训练数据和测试数据都是打好标记的,也就是这些花的分类是由人类智能分类好的。我记得河南某乡村被称为所谓的 “人工智能村”,应该就是生产这种标记好的数据,并不是真的在搞 “人工智能”。

通过下面的语句,就可以导入 iris 数据集。

from sklearn.datasets import load_iris 
iris_dataset = load_iris()

由于 Iris 数据集是有序数据,如果直接按照 3:1 的比例将这些数据分割为:

  • 训练数据
  • 测试数据

数据的分布都集中在特定的区域,分布不均匀,所以需要将数据打散后再分割,scikit-learn 已经提供了响应的工具:

from sklearn.model_selection import train_test_split 
X_train, X_test, y_train, y_test = train_test_split(
iris_dataset['data'], iris_dataset['target'], random_state=0)

磨刀

数据算是准备差不多了,CNN 要求特征本身可以作为分类的条件,模型才能真正发挥作用,比如橙子和苹果的颜色,就可以作为一个分类的条件,但是二者的价格就不一定了。在实际情况下也需要先观察数据。

import pandas as pd
import mglearn

iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)
# 按y_train着色
grr = pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15, 15), marker='o',
hist_kwds={'bins': 20}, s=60, alpha=.8, cmap=mglearn.cm3)

title

可以很清晰的看到,现有数据基本上可以将 3 种花分类,那我们就可以安心的继续下一步了。

砍柴

我们已经确定现有的数据可以用来产生分类器,下面就该构建一个模型了。感谢 Python 社区,我们无需从头生成一个模型,scikit-learn 已经提供了一些可用的分类器,就包括 KNN 分类器。我们需要做的只有:

  • 初始化分类器参数(其实只有少量参数需要指定,其余参数保持默认即可),
  • 训练模型,
  • 评估、预测。

KNN 算法的 K 是指几个最近邻居,可以是1、2、3 或者更多,这里我们构建一个 K = 3 的模型。并且将训练数据 X_train 和 Y_train 作为参数,构建模型。

from sklearn.neighbors import KNeighborsClassifier 
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)

注意 knn 是个对象,fit 函数实际上修改的是 knn 对象的内部数据。现在 KNN 分类器已经就绪了。

使用 knn.predict 方法可以对数据进行预测,为了评估分类器的准确度,我们可以将预测结果与测试数据对比,计算命中率。

y_pred = knn.predict(X_test)
print("Test set predictions:\n {}".format(y_pred))
print("Test set score: {:.2f}".format(np.mean(y_pred == y_test)))

title

最后可以看到准确率可以达到 97%,还不错。你的结果应该也差不多。

从 KNN 到 机器学习

KNN 算法是一种:

  • 理论非常简单,
  • 训练快速(实际上基本不学习),
  • 准确度较高,

同时:

  • 计算量较大(计算样本与邻近点的距离)。
  • KNN 模型依赖训练数据本身作为参数,内存消耗较大。
  • 样本不平衡的时候,稀有类别预测准确率较低。
  • 可解释性差,很难形成明确的规则。

虽然 KNN 非常简单粗暴,相比时下流行的深度学习还是有很大差别。但是其对数据的处理,学习,预测等过程,虽然简单,也具备了机器学习的基本要素。

代码在这里: https://github.com/JiangChuanGo/examples/blob/master/KNN/Iris.py

本文链接:http://www.thinkinpython.com/post/KNN_classifier.html

-- EOF --