在浏览器中训练 MNIST:tfjs-examples/mnist 手写数字识别示例源码解析
示例工程【免费下载链接】tfjs-examplesExamples built with TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-examples点击查看免费下载本文围绕 TensorFlow.js 官方示例仓库 tfjs-examples 中的 mnist 示例展开深入讲解如何使用 TensorFlow.js 的 Layers API 在浏览器中完成 MNIST 手写数字识别模型的训练、评估与推理。读完本文你将掌握基于tf.sequential()搭建卷积神经网络ConvNet与全连接网络DenseNet的完整流程、MNIST 雪碧图数据集的加载与张量化方法以及利用model.fit()回调在训练过程中实时绘制 loss/accuracy 曲线的实战技巧。示例概览一个浏览器端的数字识别训练器本示例的核心目标是使用 TensorFlow.js 的 Layers API即tf.layers高层 API在浏览器页面中训练 MNIST 手写数字识别模型。这是 tfjs-examples 仓库中最基础的图像分类示例之一对应的页面标题为 TensorFlow.js: Digit Recognizer with Layers见 index.html。按照 mnist/README.md 的说明示例在训练过程中会每 5 步steps在 1000 个随机测试集样本上计算准确率并随训练进度实时绘制 loss 与 accuracy 曲线。同时文档也给出了一条实用的工程建议可以通过减少参与准确率评估的样本数、降低评估频率来缩短训练时间——因为测试集评估本身也会消耗计算资源。需要注意的一点是当前版本中整个 MNIST 数据集被预先拼合存储在一张 PNG 雪碧图sprite image中data.js 负责将它解析并转换为Tensor。README 中注明这种加载方式在不久的将来会变得更加简单事实上仓库后续也衍生出了mnist-coremnist-core/README.md使用底层 tfjs-core API 而非 Layers API等其他实现感兴趣的读者可以对比阅读。项目结构与运行方式mnist/目录是一个完全独立、可拷贝到其他项目中直接使用的示例文件职责index.html页面骨架训练参数表单、训练进度区、推理结果展示区index.js核心逻辑模型定义、编译、训练、评估与推理data.js数据层MnistData类负责加载并张量化 MNIST 数据ui.jsUI 层状态提示、loss/accuracy 曲线绘制、测试结果渲染package.json依赖与脚本配置Parcel 打包在 package.json 中可以看到该示例仅依赖两个运行时包tensorflow/tfjs版本 2.0.0核心库提供tf.sequential、tf.layers等 APItensorflow/tfjs-vis^1.1.0用于在页面上渲染 loss/accuracy 折线图。运行方式同样在 package.json 的 scripts 中定义# 开发模式Parcel 启动本地服务器并自动打开浏览器 yarn watch # 生产构建输出到 dist 目录 yarn build其中watch实际执行parcel index.html --no-hmr --open由 Parcel 直接以 index.html 为入口完成 ES Module 的打包与热更新。数据加载将 MNIST 雪碧图转换为 TensorMNIST 数据集共有65000 个样本其中55000 个用于训练、10000 个用于测试对应 data.js 中的常量定义。每张图片为28 × 28的灰度图共10 个类别数字 09。数据加载的核心逻辑全部封装在 data.js 的MnistData类中其数据来源是两处远端资源const MNIST_IMAGES_SPRITE_PATH https://storage.googleapis.com/learnjs-data/model-builder/mnist_images.png; const MNIST_LABELS_PATH https://storage.googleapis.com/learnjs-data/model-builder/mnist_labels_uint8;雪碧图所有 65000 张图片纵向拼接成一张大 PNG每行 28 像素、每段 5000 张标签文件一个Uint8Array格式的二进制文件每个标签为 one-hot 编码、长度 10。load()方法的处理流程如下data.js通过new Image()加载雪碧图并设置img.crossOrigin 以支持跨域读取在内存中开辟65000 * 28 * 28 * 4字节的ArrayBuffer按每次 5000 张的分块方式用canvas.drawImage()裁剪出对应图块再经ctx.getImageData()读出像素数据由于图片是灰度图四个通道取值相同因此只读取红色通道即可并将像素值除以 255 归一化到[0, 1]区间data.js通过fetch()并行加载标签文件与图片加载通过Promise.all等待完成最后分别slice出训练集前 55000 个与测试集后 10000 个的图片与标签。加载完成后getTrainData()与getTestData(numExamples)负责将扁平数组转换为张量图片数据重塑为[numExamples, 28, 28, 1]的四维张量tf.tensor4d最后一维 1 表示单通道灰度标签数据重塑为[numExamples, 10]的二维张量tf.tensor2d即 one-hot 编码。getTestData()还支持传入numExamples参数通过slice截取部分测试样本——这正是页面推理示例板块与训练中定期评估所依赖的能力。从源码结构看MnistData的设计具有很好的通用性它把远端数据 → 浏览器内存 → Tensor的完整链路封装成一个可复用的数据管理类。官方注释也明确提示如果你有自定义数据完全可以仿照这个类来编写自己的数据加载器index.js。构建模型ConvNet 与 DenseNet 的对比页面允许在两种模型间切换Model Type下拉框对应的构建函数分别是createConvModel()与createDenseModel()。卷积网络ConvNetcreateConvModel()使用tf.sequential()搭建了一个典型的 CNN 结构index.js各层配置如下层配置说明Conv2DinputShape: [28, 28, 1]kernelSize: 3filters: 16activation: relu输入层同时承担首次卷积接收 28×28 灰度图MaxPooling2DpoolSize: 2strides: 2以区域最大值做下采样Conv2DkernelSize: 3filters: 32activation: relu加深特征提取MaxPooling2DpoolSize: 2strides: 2再次下采样Conv2DkernelSize: 3filters: 32activation: relu第三层卷积Flatten—将二维特征图展平为一维向量Denseunits: 64activation: relu全连接隐藏层Denseunits: 10activation: softmax输出层softmax 产生 10 个类别的概率分布源码注释中对该结构的每个环节都有通俗解释第一层卷积既充当输入层又执行第一次卷积MaxPooling 用区域内的最大值而非平均值来做下采样最后一层 softmax 的输出向量各元素求和为 1可解释为概率分布。全连接网络DenseNetcreateDenseModel()只包含展平层与两个全连接层index.jsmodel.add(tf.layers.flatten({inputShape: [IMAGE_H, IMAGE_W, 1]})); model.add(tf.layers.dense({units: 42, activation: relu})); model.add(tf.layers.dense({units: 10, activation: softmax}));源码注释明确指出该模型拥有约31000~31k个参数与上面的卷积网络参数量大致相当但因为它没有利用图像的空间结构信息预期训练后准确率会明显低于 ConvNet。这种参数量相同、结构不同的对照实验设计是理解卷积为何有效的绝佳教材——同一页面上即可直观看到两种模型的准确率差异。编译与训练关键超参数解读train()函数集中展示了模型编译与训练的全部配置index.js这些超参数也是 README 所述训练行为的具体落地model.compile({ optimizer, // rmsprop loss: categoricalCrossentropy, // 多分类标准损失 metrics: [accuracy], // 人类可读的评估指标 }); const batchSize 320; // 每次权重更新前分组的样本数 const validationSplit 0.15; // 留出 15% 训练数据做验证 const trainEpochs ui.getTrainEpochs(); // 从页面输入读取默认 3优化器rmsprop一种迭代式最小化损失函数的方法通过在训练中逐步调整权重参数来逼近损失极小值损失函数categoricalCrossentropy多分类任务的标准选择可微、适合梯度下降训练但不易被人直观解读指标accuracy直接衡量分类正确的样本占比但它不可微、不能作为损失函数因此单独作为评估指标batchSize 320源码注释给出权衡原则——过小的 batch 每次仅用极少样本更新权重、泛化能力差过大的 batch 占用更多内存且准确率并不保证更高validationSplit 0.15从训练集中留出最后 15% 作为验证集用于在训练期间监控过拟合。训练轮数trainEpochs由 UI 读取ui.js 中的getTrainEpochs()页面默认值为 3见 index.html。训练过程中的实时可视化回调model.fit()通过callbacks对象接入训练事件循环index.js这是本示例边训练边出图的关键机制onBatchEnd(batch, logs)每个 batch 结束时触发。这里用totalNumBatches由训练样本数、validationSplit、batchSize 与 epochs 推算得出计算并显示训练完成百分比调用 ui.js 的plotLoss与 ui.js 的plotAccuracy实时绘制训练集曲线每 10 个 batch 触发一次onIteration回调以刷新页面下方的推理示例最后await tf.nextFrame()让出主线程保证页面不冻结onEpochEnd(epoch, logs)每个 epoch 结束时将logs.val_acc作为验证准确率记录并绘制验证集的 loss/accuracy 曲线点。底层曲线绘制由tensorflow/tfjs-vis的tfvis.render.linechart()完成ui.js同时展示训练集与验证集两条序列x 轴为 batch 编号y 轴分别为 Loss 与 Accuracy。这里可以对照 README 的表述理解设计意图文档中描述的是每 5 步在 1000 个随机测试样本上评估准确率这一目标行为而在当前 index.js 的实现中验证集准确率由validationSplit划分的验证数据在每个 epoch 结束时计算推理示例面板则每 10 个 batch 用 100 个测试样本刷新一次。两种方式目的一致——在训练过程中持续获得模型当前表现如何的反馈。评估与推理argMax 与 tf.tidy训练完成后的整体评估model.fit()返回后代码调用model.evaluate(testData.xs, testData.labels)在全部 10000 个测试样本上计算最终指标index.jsconst testResult model.evaluate(testData.xs, testData.labels); const testAccPercent testResult[1].dataSync()[0] * 100; const finalValAccPercent valAcc * 100; ui.logStatus( Final validation accuracy: ${finalValAccPercent.toFixed(1)}%; Final test accuracy: ${testAccPercent.toFixed(1)}%);最终会在页面状态栏打印验证准确率与测试准确率两个数字。推理示例面板showPredictions()取 100 个测试样本进行预测index.js是整个推理链路的浓缩tf.tidy(() { const output model.predict(examples.xs); const labels Array.from(examples.labels.argMax(axis).dataSync()); const predictions Array.from(output.argMax(axis).dataSync()); ui.showTestResults(examples, predictions, labels); });其中三个 API 的用途值得展开tf.tidy()回调中创建的所有中间张量会在执行完毕后自动释放显存/内存免去手动dispose()的负担避免长时间训练后内存泄漏tf.argMax(axis)one-hot 编码下模型输出是一个概率分布向量argMax取概率最大的下标即为预测类别如argmax([0.07, 0.1, 0.03, 0.75, 0.05]) 3dataSync()同步地将 GPU 上的张量值下载到普通 JavaScript 数组便于在 CPU 侧渲染 UI非阻塞版本是data()。随后 ui.js 的showTestResults()将每个测试样本绘制到独立 canvas 上并标注pred: N预测正确时背景为绿色pred-correct、错误时为红色pred-incorrect效果一目了然。浏览器交互界面index.html 将整个训练流程组织为四个 sectionTraining Parameters训练参数Model Type下拉框ConvNet / DenseNet、# of training epochs输入框默认 3、以及 Load Data and Train Model 训练按钮Training Progress训练进度状态文本、loss 与 accuracy 两个折线图 canvasInference Examples推理示例动态生成 100 个测试样本的图片与预测标签。按钮点击后ui.js 的setTrainButtonCallback()会立即禁用按钮和模型类型下拉框防止训练过程中重复触发随后执行 index.js 中注册的主流程回调ui.setTrainButtonCallback(async () { ui.logStatus(Loading MNIST data...); await load(); // 1. 加载 MNIST 数据 ui.logStatus(Creating model...); const model createModel(); // 2. 按所选类型创建模型 model.summary(); // 打印模型结构到控制台 ui.logStatus(Starting model training...); await train(model, () showPredictions(model)); // 3. 训练 定期刷新推理示例 });整个流程严格遵循加载数据 → 构建模型 → 训练 → 评估推理的经典链路任何一步出现问题都能通过页面状态栏的logStatus文案与浏览器控制台定位。结语与延伸方向tfjs-examples/mnist 是理解在浏览器中完成完整深度学习训练流程的最佳起点它在一个页面内集成了数据加载、模型构建、超参数配置、训练可视化与推理展示且每一环节都配有清晰的源码注释。在此基础上仓库还提供了多种进阶方向可供继续研究mnist-core不使用 Layers API改用底层 tfjs-core 手写训练过程适合理解梯度与权重更新的底层原理mnist-transfer-cnn基于预训练 CNN 的迁移学习示例mnist-acgan对抗生成网络ACGAN在 MNIST 上的应用。读者可以把 mnist 目录整体拷贝到自己的项目中替换 data.js 的数据加载逻辑与 index.js 的模型定义即可快速改造为任意自定义图像分类任务的浏览器端训练器。赞分享示例工程【免费下载链接】tfjs-examplesExamples built with TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-examples点击查看免费下载相关推荐终极指南如何在浏览器中实现ConvNetJS MNIST手写数字识别终极指南如何在浏览器中实现ConvNetJS MNIST手写数字识别 ConvNetJS是一个强大的JavaScript深度学习库让您能够在浏览器中训练卷积深度学习机器学习RIOT 中的 uTensor MNIST 手写数字识别示例从 TensorFlow 模型训练到 MCU 端推理RIOT 中的 uTensor MNIST 手写数字识别示例从 TensorFlow 模型训练到 MCU 端推理 导读 本文围绕 RIOT 仓库 tests/物联网嵌入式操作系统实时系统Cleanlab MNIST示例基于PyTorch的手写数字识别Cleanlab MNIST示例基于PyTorch的手写数字识别 引言数据质量决定模型上限 在机器学习实践中我们常常面临一个残酷的现实 垃圾进垃圾出人工智能机器学习数据清洗数据质检创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

K8s Ingress网关性能调优:从2秒到100毫秒的排查实战

K8s Ingress网关性能调优:从2秒到100毫秒的排查实战

接到运维告警的时候,第一反应是后端应用又出问题了。可躲开那一波“2 秒左右”的慢请求,我盯着监控面板看了好一阵——应用自身 P50 只有 30 毫秒,P99 却在 1.8 秒到 2.3 秒之间反复横跳。所有慢请求都卡在 K8s Ingress 网关上。这个标题里的…

2026/10/15 20:09:40 阅读更多 →
K8s Ingress延迟优化实战:从2秒到100毫秒的配置调优

K8s Ingress延迟优化实战:从2秒到100毫秒的配置调优

线上有个业务一直反馈页面打开要2秒左右,一开始大家都以为是后端某接口慢,前后端吵了好几轮也没结论。后来我拉上运维把链路从头到尾捋了一遍,才发现问题根本不在业务代码,而是卡在K8s Ingress网关这层。那次优化做完,…

2026/10/15 20:09:40 阅读更多 →
阿波罗11号飞控计算机复刻:极致资源约束下的实时系统设计

阿波罗11号飞控计算机复刻:极致资源约束下的实时系统设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 20:09:40 阅读更多 →

最新新闻

2025年度广东省网络空间安全协会科技进步奖揭晓,itc保伦股份产学研项目获评二等奖

2025年度广东省网络空间安全协会科技进步奖揭晓,itc保伦股份产学研项目获评二等奖

近日,广东省网络空间安全协会2025年度科学技术奖评选结果正式揭晓,广东保伦电子股份有限公司(以下简称“itc保伦股份”)联合华南理工大学申报的“智能超高清视讯系统关键技术研究与应用”项目,荣获科技进步奖二等奖。该…

2026/10/15 20:51:51 阅读更多 →
Vugu 2.x DOM 事件处理实战:基于 Go+WebAssembly 的 `dom-events` 示例深度解析

Vugu 2.x DOM 事件处理实战:基于 Go+WebAssembly 的 `dom-events` 示例深度解析

前端Web框架 【免费下载链接】vugu Vugu: A modern UI library for GoWebAssembly (experimental) 项目地址: https://gitcode.com/gh_mirrors/vu/vugu 点击查看 免费下载 导读 本文以 Vugu 2.x 仓库中的 dom-events 示例 为骨架,系统讲解在 Vugu&…

2026/10/15 20:51:51 阅读更多 →
Guzzle 3 HTTP CachePlugin 深度实战:透明代理缓存的配置、再验证与扩展机制详解

Guzzle 3 HTTP CachePlugin 深度实战:透明代理缓存的配置、再验证与扩展机制详解

后端电商前端 【免费下载链接】CRMEB 🔥CRMEB开源商城免费开源多语言商城系统,Tp6框架商城,系统可商用;包含小程序商城、H5商城、公众号商城、PC商城、App,支持分销、拼团、砍价、秒杀、优惠券、积分、会员等级、小程序…

2026/10/15 20:51:51 阅读更多 →
长沙智能体培训机构怎么选不踩坑 四步筛选法

长沙智能体培训机构怎么选不踩坑 四步筛选法

摘要本文梳理长沙智能体培训市场的常见坑点,给出四步筛选法与逐项核验标准,覆盖资质、课程项目、师资、合同收费四个核心环节,帮助学习者系统规避无资质办学、低价引流、虚假项目、隐形消费等风险。一、认知背景:市场鱼龙混杂&…

2026/10/15 20:51:51 阅读更多 →
Firebase JS SDK 的 TotpMultiFactorAssertion:TOTP 第二因子认证断言的注册与登录实战解析

Firebase JS SDK 的 TotpMultiFactorAssertion:TOTP 第二因子认证断言的注册与登录实战解析

开发工具后端 【免费下载链接】firebase-js-sdk Firebase Javascript SDK 项目地址: https://gitcode.com/gh_mirrors/fi/firebase-js-sdk 点击查看 免费下载 本文以 Firebase JavaScript SDK 官方 API 参考文档 auth.totpmultifactorassertion.md 为骨架&#xff…

2026/10/15 20:51:51 阅读更多 →
ThinkJS 2.x 分页组件 think-pagination 使用指南:从 countSelect 到模板渲染的完整实践

ThinkJS 2.x 分页组件 think-pagination 使用指南:从 countSelect 到模板渲染的完整实践

后端Web框架 【免费下载链接】thinkjs Use full ES2015 features to develop Node.js applications, Support TypeScript. 项目地址: https://gitcode.com/gh_mirrors/thi/thinkjs 点击查看 免费下载 本指南以 packages/think-pagination/README_v2.md 为骨架&…

2026/10/15 20:50:49 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →