使用Python实现基于KNN算法的手写数字识别
在机器学习领域,手写数字识别是一个经典的入门级任务。它不仅能够帮助我们理解模式识别的基本原理,还能为更复杂的应用提供基础。本文将介绍如何使用Python和Scikit-Learn库来构建一个简单的手写数字识别模型,并通过K近邻(K-Nearest Neighbors, KNN)算法进行训练和预测。
1. 数据集简介
我们将使用MNIST数据集,这是一个非常流行的手写数字图像数据集。该数据集包含70,000张28x28像素的灰度图片,每张图片代表一个0到9之间的数字。这些图片被分为训练集(60,000张)和测试集(10,000张)。每张图片的数据可以展开成一个长度为784的一维向量。
2. 环境搭建
首先需要确保安装了必要的Python包。可以通过pip命令安装:
pip install numpy matplotlib scikit-learn
3. 加载并预处理数据
Scikit-Learn自带了对MNIST数据集的支持,因此可以直接从sklearn.datasets
模块中加载数据。
from sklearn.datasets import fetch_openmlimport numpy as np# 下载MNIST数据集mnist = fetch_openml('mnist_784', version=1)# 获取特征和标签X, y = mnist["data"], mnist["target"]# 将标签转换为整数类型y = y.astype(np.int8)# 查看数据形状print("Features shape:", X.shape)print("Labels shape:", y.shape)
输出:
Features shape: (70000, 784)Labels shape: (70000,)
接下来,为了提高效率,我们可以仅使用一部分数据来进行实验。这里选择前6000个样本作为训练集,另外1000个样本作为验证集。
# 分割训练集和验证集X_train, X_test = X[:6000], X[6000:7000]y_train, y_test = y[:6000], y[6000:7000]# 混洗训练集以保证随机性shuffle_index = np.random.permutation(6000)X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
4. 训练KNN分类器
Scikit-Learn提供了非常方便的接口来创建和训练KNN分类器。只需要几行代码就可以完成整个过程。
from sklearn.neighbors import KNeighborsClassifier# 创建KNN分类器对象knn_clf = KNeighborsClassifier(n_neighbors=3) # 设置邻居数量为3# 开始训练knn_clf.fit(X_train, y_train)# 输出模型参数信息print(knn_clf)
5. 模型评估
训练完成后,我们需要评估模型的表现。最直接的方法是计算准确率,即正确预测的比例。
from sklearn.metrics import accuracy_score# 在验证集上进行预测y_pred = knn_clf.predict(X_test)# 计算准确率acc = accuracy_score(y_test, y_pred)print(f"Accuracy on test set: {acc:.2%}")
如果想要更加深入地了解模型性能,还可以绘制混淆矩阵或生成分类报告。
from sklearn.metrics import confusion_matrix, classification_report# 绘制混淆矩阵cm = confusion_matrix(y_test, y_pred)print("Confusion Matrix:")print(cm)# 打印分类报告report = classification_report(y_test, y_pred)print("\nClassification Report:\n", report)
6. 可视化结果
最后,让我们可视化一些预测的结果,以便直观地看到模型的工作情况。
import matplotlib.pyplot as pltdef plot_digits(instances, images_per_row=10, **options): size = 28 images_per_row = min(len(instances), images_per_row) images = [instance.reshape(size,size) for instance in instances] n_rows = (len(instances) - 1) // images_per_row + 1 row_images = [] n_empty = n_rows * images_per_row - len(instances) images.append(np.zeros((size, size * n_empty))) for row in range(n_rows): rimages = images[row * images_per_row : (row + 1) * images_per_row] row_images.append(np.concatenate(rimages, axis=1)) image = np.concatenate(row_images, axis=0) plt.imshow(image, cmap = mpl.cm.binary, **options) plt.axis("off")# 随机选取几个测试样本some_digit_images = X_test[:12].reshape(-1, 28, 28)some_digit_labels = y_test[:12]plt.figure(figsize=(9, 9))for index, (image, label) in enumerate(zip(some_digit_images, some_digit_labels)): plt.subplot(4, 3, index + 1) plt.imshow(image, cmap=plt.cm.binary, interpolation='nearest') plt.title(f"Predicted: {y_pred[index]}\nTrue: {label}") plt.axis('off')plt.subplots_adjust(wspace=0.5, hspace=0.5)plt.show()
这段代码会展示12个测试样本及其对应的预测值与真实值,帮助我们快速检查模型是否工作正常。
7. 总结
通过上述步骤,我们已经成功地使用Python实现了基于KNN算法的手写数字识别系统。尽管这个例子相对简单,但它涵盖了从数据准备、模型选择、训练到评估的完整流程。对于初学者来说,这是理解机器学习概念的一个很好的起点。当然,在实际应用中,可能还需要考虑更多的因素,如优化超参数、处理不平衡数据等。希望这篇文章能为你打开通往机器学习世界的大门!