如何在 sklearn 中使用 KNN
在 Python 的 sklearn 工具包中有 KNN 算法。KNN 既可以做分类器,也可以做回归。如果是做分类,你需要引用:
from sklearn.neighbors import KNeighborsClassifier
如果是做回归,你需要引用:
from sklearn.neighbors import KNeighborsRegressor
如何用 KNN 对手写数字进行识别分类
我们先来规划下整个 KNN 分类的流程:
整个训练过程基本上都会包括三个阶段:
-
数据加载:我们可以直接从 sklearn 中加载自带的手写数字数据集;
-
准备阶段:在这个阶段中,我们需要对数据集有个初步的了解,比如样本的个数、图像长什么样、识别结果是怎样的。你可以通过可视化的方式来查看图像的呈现。通过数据规范化可以让数据都在同一个数量级的维度。另外,因为训练集是图像,每幅图像是个 8*8 的的矩阵,我们不需要对它进行特征选择,将全部的图像数据作为特征值矩阵即可;
-
分类阶段:通过训练可以得到分类器,然后用测试集进行准确率的计算。
首先是加载数据和对数据的探索:
# 加载数据 digits = load_digits() data = digits.data # 数据探索 print(data.shape) # 查看第一幅图像 print(digits.images[0]) # 第一幅图像代表的数字含义 print(digits.target[0]) # 将第一幅图像显示出来 plt.gray() plt.imshow(digits.images[0]) plt.show() # 运行结果: (1797, 64) [[ 0. 0. 5. 13. 9. 1. 0. 0.] [ 0. 0. 13. 15. 10. 15. 5. 0.] [ 0. 3. 15. 2. 0. 11. 8. 0.] [ 0. 4. 12. 0. 0. 8. 8. 0.] [ 0. 5. 8. 0. 0. 9. 8. 0.] [ 0. 4. 11. 0. 1. 12. 7. 0.] [ 0. 2. 14. 5. 10. 12. 0. 0.] [ 0. 0. 6. 13. 10. 0. 0. 0.]] 0
我们对原始数据集中的第一幅进行数据可视化,可以看到图像是个8*8 的像素矩阵,上面这幅图像是一个“0”,从训练集的分类标注中我们也可以看到分类标注为“0”。
sklearn 自带的手写数字数据集一共包括了 1797 个
样本,每幅图像都是 8*8 像素的矩阵。因为并没有专门的测试集,所以我们需要对数据集做划分,划分成训练集和测试集。因为KNN 算法和距离定义相关,我们需要对数据进行规范化处理,采用 Z-Score 规范化,代码如下:
# 分割数据,将 25% 的数据作为测试集,其余作为训练集(你也可以指定其他比例的数据作为训练集) train_x, test_x, train_y, test_y = train_test_split(data, digits.target, test_size=0.25, random_state=33) # 采用 Z-Score 规范化 ss = preprocessing.StandardScaler() train_ss_x = ss.fit_transform(train_x) test_ss_x = ss.transform(test_x)
然后我们构造一个 KNN 分类器 knn,把训练集的数据传入构造好的 knn,并通过测试集进行结果预测,与测试集的结果进行对比,得到 KNN 分类器准确率,代码如下:
# 创建 KNN 分类器 knn = KNeighborsClassifier() knn.fit(train_ss_x, train_y) predict_y = knn.predict(test_ss_x) print("KNN 准确率: %.4lf" % accuracy_score(predict_y, test_y)) # 运行结果: KNN 准确率: 0.9756
这样我们就构造好了一个 KNN 分类器。之前我们还讲过 SVM、朴素贝叶斯和决策树分类。我们用手写数字数据集一起来训练下这些分类器,然后对比下哪个分类器的效果更好。代码如下:
# 创建 SVM 分类器 svm = SVC() svm.fit(train_ss_x, train_y) predict_y=svm.predict(test_ss_x) print('SVM 准确率: %0.4lf' % accuracy_score(predict_y, test_y)) # 采用 Min-Max 规范化 mm = preprocessing.MinMaxScaler() train_mm_x = mm.fit_transform(train_x) test_mm_x = mm.transform(test_x) # 创建 Naive Bayes 分类器 mnb = MultinomialNB() mnb.fit(train_mm_x, train_y) predict_y = mnb.predict(test_mm_x) print(" 多项式朴素贝叶斯准确率: %.4lf" % accuracy_score(predict_y, test_y)) # 创建 CART 决策树分类器 dtc = DecisionTreeClassifier() dtc.fit(train_mm_x, train_y) predict_y = dtc.predict(test_mm_x) print("CART 决策树准确率: %.4lf" % accuracy_score(predict_y, test_y)) # 运行结果: SVM 准确率: 0.9867 多项式朴素贝叶斯准确率: 0.8844 CART 决策树准确率: 0.8556
这里需要注意的是,我们在做多项式朴素贝叶斯分类的时候,传入的数据不能有负数。因为 Z-Score 会将数值规范化为一个标准的正态分布,即均值为 0,方差为 1,数值会包含负数。因此我们需要采用 Min-Max 规范化,将数据规范化到 [0,1] 范围内。
#### 多项式朴素贝叶斯实际上是符合多项式分布,不会存在负数。而高斯朴素贝叶斯呈现的是高斯分布,也就是正态分布,比如均值为0,方差为1的标准正态分布,可以存在负数。
整理下这 4 个分类器的结果:
# 相关的导包 from sklearn.model_selection import train_test_split from sklearn import preprocessing from sklearn.metrics import accuracy_score from sklearn.datasets import load_digits from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC from sklearn.naive_bayes import MultinomialNB from sklearn.tree import DecisionTreeClassifier import matplotlib.pyplot as plt