当前位置:首页 > 工具 > 正文内容

基于 KNN 算法的 MNIST 手写数字分类实战

访客 工具 2026年8月27日 1

本文将演示如何利用 NumPy 实现一个基础的 K-近邻 (KNN) 分类器,并应用于经典的 MNIST 手写数字数据集。通过从零构建算法,我们可以深入理解该分类原理的工作机制,特别是在图像识别场景下的应用。

1. 环境准备与依赖库

首先,我们需要引入科学计算库 NumPy 用于矩阵运算,以及 Matplotlib 用于数据可视化。为了方便获取数据集,这里使用 TensorFlow 的 Keras 接口。

import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist

# 设置绘图后端
%matplotlib inline

2. 数据集加载与可视化

加载 MNIST 数据集,并将其分为训练集和测试集。原始图像是 28x28 的灰度图,为了简化计算,我们将图像扁平化为 784 维的向量,并进行归一化处理以提升计算稳定性。

# 加载数据
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 数据预处理:扁平化与归一化
x_train = train_images.reshape(train_images.shape[0], -1).astype('float32') / 255.0
y_train = train_labels
x_test = test_images.reshape(test_images.shape[0], -1).astype('float32') / 255.0
y_test = test_labels

print(f"训练集特征维度: {x_train.shape}")
print(f"测试集特征维度: {x_test.shape}")

下面随机选取几张训练集图像进行可视化展示,确认数据加载正确。

plt.figure(figsize=(10, 2))
for index in range(6):
    plt.subplot(1, 6, index + 1)
    plt.imshow(x_train[index].reshape(28, 28), cmap='gray')
    plt.axis('off')
plt.show()

3. KNN 分类器核心实现

我们将定义一个 SimpleKNN 类。该算法的核心逻辑是计算测试样本与训练集中所有样本的欧氏距离,选取距离最近的 K 个样本,根据这 K 个样本的标签进行投票,得票最多的类别即为预测结果。

为了提升代码可读性,我们将距离计算和投票逻辑拆分为独立的方法。

class SimpleKNN:
    def __init__(self, n_neighbors=5):
        self.n_neighbors = n_neighbors

    def fit(self, X, y):
        """
        存储训练数据,KNN 是惰性学习,训练阶段仅需保存样本
        """
        self.X_train = X
        self.y_train = y

    def _predict_single(self, x):
        """
        对单个样本进行预测
        """
        # 1. 计算欧氏距离
        distances = np.linalg.norm(self.X_train - x, axis=1)
        
        # 2. 获取距离最近的 K 个样本的索引
        k_indices = np.argsort(distances)[:self.n_neighbors]
        
        # 3. 获取对应的标签
        k_nearest_labels = [self.y_train[i] for i in k_indices]
        
        # 4. 统计出现次数最多的标签
        from collections import Counter
        most_common = Counter(k_nearest_labels).most_common(1)
        return most_common[0][0]

    def predict(self, X):
        """
        批量预测
        """
        predictions = [self._predict_single(x) for x in X]
        return np.array(predictions)

    def score(self, X, y):
        """
        计算模型在给定数据上的准确率
        """
        y_pred = self.predict(X)
        accuracy = np.sum(y_pred == y) / len(y)
        return accuracy

4. 模型训练与评估

由于 KNN 在预测时需要计算所有样本的距离,计算复杂度较高。为了演示效果,我们对测试集进行采样(例如选取前 1000 个样本)进行评估,设置 K 值为 10。

# 初始化模型,设置 K=10
knn_clf = SimpleKNN(n_neighbors=10)

# 使用训练数据进行拟合
knn_clf.fit(x_train, y_train)

# 选取部分测试数据进行预测(为了节省时间)
sample_size = 1000
x_test_sample = x_test[:sample_size]
y_test_sample = y_test[:sample_size]

# 计算准确率
acc = knn_clf.score(x_test_sample, y_test_sample)
print(f"模型在测试样本上的准确率: {acc:.4f}")

运行上述代码后,模型通常会输出接近 0.96 左右的准确率。这证明了在没有任何参数优化的情况下,KNN 算法本身在手写数字识别任务中依然具有相当的竞争力。

相关文章

Trojan服务器搭建与配置

一、整体架构(先对齐认知)Clash Meta (PC / iOS / Android)        ↓ TLS   Trojan Server (443)        ↓     InternetTrojan 的核心是: TLS + HTTPS 流量伪装 看起来像正常网站 非常适合...

Tailscale 的详细用法

Tailscale 是一种基于 WireGuard 协议 的 零配置 VPN(虚拟私有网络)服务,让设备之间能够 安全、加密地直接连接,就像它们在同一个本地网络一样。它的核心特点是 简单、安全、跨平台。Tailscale 非常适合 没有公网 IP、两台电脑不在同一局域网 的场景。 简单来说,Tailscale 是什么?Tailscale 是一款让你的各种设备(电脑、服务器、手机...

Clash Tun 模式 导致 爱快(iKuai SD-Wan)内网域名无法访问

一、Clash  DNS 配置dns:  enable: true  listen: 0.0.0.0:53  ipv6: true  enhanced-mode: redir-host  nameserver:    - 223.5.5.5    - 223.6.6.6iKuai 内网域名 ...

深入解析Node.js运行环境与异步I/O架构

深入解析Node.js运行环境与异步I/O架构

核心定义与价值Node.js本质上是一个JavaScript运行环境,而非编程语言或应用框架。它赋予了JavaScript脱离浏览器在服务端、命令行工具及网络应用中执行的能力。其核心意义在于:用单一语言打通前后端开发壁垒。基于事件驱动与非阻塞I/O的架构特性,Node.js在处理API网关、实时通信及微服务等I/O密集型场景时表现卓越,已成为现代后端工程的主流选择。浏览器沙箱限制1995年Java...

ADO.NET SQL参数化查询的最佳实践

在 ADO.NET 中执行 SQL 查询时,参数化查询是一种关键的安全措施和性能优化手段。它通过将 SQL 命令和用户提供的数据分开处理,有效防止了 SQL 注入攻击,并有助于数据库缓存执行计划。下面总结了几种常用的参数化查询方式。 1. 使用 SqlParameter 对象(推荐) 这是最推荐的参数化查询方式。通过显式创建 SqlParameter 对象,您可以精确控制参数的类...

基于ELK的日志集中化分析系统搭建

构建统一日志管理平台的必要性 在分布式架构中,各服务节点独立运行,日志分散存储于不同主机。传统通过命令行工具如grep、awk逐个检索日志的方式,在数据量庞大时效率极低,难以实现快速定位问题。为提升运维效率,需建立集中式日志处理体系,具备日志采集、传输、存储、分析与告警能力。 ELK技术栈核心组件解析 Elasticsearch:分布式搜索引擎,支持全文检索、实时数据分析和高可用集群部署,...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。