04-KNN案例:手写数字识别
1. 需求分析从数万个手写图像的数据集中正确识别数字。2. 数据集说明MNISTModified National Institute of Standards and Technology是手写数字识别标准数据集由美国国家标准与技术研究院改造而来是深度学习入门最经典的图像分类数据集。任务目标灰度手写数字 0~9 十分类图像规格单通道灰度图尺寸28×28 像素像素取值0纯黑~255纯白代表笔画灰度2.1 数据来源2.1.1 TensorFlow/Kerasfrom tensorflow.keras.datasets import mnist (x_train, y_train), (x_test, y_test) mnist.load_data()2.1.2 PyTorchfrom torchvision import datasets train_set datasets.MNIST(root./data, trainTrue, downloadTrue) test_set datasets.MNIST(root./data, trainFalse, downloadTrue)2.1.3 sklearn 内置小 MNIST 简介规模仅 1797 张8×8 灰度手写数字不是原版 28×28结构特征 64 维标签 0-9用途传统机器学习SVM、逻辑回归、KNN快速测试不适合深度学习from sklearn.datasets import load_digits3. 建模这里用sklearn中的小MNIST数据集训练速度快一点原理是一样的。3.1 加载包import joblib import numpy as np from sklearn.datasets import load_digits import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score from PIL import Image3.2 获取数据# 1. 加载数据 digits load_digits() x digits.data # 特征矩阵(1797, 64)1797张图每张8×864像素展平 y digits.target # 标签0-9数字 images digits.images # 原始8×8图像数组 print(x.shape) # (1797, 64) print(images.shape) # (1797, 8, 8) # 2. 可视化1张图片 plt.imshow(images[0], cmapgray) plt.title(f数字{y[0]}) plt.axis(off) plt.show()3.3 数据预处理缺失值、异常值处理这里不用归一化因为知道像素区间范围是[0,255]划分数据集# 归一化 x x / 255 # 划分数据集stratify: 按照y的类别比例进行分割 x_train, x_test, y_train, y_test train_test_split(x, y, test_size0.2, stratifyy, random_state21)3.4 特征工程3.4.1 特征提取这里不用3.4.2 特征预处理消除量纲动作归一化已经前置这里不用做3.5 模型训练网格搜索交叉验证这里用5折交叉验证# 创建模型对象 estimator KNeighborsClassifier() # 网格搜索交叉验证 param_dict {n_neighbors: [1,3,5,7,9]} # 超参数字典, 超参可能出现的值 estimator GridSearchCV(estimator, param_gridparam_dict, cv5) # 创建GridSearchCV模型对象 estimator.fit(x_train, y_train) # 交叉验证前的模型训练 print(f最优评分为{estimator.best_score_}) print(f最优超参组合为{estimator.best_params_}) print(f最优的估计器对象为{estimator.best_estimator_}) print(f具体的交叉验证结果为{estimator.cv_results_})3.6 模型评估# 1获取最优超参的模型对象 estimator estimator.best_estimator_ # 根据需要选择 # 2模型训练 estimator.fit(x_train, y_train) # 3模型预测 y_pre estimator.predict(x_test) # 4模型评估 print(f准确率{accuracy_score(y_test, y_pre)})3.7 模型保存joblib.dump(estimator, model/knn.pkl) # 保存路径可替换3.8 模型预测需要准备1张8*8的图片底色为黑色数字为白色因为数据集过于简单预测结果可能不准这里对28*28做了像素和灰度转换图片已经失真但仍然以下列方式预测原理不变示例图片# 1. 读取图片 img Image.open(image.png) # 展示原始图片 # plt.imshow(img, cmapgray) # plt.axis(off) # 关闭坐标轴 # plt.show() # 2. 像素灰度转换 # 灰度转换 gray_img img.convert(L) # 转为灰度图 L模式单通道灰度 # 像素转换 new_size (8, 8) # 自定义像素大小 resized_gray gray_img.resize(new_size) # 展示像素灰度转换后的图片 # plt.imshow(resized_gray, cmapgray) # plt.axis(off) # 关闭坐标轴 # plt.show() # 3. 数据结构转换 # 灰度图转为数组 img_array np.array(resized_gray) img_model img_array.reshape(1, -1) # 形状从: (8, 8) (1, 64) # 归一化 img_model img_model / 255 # 4. 加载模型 estimator joblib.load(model.pkl) # 5. 预测 y_pre estimator.predict(img_model) print(f该图片的数字是: {y_pre})附件