机器学习入门:手写数字识别与算法对比

机器学习入门:手写数字识别与算法对比

前言 :在前面的一系列文章中,我们陆续学习了 KNN、逻辑回归、SVM、决策树、随机森林、朴素贝叶斯、AdaBoost、XGBoost 等算法。本篇我们将把这些算法放在同一个任务上------手写数字识别,通过实际运行对比它们的表现。这既是对前面所学算法的回顾总结,也能帮助理解不同算法的适用场景和性能差异。

目录

  • 一、案例背景
  • 二、数据集与预处理
  • 三、模型训练与评估
  • 四、结果分析
  • 五、总结

一、案例背景

手写数字识别是机器学习领域的经典入门问题。给定一张包含手写数字的图片,让计算机自动判断它写的是 0-9 中的哪一个数字。

本案例使用的手写数字图片包含 5000 个样本(每个数字 500 个),其中 2500 个作为训练集,2500 个作为测试集。我们将用 8 种不同的算法分别训练模型,对比它们的识别准确率。

二、数据集与预处理

2.1 数据说明

digits.png 是一张 1000 × 2000 像素的图片,布局如下:

  • 共有 50 行 × 100 列 = 5000 个数字
  • 每个数字是一个 20 × 20 像素的小方块
  • 每个数字出现 500 次
  • 前 50 列作为训练集,后 50 列作为测试集
数据集 样本数 说明
训练集 2500 前 50 列
测试集 2500 后 50 列

2.2 数据预处理

python 复制代码
import numpy as np
import cv2
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from xgboost import XGBClassifier

# 读取图片
img = cv2.imread('digits.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 分割图片:纵向切成50行,横向切成100列
a = np.vsplit(gray, 50)
cells = [np.hsplit(row, 100) for row in a]
x = np.array(cells)

# 划分训练集和测试集
train = x[:, :50]
test = x[:, 50:100]

# 展平为特征向量(每个数字20×20=400维)
train_new = train.reshape(-1, 400).astype(np.float32)
test_new = test.reshape(-1, 400).astype(np.float32)

# 生成标签:每个数字出现250次(50行 × 5列)
k = np.arange(10)
train_labels = np.repeat(k, 250)
test_labels = np.repeat(k, 250)

三、模型训练与评估

3.1 完整代码

python 复制代码
# 算法列表
models = {
    'KNN': KNeighborsClassifier(n_neighbors=9),
    '逻辑回归': LogisticRegression(max_iter=1000),
    'SVM': SVC(kernel='rbf'),
    '随机森林': RandomForestClassifier(n_estimators=50),
    '决策树': DecisionTreeClassifier(max_depth=10),
    '朴素贝叶斯': GaussianNB(),
    'AdaBoost': AdaBoostClassifier(n_estimators=50),
    'XGBoost': XGBClassifier(n_estimators=50, eval_metric='mlogloss')
}

print("=" * 50)
print("手写数字识别各算法准确率对比")
print("=" * 50)

for name, model in models.items():
    model.fit(train_new, train_labels)
    result = model.predict(test_new)
    acc = np.count_nonzero(result == test_labels) * 100.0 / len(test_labels)
    print(f"{name:10} 准确率: {acc:.2f}%")

3.2 运行结果

复制代码
==================================================
手写数字识别各算法准确率对比
==================================================
KNN        准确率: 91.00%
逻辑回归       准确率: 86.20%
SVM        准确率: 94.20%
随机森林       准确率: 92.20%
决策树        准确率: 74.16%
朴素贝叶斯      准确率: 59.28%
AdaBoost   准确率: 63.28%
XGBoost    准确率: 92.64%

四、结果分析

4.1 算法性能排名

排名 算法 准确率 算法类型
1 SVM 94.20% 支持向量机
2 XGBoost 92.64% 集成学习(Boosting)
3 随机森林 92.20% 集成学习(Bagging)
4 KNN 91.00% 基于距离
5 逻辑回归 86.20% 线性模型
6 决策树 74.08% 树模型(单棵)
7 AdaBoost 63.28% 集成学习(Boosting)
8 朴素贝叶斯 59.28% 概率模型

4.2 关键结论

算法类型 表现 原因分析
SVM 最佳 核函数能有效处理手写数字这类高维非线性问题
集成学习 优秀 XGBoost 和随机森林通过组合多棵树,泛化能力强
KNN 良好 简单有效,但计算量大,不适合大规模数据
逻辑回归 一般 线性模型处理非线性问题能力有限
决策树 较差 单棵树容易过拟合,泛化能力弱
朴素贝叶斯 最差 特征独立假设在图像数据中不成立,导致效果差

总结 :在手写数字识别这类图像分类任务中,SVM集成学习算法 (XGBoost、随机森林)表现最为出色,而朴素贝叶斯因特征独立性假设不成立,效果最差。

五、总结

核心知识点速查

知识点 说明
数据预处理 图像分割 → 展平为特征向量 → 生成标签
训练/测试划分 训练集和测试集样本量 1:1(各 2500 个)
八种算法对比 从准确率、算法类型两个维度分析
最佳算法 SVM(94.20%)
最差算法 朴素贝叶斯(59.28%)

注意事项

要点 说明
数据形状 确保 reshape 后维度为 (2500, 400)
标签生成 np.repeat(k, 250) 确保每个数字有 250 个标签
算法参数 不同算法可能需要调参才能达到最佳效果
图像质量 手写数字图片质量影响最终识别率
相关推荐
霸道流氓气质1 小时前
Spring AI 多租户隔离方案
java·人工智能·spring
ACP广源盛139246256731 小时前
M6/M5 Pro Mac mini 端侧 AI 爆发@ACP#YLB3118 存储扩展芯片在本地 AI 服务中的机会与落地场景
大数据·网络·数据库·人工智能·嵌入式硬件·macos
Rain5091 小时前
谁动了我的 URL?——记一次微前端“灵异 Bug“的排查实录
前端·vue.js·人工智能·前端框架·bug·ai编程
外域速览1 小时前
OpenAI Astra 跨过「高危红线」、李飞飞世界模型 Atlas 落地:AI 行业进入「安全与落地」双拐点
人工智能·安全
Mr数据杨1 小时前
莫斯科公寓价格预测实战 从 Kaggle 房价回归到可落地估值流程
人工智能·数据分析·kaggle竞赛
故七月1 小时前
产业观察|从 9 月行业数据看西南市场 GEO 落地现状与发展路径
大数据·人工智能
丶浅行DE时光1 小时前
管道式电磁流量计选型指南 介质腐蚀与工况适配方案推荐
大数据·网络·人工智能·科技·推荐算法
电子科技圈1 小时前
芯科科技在IOTE 2026上以全栈无线连接与边缘AI展现其在智能网联领域的卓越领导力
人工智能·科技
张欣-男1 小时前
3分钟理解线性代数
线性代数·算法