手写数字识别项目入门:先读懂 train.csv、test.csv 和标签结构
手写数字识别项目入门:先读懂 train.csv、test.csv 和标签结构
站内搜索
直接问 AI

手写数字识别项目入门:先读懂 train.csv、test.csv 和标签结构

手写数字识别不必从训练模型开始。这个项目把一张 28 × 28 灰度图存成一行 CSV:输入是 784 个像素,输出是数字 0 到 9。读错一个字段、混用两个版本,后面的 loss 和准确率就可能回答错误的问题。本文从站点提供的实际文件出发,检查数据、还原图像,再说明它与 C 程序和浏览器演示的关系。

文件核对日期:2026-09-08。本次执行的是逐行数据检查、文件校验和比较与小型数值测试,没有重新训练模型,也没有获得新的测试集准确率。源码和模型的原始下载文件保持不变。

一、先明确文件与列的含义

train.csv: label,pixel0,pixel1,...,pixel783  共 785 列
test.csv:        pixel0,pixel1,...,pixel783  共 784 列
图像坐标 (r, c) 对应 pixel[28*r + c],r、c 从 0 开始
归一化输入 x[j] = pixel[j] / 255.0

训练集的第 0 列是标签,测试集的第 0 列已经是像素。监督学习的损失需要真实标签;这份无标签测试文件可以用于生成预测,但不能直接计算分类准确率。需要调参时,应从有标签数据中先固定训练/验证划分,记录样本编号,不能把提交文件中的预测当成真实标签。

sample_submission.csv 是输出格式示例,submission.csv 是已有预测文件。两者都应包含 ImageId,Label,ID 从 1 连续到测试样本数。格式合格不代表预测正确,也不能仅凭文件名确认是哪一次训练生成的。

二、实际文件检查结果

检查程序逐行验证了完整表头、精确字段数、标签范围和所有像素的整数范围;以下不是从竞赛说明里复制的预期数字,而是对当前下载材料的统计。行数均不含表头。

项目 训练集 测试集
数据行数 42,000 28,000
每行字段数 785 784
原始像素范围 0 至 255 0 至 255
像素总数 32,928,000 21,952,000
零像素个数 26,621,312 17,753,313
非零像素比例 19.152964% 19.126672%

标签 0 到 9 的训练样本数依次为 [4132, 4684, 4177, 4351, 4072, 3795, 4137, 4401, 4063, 4188]。所有类别都有样本,但并非完全均衡;始终预测最多的类别 1,也能在这份训练数据上得到约 11.15%。因此“超过 10%”不是充分的模型有效性判据。

实际训练文件中数字 0 到 9 的样本数量柱状图
逐行统计得到的类别计数;这张图描述数据组成,不是模型准确率。

已有 submission.csv 和格式示例均通过 28,000 行、连续 ID 和 0 到 9 标签检查。数据结构正确不能证明没有重复样本、训练/验证交叉、作者重叠或标注错误;本次没有执行这些独立性与标注质量检查。

三、CSV 能读出来,不等于读对了

原始 C 加载器保留了以下实现:训练标签用 atoi,像素用 atof,再除以 255。这段代码展示数据映射,不是生产级输入校验器。

y_train[sample_count] = atoi(tokens[0]);
for (int j = 0; j < FEATURES; j++) {
    X_train[sample_count][j] = atof(tokens[j + 1]) / 255.0;
}

其 strtok 分词会合并连续分隔符;调用原函数测试 1,,2 得到 2 个 token,而不是保留中间空字段。token 数量上限还会让 1,2,3,4 在容量 3 时返回 3,不能据此判断原行只有 3 列。加载器会跳过部分列数不对的行,却没有完整验证标签范围和数值,因此不要直接把不可信 CSV 交给它训练。

配套检查器使用标准库 csv.reader 保留字段结构,再显式检查 schema。它拒绝空文件、仅表头、错表头、缺列、多列、标签 10、空像素、nan、像素 256、负数和小数,共 11 个固定错误样例。整数文本限定为这份数据采用的规范形式,例如 0 到 255;不会把 0.0 自动修成整数。Python 的 CSV 解析本身不会替你完成这种业务校验,见 官方 csv 文档。

四、还原一行,检查空间索引

以下程序在实验包内可直接运行:python3 preview_first.py ../digit-assets/train.csv.zip。它调用同包的 validate_row,读取第一个数据行,不依赖前一段循环留下的变量,也不会解压或修改数据。

完整的首行字符图程序
"""Print one validated training row without unpacking or changing the data."""
import csv
import io
import sys
import zipfile
from audit_digits import PIXEL_HEADER, validate_row

with zipfile.ZipFile(sys.argv[1]) as archive:
    with archive.open("train.csv") as raw:
        with io.TextIOWrapper(raw, encoding="utf-8", newline="") as stream:
            reader = csv.reader(stream, strict=True)
            if next(reader, None) != ["label"] + PIXEL_HEADER:
                raise ValueError("unexpected training header")
            row = next(reader, None)
            if row is None:
                raise ValueError("no training rows")
            label, pixels = validate_row(row, True, 2)

print("label:", label)
for r in range(28):
    print("".join(".:*#"[pixels[28 * r + c] * 3 // 255]
                  for c in range(28)))

本次文件的首行标签为 1,程序输出 28 行、每行 28 个字符。字符图只是粗略预览,不能替代字段检查。特别要纠正一个容易误导的说法:把测试集的 row[1] 当成 pixel0,并不等价于图像规整地平移一格。它可能丢掉一个元素,也可能在展平索引的行边界发生串位;是否报错取决于读取方式。准确的检查应是表头、长度和 28*r+c 的对应关系。

五、为什么除以 255 不等于调整一次学习率

输入缩放会同时改变 logits、概率和梯度。对固定二分类例子,设 z=[0.01*x,0]、真实类别为 0,则 dW0=(p0-1)*x、db0=p0-1。实测 x=1 时 p0=0.502500、dW0=-0.497500;x=255 时 p0=0.927574、dW0=-18.468754。权重梯度并没有简单变成 255 倍,偏置梯度也发生了不同变化。

因此应保持训练和推理的像素缩放一致,并重新检查优化行为,而不是把“不归一化”概括为“学习率放大 255 倍”。除以 255 是这里定义的输入约定,不是适用于所有图像模型的唯一预处理。若额外估计均值或标准差,只能从训练部分拟合,再应用到验证与测试部分。

六、不要混用同名的两个项目版本

站点的独立 digit_softmax_classifier.c 已是 784 → 128 ReLU → 10 Softmax 的 MLP;旧 handwritten-digits-materials.zip 内的同名源码仍是 784 → 10 的线性 Softmax。两个版本的训练/测试 ZIP 和已有提交文件字节相同,但源码和模型 JSON 不同。旧包没有被替换,适合研究线性基线;不能解压后又用独立 MLP 文件覆盖其中一部分,再把它们当作同一次实验。

独立源码 SHA-256 前 12 位为 eddd081ee163,旧包内源码为 88b8953bac9f。完整校验和、ZIP 成员对照与原始统计见 检查结果 JSON。哈希只识别文件字节,不证明训练来源或数据授权。

七、复跑与继续阅读

下载 版本核对与数值检查实验包,按 双语说明 准备现有数据。数据检查仅需 Python 3.10+ 标准库;本次实际运行版本为 Python 3.13.9。绘图依赖是可选的,实验包不包含新的模型权重或数据集副本。

python3 audit_digits.py --assets ../digit-assets --out ../digit-results
python3 preview_first.py ../digit-assets/train.csv.zip

接着阅读 C 分类器的两个版本、梯度和损失,或 浏览器模型与概率解释。原有材料仍在 下载页,交互演示在 实验台。

发表回复

向下探索