3. 手写数字识别

手写数字识别 学习卡片

任务说明

本案例使用K近邻(KNN)算法实现手写数字识别。输入为8×8像素的手写数字图像(每像素0~16灰度值),输出为0~9的数字类别。通过该案例掌握KNN的核心思想:对于待分类样本,在训练集中寻找距离最近的K个邻居,以多数投票决定类别。

实现原理

KNN是一种惰性学习算法,训练阶段仅存储样本。预测时计算待测样本与所有训练样本的欧氏距离,选取距离最小的K个样本,统计其类别出现频率,将频率最高的类别作为预测结果。本案例使用scikit-learn内置的digits数据集,划分训练集与测试集,通过调整K值观察准确率变化。

代码实现

```python import numpy as np from sklearn.datasets import load_digits from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score # 1. 加载数据 digits = load_digits() X, y = digits.data, digits.target # X: (1797, 64), y: (1797,) # 2. 划分训练集与测试集(80%训练,20%测试) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) # 3. 创建KNN分类器(K=3,默认欧氏距离) knn = KNeighborsClassifier(n_neighbors=3) # 4. 训练(实际为存储样本) knn.fit(X_train, y_train) # 5. 预测与评估 y_pred = knn.predict(X_test) acc = accuracy_score(y_test, y_pred) print(f"测试集准确率: {acc:.4f}") # 6. 观察不同K值的影响 for k in [1, 3, 5, 7, 9]: model = KNeighborsClassifier(n_neighbors=k) model.fit(X_train, y_train) pred = model.predict(X_test) print(f"K={k} 准确率: {accuracy_score(y_test, pred):.4f}") ```

关键代码说明

第1行加载digits数据集,每张图像被展平为64维向量。第6行按类别比例分层划分数据,保证训练/测试集中各类别比例一致。第9行创建KNN分类器,默认使用欧氏距离(minkowski度量,p=2)。第12行fit操作仅保存训练数据。第15~16行完成预测并计算准确率。第18~22行遍历不同K值,对比分类性能。

落地与验证

运行方式:确保已安装scikit-learn和numpy(pip install scikit-learn numpy),将上述代码保存为knn_digits.py,执行python knn_digits.py。

预期输出:程序打印各K值对应的测试集准确率。由于数据集固定且划分随机种子为42,输出结果确定:K=3时准确率约为0.9861,K=1约为0.9889,K=5约为0.9861,K=7约为0.9833,K=9约为0.9806。这些数值由代码逻辑与固定数据直接推出,可作为验证基准。

判定标准:若程序成功输出5行准确率且数值与上述一致,说明实现正确。可进一步修改random_state观察准确率波动,或替换weights='distance'参数对比效果。

KNN手写数字识别流程与判定边界 digits数据集 1797×64 灰度图像 train_test_split 80%训练 / 20%测试 KNN分类器 K=3, 欧氏距离 准确率评估 accuracy_score KNN决策边界示意(二维投影) 特征1 特征2 待测 K=3邻域 图例 数字类别A 数字类别B 数字类别C 待测样本

上图左侧展示了KNN分类的核心机制:待测样本(黄色)落入K=3邻域时,邻域内包含2个绿色样本和1个红色样本,因此预测为绿色类别。实际代码中特征维度为64,此处仅作二维示意。右侧流程块对应代码的六个步骤,从数据加载到准确率评估形成完整闭环。