news 2026/8/10 22:20:05

MNIST手写数字分类实战:从数据加载到模型评估的完整流程(附代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MNIST手写数字分类实战:从数据加载到模型评估的完整流程(附代码)

MNIST手写数字分类实战:从数据加载到模型评估的完整流程(附代码)

在机器学习领域,MNIST数据集堪称经典中的经典。这个包含7万张手写数字图片的数据集,已经成为无数数据科学家和机器学习工程师的"入门必修课"。本文将带你从零开始,完整实现一个MNIST手写数字分类项目,涵盖数据探索、模型构建、训练优化和性能评估的全流程。

1. 环境准备与数据加载

首先我们需要搭建Python环境并安装必要的库。推荐使用Anaconda创建虚拟环境:

conda create -n mnist python=3.8 conda activate mnist pip install numpy pandas matplotlib scikit-learn tensorflow

MNIST数据集可以通过多种方式获取。最便捷的方法是直接使用scikit-learn提供的API:

from sklearn.datasets import fetch_openml mnist = fetch_openml('mnist_784', version=1, as_frame=False) X, y = mnist["data"], mnist["target"]

数据加载后,我们可以查看其基本结构:

  • 样本数量:70,000
  • 特征维度:784(28x28像素)
  • 标签范围:0-9

为了更好地理解数据,让我们可视化几个样本:

import matplotlib.pyplot as plt def plot_digit(image_data): image = image_data.reshape(28, 28) plt.imshow(image, cmap="binary") plt.axis("off") plt.figure(figsize=(10,5)) for i in range(10): plt.subplot(2,5,i+1) plot_digit(X[i]) plt.show()

2. 数据预处理与分割

在建模前,我们需要对数据进行适当的预处理:

  1. 类型转换:将标签从字符串转为整数
  2. 归一化:将像素值从0-255缩放到0-1范围
  3. 数据集分割:划分训练集和测试集
import numpy as np from sklearn.model_selection import train_test_split # 类型转换 y = y.astype(np.uint8) # 归一化 X = X / 255.0 # 数据集分割 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

注意:MNIST数据集已经预先进行了随机化处理,前60,000个样本通常作为训练集,后10,000个作为测试集。但为了演示通用流程,我们使用train_test_split进行随机分割。

3. 模型构建与训练

我们将尝试两种不同的分类器:随机梯度下降(SGD)分类器和随机森林分类器。

3.1 SGD分类器

from sklearn.linear_model import SGDClassifier sgd_clf = SGDClassifier(max_iter=1000, tol=1e-3, random_state=42) sgd_clf.fit(X_train, y_train)

3.2 随机森林分类器

from sklearn.ensemble import RandomForestClassifier forest_clf = RandomForestClassifier(n_estimators=100, random_state=42) forest_clf.fit(X_train, y_train)

4. 模型评估与性能分析

评估分类器性能有多种方法,我们将重点介绍几种常用指标。

4.1 准确率评估

最简单的评估指标是准确率:

from sklearn.model_selection import cross_val_score # SGD分类器交叉验证 sgd_scores = cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring="accuracy") print(f"SGD分类器准确率: {sgd_scores.mean():.2f} (±{sgd_scores.std():.2f})") # 随机森林交叉验证 forest_scores = cross_val_score(forest_clf, X_train, y_train, cv=3, scoring="accuracy") print(f"随机森林准确率: {forest_scores.mean():.2f} (±{forest_scores.std():.2f})")

4.2 混淆矩阵分析

混淆矩阵能提供更详细的分类信息:

from sklearn.metrics import confusion_matrix from sklearn.model_selection import cross_val_predict y_train_pred = cross_val_predict(sgd_clf, X_train, y_train, cv=3) conf_mx = confusion_matrix(y_train, y_train_pred) plt.matshow(conf_mx, cmap=plt.cm.gray) plt.show()

4.3 精度与召回率

对于多分类问题,我们可以计算每个类别的精度和召回率:

from sklearn.metrics import precision_score, recall_score precision = precision_score(y_train, y_train_pred, average="macro") recall = recall_score(y_train, y_train_pred, average="macro") print(f"精度: {precision:.2f}, 召回率: {recall:.2f}")

4.4 ROC曲线分析

虽然ROC曲线主要用于二分类问题,但我们可以通过"一对多"策略将其扩展到多分类:

from sklearn.metrics import roc_curve, roc_auc_score from sklearn.preprocessing import label_binarize # 将标签二值化 y_train_bin = label_binarize(y_train, classes=np.arange(10)) # 计算每个类别的ROC曲线 fpr = dict() tpr = dict() roc_auc = dict() for i in range(10): y_score = cross_val_predict(sgd_clf, X_train, y_train_bin[:,i], cv=3, method="decision_function") fpr[i], tpr[i], _ = roc_curve(y_train_bin[:,i], y_score) roc_auc[i] = roc_auc_score(y_train_bin[:,i], y_score) # 绘制ROC曲线 plt.figure(figsize=(10,8)) for i in range(10): plt.plot(fpr[i], tpr[i], label=f'数字{i} (AUC = {roc_auc[i]:.2f})') plt.plot([0, 1], [0, 1], 'k--') plt.xlabel('假正类率') plt.ylabel('真正类率') plt.legend(loc="lower right") plt.show()

5. 模型优化与调参

5.1 特征缩放

SGD分类器对特征缩放敏感,我们可以尝试标准化:

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) sgd_clf.fit(X_train_scaled, y_train) scaled_scores = cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring="accuracy") print(f"标准化后准确率: {scaled_scores.mean():.2f}")

5.2 超参数调优

使用网格搜索优化随机森林参数:

from sklearn.model_selection import GridSearchCV param_grid = [ {'n_estimators': [50, 100, 200], 'max_depth': [None, 10, 20]}, {'bootstrap': [False], 'n_estimators': [50, 100], 'max_depth': [5, 10]} ] forest_clf = RandomForestClassifier(random_state=42) grid_search = GridSearchCV(forest_clf, param_grid, cv=3, scoring='accuracy') grid_search.fit(X_train, y_train) print(f"最佳参数: {grid_search.best_params_}") print(f"最佳准确率: {grid_search.best_score_:.2f}")

6. 最终模型评估

选择表现最好的模型在测试集上进行最终评估:

from sklearn.metrics import classification_report best_model = grid_search.best_estimator_ y_pred = best_model.predict(X_test) print(classification_report(y_test, y_pred))

7. 模型部署与应用

训练好的模型可以保存并用于实际应用:

import joblib # 保存模型 joblib.dump(best_model, 'mnist_classifier.pkl') # 加载模型 loaded_model = joblib.load('mnist_classifier.pkl') # 使用模型预测新数据 sample = X_test[0].reshape(1, -1) prediction = loaded_model.predict(sample) print(f"预测数字: {prediction[0]}")

8. 进阶探索方向

完成基础分类后,可以考虑以下进阶方向:

  1. 卷积神经网络(CNN):使用TensorFlow/Keras构建更强大的图像分类模型
  2. 数据增强:通过旋转、平移等变换增加训练数据多样性
  3. 模型集成:结合多个模型的预测结果提高准确率
  4. 错误分析:深入研究分类错误的样本特征
# CNN示例代码 from tensorflow import keras from tensorflow.keras import layers model = keras.Sequential([ layers.Reshape((28, 28, 1), input_shape=(784,)), layers.Conv2D(32, kernel_size=3, activation='relu'), layers.MaxPooling2D(pool_size=2), layers.Flatten(), layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) model.fit(X_train, y_train, epochs=5, validation_data=(X_test, y_test))

在实际项目中,我发现数据预处理和特征工程往往比模型选择更重要。例如,对MNIST图像进行适当的去噪和增强,可以显著提升模型性能。另外,不同模型在不同数字上的表现差异明显,通过分析混淆矩阵,可以针对性地优化特定数字的分类效果。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 15:36:21

微信PC端登录背后的技术细节:如何安全处理用户授权与数据获取

微信PC端登录背后的安全架构与工程实践 每次扫描二维码完成微信登录时,背后都运行着一套精密的身份验证交响曲。作为日活超10亿的国民级应用,微信的PC端登录流程在便捷性背后隐藏着层层安全设计,从密码学原理到分布式系统协同,每个…

作者头像 李华
网站建设 2026/7/14 15:36:21

JetBrains IDE试用期管理工具:从原理到实践的全方位指南

JetBrains IDE试用期管理工具:从原理到实践的全方位指南 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter 问题引入:开发流程中的隐形中断点 在软件开发过程中,IDE试用期到期提示…

作者头像 李华
网站建设 2026/8/10 22:19:48

RePKG:Wallpaper Engine资源处理的技术革新与未来展望

RePKG:Wallpaper Engine资源处理的技术革新与未来展望 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 一、技术价值:重新定义资源处理的核心突破 1.1 动态格…

作者头像 李华
网站建设 2026/7/14 15:36:20

工业超融合系统:重构制造底层逻辑的数字基座

在制造业加速向智能化、绿色化转型的当下,传统IT架构的“烟囱式”部署已难以支撑复杂多变的生产需求。服务器、存储、网络各自为政,数据孤岛林立,系统扩展成本高昂,运维复杂度居高不下——这些问题不仅拖慢了数字化进程&#xff0…

作者头像 李华
网站建设 2026/7/14 15:36:22

UDOP-large实战指南:5分钟学会英文文档关键信息自动提取

UDOP-large实战指南:5分钟学会英文文档关键信息自动提取 1. 为什么选择UDOP-large处理英文文档? 在信息爆炸的时代,我们每天都要处理大量英文文档——学术论文、商业报告、发票合同等等。传统的手工提取方式不仅效率低下,还容易…

作者头像 李华
网站建设 2026/7/14 15:36:24

Llava-v1.6-7b模型剪枝实战:减小模型体积保持精度

Llava-v1.6-7b模型剪枝实战:减小模型体积保持精度 1. 引言 当你第一次接触多模态大模型时,可能会被它们强大的能力所震撼——既能看懂图片,又能理解文字,还能进行智能对话。但随之而来的就是一个现实问题:这些模型太…

作者头像 李华