
示例工程【免费下载链接】tfjs-examplesExamples built with TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-examples点击查看免费下载本文围绕 TensorFlow.js 官方示例仓库 tfjs-examples 中的mnist-transfer-cnn示例展开系统讲解如何把 Python Keras 预训练好的 CNN 模型转换为 TensorFlow.js 格式后加载进浏览器再通过冻结特征提取层、只微调全连接层的方式完成数字 59的分类任务。读完本文你将掌握tf.loadLayersModel()加载远程模型、浏览器内model.fit()微调、三种迁移学习训练模式的选择以及如何用双端口 HTTP 服务器同时提供页面与模型资源。示例概述在浏览器中完成一次迁移学习该示例完整演示了TensorFlow.js Layers API 下的迁移学习Transfer Learning流程其设计思路继承自 Keras 官方示例mnist_transfer_cnn实现细节见 python/mnist_transfer_cnn.py。整体分为两个阶段Python 端预训练用 Keras 在 MNIST 数据集前 5 个数字04上训练一个简单卷积网络将模型产物拓扑 JSON 权重托管到 URL浏览器端微调用tf.loadLayersModel()把模型加载进浏览器冻结卷积层仅让后面的全连接层在数字 59 的数据上重新训练fine-tuning。该演示验证了一个核心观点详见 index.html 中的 Description 说明预训练模型的前几层可以作为特征提取器feature extractor复用于新数据从而显著加快新任务上的训练速度。启动示例只需两条命令yarn yarn watch第一条安装依赖tensorflow/tfjs、tensorflow/tfjs-vis等见 package.json第二条启动开发服务器并在浏览器中打开页面。端到端工作流从 Keras 预训练到浏览器微调整个示例的数据流可以概括为下图所示链路本文依据 index.js 与 python/mnist_transfer_cnn.py 源码梳理MNIST 全量数据 │ ├─ 数字 0~4lt5── Python Keras 训练 CNN ── tfjs.converters.save_keras_model │ │ │ ▼ │ model.json 权重托管 URL │ │ │ 浏览器 tf.loadLayersModel() 加载 │ └─ 数字 5~9gte5标签减 5── 导出 gte5.train.json / gte5.test.json │ ▼ 浏览器 fetch 加载 ── 张量化 ── model.fit() 微调关键点在于预训练用的数据04与微调用数据59刻意划分开这样微调时模型从未见过数字 59才能真实检验迁移学习的效果。在浏览器端模型与数据有两套来源分别定义在 index.js 的HOSTED_URLS与LOCAL_URLS中资源托管地址HOSTED本地地址LOCAL端口 1235预训练模型https://storage.googleapis.com/tfjs-models/tfjs/mnist_transfer_cnn_v1/model.jsonhttp://localhost:1235/resources/model.json微调训练数据.../mnist_transfer_cnn_v1/gte5.train.jsonhttp://localhost:1235/resources/gte5.train.json微调验证数据.../mnist_transfer_cnn_v1/gte5.test.jsonhttp://localhost:1235/resources/gte5.test.json页面加载后index.js 的setupMnistTransferCNN()会先通过 HEAD 请求探测两套 URL 是否可达把可用的加载模型按钮load-pretrained-remote/load-pretrained-local显示出来。Python 端预训练模型架构与数据切分模型架构特征层 分类层train_and_save_model()函数把网络显式拆成两组见 python/mnist_transfer_cnn.py特征提取层feature_layers共 7 层Conv2D(32, 3×3)→ReLU→Conv2D(32, 3×3)→ReLU→MaxPooling2D(2×2)→Dropout(0.25)→Flatten分类层classification_layers共 5 层Dense(128)→ReLU→Dropout(0.5)→Dense(5)→Softmax。输入形状由 python/mnist_transfer_cnn.py 中的INPUT_SHAPE决定通道在前的环境为(1, 28, 28)否则为(28, 28, 1)。整体 12 层结构之所以重要是因为浏览器端冻结前 7 层的编号正是以此为基准。命令行参数一览Python 脚本通过 argparse 暴露了全部训练超参数python/mnist_transfer_cnn.py参数默认值含义--epochs5Keras 预训练轮数--batch_size128训练批大小--filters32卷积层滤波器数量--pool_size2最大池化窗口大小--kernel_size3卷积核尺寸--artifacts_dir/tmp/mnist.kerasTensorFlow.js 模型产物保存目录--optimizeradam预训练优化器名称--gte5_cutoff1024写入 JSON 的 gte5 样本数上限0 时截断--gte5_data_path_prefix/tmp/mnist_transfer_cnn.gte5gte5 训练/测试 JSON 文件路径前缀数据切分与序列化load_mnist_data()python/mnist_transfer_cnn.py把 MNIST 切分成两组lt5组标签 5即数字 04用于预训练gte5组标签 5且标签统一减 5数字 5 的标签变为 0数字 9 的标签变为 4用于浏览器端微调。write_mnist_examples_to_json_file()python/mnist_transfer_cnn.py把每个样本序列化为{x: [28×28 灰度值二维数组], y: 整数标签}的 JSON 数组分别写出*.train.json与*.test.json。对应单测testWriteGte5DataToJsFiles与testTrainWithFakeDataAndSave在 python/mnist_transfer_cnn_test.py 中验证了该序列化格式与模型保存流程。浏览器端模型加载tf.loadLayersModel()浏览器端的加载逻辑封装在 loader.js 中urlExists(url)对资源做fetch(url, {method: HEAD})探测返回response.ok决定页面显示哪个加载按钮loadHostedPretrainedModel(url)核心一行await tf.loadLayersModel(url)返回tf.Model实例含拓扑与权重。加载成功后通过ui.disableLoadModelButtons()隐藏加载按钮防止重复加载源码注释提到受 tfjs issue #34 限制同一模型不能重复加载loadHostedData(url, numClasses)fetchJSON 后调用util.convertDataToTensors()转为张量。在 index.js 的init()中模型加载完成后会打印model.summary()并通过tfVis.show.modelSummary()在 tfjs-vis 面板中可视化this.imageSize从model.layers[0].batchInputShape[1]读取即 28this.numClasses固定为 5。张量转换与 ASCII 位图交互JSON 数据 → 训练张量util.js 的convertDataToTensors()完成三件事把[示例数, 28, 28]的tf.tensor3dreshape 为[示例数, 28, 28, 1]用tf.mul(tf.scalar(1 / 255), xsTensor)将 0255 灰度归一化到 01标签经indexToOneHot转成 5 类 one-hot 向量。像素编辑与预测util.js 的textToImageArray(text, imageSize)把文本编辑框中的数字矩阵解析为像素值并除以 255最终构造[1, 28, 28, 1]的tf.tensor4d。预测过程在 index.js 的predict()中完成并整体包在tf.tidy()中以保证中间张量被自动回收const image util.textToImageArray(imageText, this.imageSize); const predictOut this.model.predict(image); const winner predictOut.argMax(1); ui.setPredictResults(predictOut.dataSync(), winner.dataSync()[0] 5);由于微调模型输出的是标签 04对应数字 59所以最终类别要加 5 还原为真实数字。浏览器内微调三种训练模式对比retrainModel()index.js是迁移学习的核心根据用户在界面选择的training-mode走三条不同路径训练模式源码实现适用场景freeze-feature-layers冻结特征层遍历this.model.layers前 7 层置trainable false最典型的迁移学习特征提取器不动只训最后 5 层分类器no-freezing不冻结不做任何设置所有层均可训练对照组观察全部层训练时的收敛速度与损失波动reinitialize-weights重置权重通过tf.models.modelFromJSON({modelTopology: this.model.toJSON(null, false)})重建同拓扑、随机初始化权重的模型等效于从零训练用于对照迁移学习收益随后统一compile与fitthis.model.compile({ loss: categoricalCrossentropy, optimizer: tf.train.adam(0.01), metrics: [acc], }); const batchSize 128; const epochs ui.getEpochs(); // 界面输入默认 10 await this.model.fit(this.gte5TrainData.x, this.gte5TrainData.y, { batchSize: batchSize, epochs: epochs, validationData: [this.gte5TestData.x, this.gte5TestData.y], callbacks: [ ui.getProgressBarCallbackConfig(epochs), // 进度条回调 tfVis.show.fitCallbacks(..., [val_loss, val_acc], ...), // tfjs-vis 曲线 ] });值得注意的工程细节冻结前 7 层对应 Python 端 12 层结构中前 7 层两层 Conv2D 两层 ReLU 池化 Dropout Flatten见 index.html 的 Retrain Model 说明这样只允许最后 5 层参与训练与 Python 端网络定义严格对应。compile后再次model.summary()打印即可在控制台看到大量参数变为非可训练non-trainable。训练完成后验证集上的val_acc与val_loss会实时绘制在 tfjs-vis 的 Transfer Learning 标签页中。交互界面像素级编辑与概率输出页面布局见 index.htmlui.js 负责交互逻辑测试示例选择器预置数字 59 各 10 个5_1、5_2……9_10由 index.js 的prepTestExamples()从测试数据中按类别收集每类 10 个ASCII 位图编辑框28×28 的灰度值文本矩阵可在keyup事件下实时触发重新预测ui.js用于直观观察修改像素 → 类别概率变化模型输出表setPredictResults()ui.js以固定表头5 6 7 8 9展示五类概率保留 6 位小数并在下方标注Output class最大概率对应的数字进度条getProgressBarCallbackConfig()注册onTrainBegin/onEpochEnd/onTrainEnd回调更新#trainProg进度条并统计微调耗时训练期间禁用 Retrain 按钮防止并发训练。运行与部署双端口服务器的由来开发环境启动yarn watch实际执行 serve.sh该脚本同时启动两个 HTTP 服务器端口 1234parcel index.html提供页面与 JS 代码自动打开浏览器端口 1235node_modules/http-server/bin/http-server dist --cors -p 1235提供预训练模型与数据资源。之所以需要两个端口脚本注释给出了明确原因Parcel 打包器当时存在限制无法直接伺服预训练模型资源关联 parcel 仓库 issue #1098。因此页面代码与模型资源被拆到两个服务上LOCAL_URLS中localhost:1235正是为了对接后者。当 Parcel 服务退出时脚本会杀掉 http-server。生产构建如需产出静态产物可执行 package.json 中的build脚本yarn build它调用cross-env NODE_ENVproduction parcel build --no-scope-hoist index.html --public-url ./将页面打包为相对路径可部署的dist/目录。测试与验证仓库为 Python 端提供了基于unittest的测试 python/mnist_transfer_cnn_test.py覆盖两条关键链路testWriteGte5DataToJsFiles用随机伪造数据验证 gte5 数据能被正确写成*.train.json/*.test.json且每个样本的x为 28×28 结构testTrainWithFakeDataAndSave用小规模参数filters/kernel/pool/batch 均为 2epochs1跑通训练 保存流程并校验model.json产物可被正常解析。浏览器端则通过可视界面验证加载模型 → 选中某个 59 的测试示例 → 微调 → 观察概率表与验证曲线。从源码结构看index.js 中adam(0.01)的学习率与批大小 128 与 Python 端默认参数保持了一致的设计思路Python 端默认adam、batch_size128便于对照两套环境下的训练行为。小结mnist-transfer-cnn示例完整覆盖了迁移学习从Python 预训练到浏览器微调的全链路其工程要点可归纳为资源分离模型、训练数据、验证数据分别托管浏览器端用 HEAD 请求探测可用性层级冻结通过逐层设置trainable false实现特征层冻结且冻结编号与 Python 端网络结构严格对齐三模式对照冻结 / 不冻结 / 重置权重三种训练模式让迁移学习效果可以量化对比可视化反馈tfjs-vis 的模型摘要与训练曲线、ASCII 位图编辑框让训练过程与预测结果一目了然工具链协同双端口服务器绕开打包器限制为加载大模型 开发页面提供了可复用的工程模式。对想在浏览器端复用预训练视觉模型的开发者而言本示例是理解 TensorFlow.js 迁移学习 APItf.loadLayersModel、model.compile、model.fit与自定义回调的最佳入门样板。赞分享示例工程【免费下载链接】tfjs-examplesExamples built with TensorFlow.js项目地址https://gitcode.com/gh_mirrors/tf/tfjs-examples点击查看免费下载相关推荐OfficeCLI 完全指南一个二进制让 AI Agent 读写 Word/Excel/PPTOfficeCLI 完全指南一个二进制让 AI Agent 读写 Word/Excel/PPT 上午 9:40AI 助手接到任务出一份季度销售汇总——带CLIAI 应用MCP 服务安全烧录系统镜像Balena Etcher的技术实现与生产实践安全烧录系统镜像Balena Etcher的技术实现与生产实践 在嵌入式开发和系统部署场景中误操作导致数据丢失是技术人员面临的常见风险。传统命令行工具如dd桌面应用开发工具智能硬件手把手用 MuJoCo Python 绑定跑通物理仿真从 3 行代码到 60 帧视频手把手用 MuJoCo Python 绑定跑通物理仿真从 3 行代码到 60 帧视频 写机器人控制或强化学习时最磨人的往往不是算法而是环境装图形依赖、配物理引擎机器人机器学习图形学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考