手写数字实验记录:怎么把离线分类项目接进浏览器实验台
手写数字实验记录:怎么把离线分类项目接进浏览器实验台
站内搜索
直接问 AI

手写数字实验记录:怎么把离线分类项目接进浏览器实验台

浏览器里的手写数字模块做的是推理:加载权重,把 784 个灰度值变成十类概率,而不是在每次打开页面时重训完整数据集。理解这个边界还不够,必须确认页面到底加载了哪个文件。本次核对发现,旧项目压缩包和独立模型 JSON 的结构、元数据与内置样本都不一样。

检查日期:2026-09-08。本文给出文件层面的对照、三个固定输入的离线推理结果,以及线上空白画板的实际表现。没有新增训练成绩,没有把历史分数移植给当前模型,也没有替换在线权重或修改实验台交互。

一、当前模型与旧包不是同一份

页面配置加载的是独立 digit-playground-model.json。它包含 W1、b1、W2、b2 与 meta,构成 784 → 128 ReLU → 10 Softmax 的 MLP。全部 101,770 个参数通过维度和有限数值检查。文件 SHA-256 前 12 位是 51073f30e1b5。

文件 模型 样本数
独立文件 MLP
784 / 128 / 10
0
旧包成员 线性模型
784 / 10
40

当前 JSON 的元数据只有模型名、20 轮和学习率 0.005,没有验证准确率。旧 JSON 有 7,850 个参数,哈希前 12 位为 6b256e9455cc;其元数据记载 10,000 条训练样本、2,000 条验证样本、18 轮、学习率 0.35 和验证准确率 90.65%。表中的样本数指嵌入文件、供页面选择的样本,不是训练集大小。

90.65% 只是一条旧文件中的元数据记录,本次没有复核其划分和训练过程。它不是当前 MLP 的验证成绩,更不是手绘输入识别率。旧 C 源码的 20 轮、学习率 0.01 又与该旧 JSON 记录不同;不能将几个文件直接说成同一次训练的输入和输出。

独立 C 文件虽然与当前 JSON 的 MLP 形状一致,但没有导出 JSON 权重的代码,也没有足够的检查点与训练日志把两者绑定。文件名和网络层数相同不构成来源证明。完整哈希和成员对照见 检查记录。

二、为什么样本列表和验证分数是空的

浏览器脚本兼容两种权重结构;样本选择项来自 JSON 的 samples 数组,验证分数来自 meta.validation_accuracy。当前独立文件没有这两个字段,所以本次线上检查得到样本选项数 0、验证准确率显示“-”。这不是一个隐藏的 90.65% 成绩,也不是文章少写了一个数字。

手绘和概率推理仍可使用,但当前文件并不支持文章旧版所承诺的内置样本浏览。旁边的样本预览图片是单独的展示资源,不等于模型 JSON 里存在可选择的样本。本文记录这一功能限制,不通过换回旧模型或编造样本来掩盖它。

页面里的笔刷会生成灰度像素,数值被限制在 0 到 1;当前推理路径没有自动裁边、缩放到特定大小或质心居中。手绘输入和本文的二值测试图不完全相同,因此不要用肉眼画出的相似线条要求逐位一致的概率。

三、空白与平移输入的实际输出

离线检查直接读取当前 JSON,用 Python 浮点数执行两层矩阵运算、ReLU 和减最大值 Softmax。定义三个固定输入:全部为 0 的空白;第 14 列、第 5 到 22 行为 1 的竖线;同样竖线移动到第 7 列。坐标从 0 开始,其他像素都为 0,没有插值或自动居中。

固定输入 Top-1 Top-2
空白 5;52.87% 6;10.23%
竖线,列 14 1;99.96% 9;0.0159%
竖线,列 7 4;40.59% 0;21.93%
空白和两条不同位置的合成竖线,以及当前 MLP 对它们的预测
相同权重、明确的输入数组;这些合成探针没有预设真实类别,不构成准确率测试。

线上先点击“清空”,再点击“识别”,实际显示数字 5、52.9%,与离线空白结果按界面精度取整一致。另两条线的数值是离线固定数组测试,不是用网页笔刷逐像素复刻后的截图结果。完整十类概率、概率和与输入哈希都保存在实验包中。

空白时网络并非没有可算的内容:a1=ReLU(b1),再由 W2*a1+b2 产生输出。竖线的平移改变了激活的像素权重,模型的首选类别也改变。这是当前权重对一个特定扰动的敏感性证据,不足以估计整体手写数字错误率。

四、概率、间隔和准确率回答不同问题

Top-1 概率、Top-2 概率和两者差值适合描述一次输出,但不是“输入属于训练分布”的证明。这个模型的输出被迫分配给十个数字,即使输入为空白也会给一个类别。概率接近 1 不能自动解释为同类输入约 100% 正确;概率接近均匀也不能单独证明模型从未见过这种输入。

准确率需要一组有真实标签的样本。概率校准需要比较代表性样本上分数区间与实际正确比例。分布外检测则需要单独设计非数字、空白和异常输入的评估集合。三者不能用一个 90.65% 历史字段或一次 Top-1 间隔相互替代。

保留失败输入比只展示成功的数字更有解释力,但不要事后挑一小批有利样本作为“测试集”。本次三个数组只用于解释机制,没有真实类别,也没有被计入任何准确率分母。

五、质心检查是诊断,不是已经上线的修复

笔画的位置、大小、灰度和粗细可能与训练样本不同;模型本身、解析错误或权重来源也可能造成误判,不能先认定“模型没有问题”。下面的函数只计算灰度质心相对网格中心的偏移,不会移动图像,也没有接入在线推理。

带空白检查的质心诊断程序
"""Diagnostic offset only: this does not resample or improve a classifier."""
import math


def centroid_offset(pixels):
    if len(pixels) != 784 or any(not math.isfinite(v) or not 0 <= v <= 1 for v in pixels):
        raise ValueError("expected 784 finite grayscale values in 0..1")
    mass = sum(pixels)
    if mass == 0:
        return None
    cx = sum((i % 28) * v for i, v in enumerate(pixels)) / mass
    cy = sum((i // 28) * v for i, v in enumerate(pixels)) / mass
    return 13.5 - cx, 13.5 - cy


if __name__ == "__main__":
    from audit_digits import probe_inputs
    for name, pixels in probe_inputs().items():
        print(name, centroid_offset(pixels))

在本文固定输入上,输出依次为 None、(-0.5,0.0) 和 (6.5,0.0)。空白没有可定义的灰度质心,不能除以零。坐标采用 0 到 27 的像素中心,所以几何中心是 13.5;半像素平移需要说明插值方法。

若后续实现裁边、等比缩放或居中,应先定义与训练一致的预处理,再用固定、未用于调参的手绘验证集比较原始与处理后的逐样本结果。裁剪可能丢笔画,插值可能改变灰度;本次没有证据保证“加上居中就显著提高准确率”,也不能把这种尚未执行的对照写成实验结论。

六、复跑与报告的最小记录

下载 模型文件核对实验包,按 README 准备独立资源,执行:

python3 audit_digits.py --assets ../digit-assets --out ../digit-results
python3 centroid_offset.py

数据与推理检查只需 Python 标准库,本次使用 Python 3.13.9。记录至少应包含完整模型哈希、输入像素及其哈希、归一化约定、推理程序版本、十类概率,以及样本是否有真实标签。更换权重后应重新计算,不能把本页数值当成所有版本的固定答案。

下一步可阅读 数据集检查与空间索引和C 实现的两个版本与损失反例;原始资料仍在 下载区,当前交互模块在 实验台。本文把已测行为、历史元数据和未来实验区分开,让读者能够复核其中一项,而不是只能相信一个总分。

发表回复

向下探索