尧图精选

用 TensorFlow.js 在浏览器中实现多变量线性回归:基于 tfjs-data 管道的 Boston Housing 房价预测实战

🕒 发布时间:2026/9/20 10:58:22 📁 来源:尧图网络
用 TensorFlow.js 在浏览器中实现多变量线性回归基于 tfjs-data 管道的 Boston Housing 房价预测实战【免费下载链接】tfjsA WebGL accelerated JavaScript library for training and deploying ML models.项目地址: https://gitcode.com/gh_mirrors/tf/tfjs本教程围绕 tfjs-data 的 Boston Housing 多元线性回归示例完整讲解如何用tensorflow/tfjs-data的 CSV 数据集 API 在浏览器端完成数据下载、特征/标签切分、洗牌、批处理、统计归一化再用tensorflow/tfjs的 Layers API 构建线性回归与多层感知机回归模型并借助model.fitDataset()/model.evaluateDataset()完成训练与评估。读完本文你将掌握一套可复用的「CSV 数据 → Dataset 管道 → 浏览器端模型训练」完整工作流并理解每个环节背后的源码实现。示例概览为什么用 Boston Housing 数据集Boston Housing 是一个经典回归数据集数据来自美国人口普查局U.S. Census Service收集的波士顿地区住房信息其目标变量medv表示房屋价格中位数单位$1000s。该示例的意义在于多变量回归模型需要同时消费多个特征如犯罪率、房龄、房间数、到就业中心距离等而不是单一输入数据管道驱动训练数据并非一次性塞进内存而是通过 tfjs-data 的Dataset懒加载管道lazy pipeline流式供给浏览器端训练所有下载、归一化、训练、绘图都在浏览器中完成无需 Python 后端。示例目录结构如下完整清单见 tfjs-data/demo/boston-housingtfjs-data/demo/boston-housing/ ├── data.ts # CSV 下载、解析、洗牌、特征数计算 ├── index.ts # 主流程归一化、模型定义、训练与评估 ├── normalization.ts # Tensor 层面的均值/标准差归一化工具 ├── stats.ts # 数据集列统计mean/stddev/min/max实现 ├── ui.ts # 状态输出与 Vega-Lite 训练曲线绘制 ├── index.html # 页面骨架状态区、基线区、两个训练按钮 └── package.json # 依赖与 watch 脚本环境准备安装依赖在 package.json 中示例依赖tensorflow/tfjsLayers/核心、tensorflow/tfjs-data数据管道、vega/vega-lite/vega-embed训练曲线可视化并用parcel作为零配置打包器。进入示例目录后安装依赖$ npm install # 或者 $ yarnNode 版本要求8.9.0见 package.json 的engines字段。注意示例依赖锁定在较早期版本如tensorflow/tfjs0.14.0如果希望使用当前仓库根目录下的最新 tfjs 源码需要走下面的本地链接流程。使用本地 tfjs 源码运行示例可选原 README 说明在 tfjs 迁移到独立的 tfjs-examples 仓库之前可以临时用「本地发布 yalc 链接」的方式让示例使用仓库内最新构建的tensorflow/tfjs-datacd ../../ yarn publish-local cd demo/boston-housing yarn link-local tensorflow/tfjs-data对应到当前仓库结构cd ../../即回到仓库根目录 package.json其publish-local脚本会构建各包并发布到本地 registry而link-local脚本在 demo 的 package.json 中定义为yalc link借助 yalc 将本地构建产物链接进示例的node_modules。若你只想快速跑通示例、不关心 tfjs-data 源码改动直接使用 npm/yarn 安装的官方发布版本即可无需执行这一步。构建并启动示例$ yarn watch该命令见 package.json 的watch脚本等价于cross-env NODE_ENVdevelopment parcel index.html --no-hmr --open即用 Parcel 以开发模式打包 index.html禁用 HMR热模块替换并自动打开浏览器。页面加载后自动下载三份 CSVtrain / validation / test计算特征统计量并完成归一化估算基线损失始终预测训练集目标均值时的 MSE显示两个按钮Train Linear Regressor线性回归与Train Neural Network Regressor神经网络回归。数据层源码解析从 CSV 到可训练 Dataset1. 用tfd.csv()读取远程 CSV 并标记标签列核心实现在 data.ts。数据托管在https://storage.googleapis.com/tfjs-examples/multivariate-linear-regression/data/共三份文件const TRAIN_FILENAME boston-housing-train.csv; const VALIDATION_FILENAME boston-housing-validation.csv; const TEST_FILENAME boston-housing-test.csv;读取的核心调用是tfd.csv()const csvDataset tfd.csv(url, {columnConfigs: {medv: {isLabel: true}}});url可以是远程 HTTP(S) URL在 Node 环境也可传file://开头的本地路径见 readers.ts 中csv()工厂函数其内部用URLDataSource包装columnConfigs中的isLabel: true把medv列标记为标签。根据 types.ts 中CSVConfig/ColumnConfig的定义csv()返回的CSVDataset元素结构会因此改变每个元素变为[features, label]二元数组前者是特征列键值对对象后者是标签列键值对对象。CSVConfig还支持其他常用选项供你迁移到自己的数据时参考配置项类型说明依据 types.tshasHeaderboolean首行是否为列名表头缺省时从首行推断列名columnNamesstring[]显式指定列名会覆盖从表头推断的结果hasHeaderfalse且未提供时会抛错columnConfigs对象按列名配置required空值报错、dtypeint32/float32/bool/string、default、isLabelconfiguredColumnsOnlyboolean为 true 时只解析columnConfigs中出现的列delimiterstring行内分隔符默认按 CSV 规则处理逗号delimWhitespaceboolean为 true 时以空白含连续多个空白作为分隔符2. map把对象形态转为数值数组tfd.csv()产出的元素是键值对对象而模型输入需要数值数组因此用map转换const convertedDataset csvDataset.map((row) { const [rawFeatures, rawLabel] row; const convertedFeatures Object.values(rawFeatures); const convertedLabel [rawLabel[medv]]; return [convertedFeatures, convertedLabel]; });Dataset.map()是 tfjs-data 的惰性转换算子详见 dataset.ts它不立即消费数据而是返回新的Dataset实际计算在迭代时逐元素进行。3. shuffle 与特征数计算return { dataset: convertedDataset.shuffle(100), numFeatures: (await csvDataset.columnNames()).length - 1 };shuffle(100)用大小为 100 的滑动窗口对元素做局部随机重排shuffle 窗口机制由 iterators/shuffle_iterator.ts 实现避免训练时相邻样本高度相关numFeatures 列数 - 1减去被标记为标签的medv列。columnNames()返回异步结果所以这里用了await。BostonHousingDataset类对三份文件统一走prepareDataset()最后分别暴露trainDataset、validationDataset、testDataset三个Dataset与numFeatures。loadData()中刻意只把trainDataset的numFeatures赋给模型使用——因为特征列名以训练集为准。统计与归一化让多特征处于同一量纲1. 统计 API 的实现示例使用computeDatasetStatistics()定义在 stats.ts对训练集计算每列统计量。该函数在仓库 statistics.ts 中有对应实现用 Welford 风格的单遍递推公式累积min/max/mean/variance/stddev/length避免数据全部驻留内存还支持sampleSize与shuffleWindowSize参数分别表示抽样统计与统计前洗牌。统计只应从训练集计算再把同样的均值和标准差应用到验证集/测试集防止「测试集信息泄漏到训练过程」。2. 归一化管线在 index.ts 的loadDataAndNormalize()中归一化被织入 Dataset 管道preparedData.trainData bostonData.trainDataset .map(row normalizeFeatures(row, featureStats)) .batch(BATCH_SIZE); preparedData.validationData bostonData.validationDataset .map(row normalizeFeatures(row, featureStats)) .batch(BATCH_SIZE); preparedData.testData bostonData.testDataset .map(row normalizeFeatures(row, featureStats)) .batch(BATCH_SIZE);每个row形如[features数组, label数组]normalizeFeatures对每个特征做标准分数变换(value - mean) / stddev使每个特征列近似零均值、单位标准差。batch(BATCH_SIZE)把流式元素聚合成固定大小的批次默认批大小BATCH_SIZE 40见 index.ts 顶部超参数区。3. Tensor 层面的归一化对照仓库还提供了 normalization.ts展示了张量视角的等价做法determineMeanAndStddev()用data.mean(0)、平方差、方差、开方计算每列均值与标准差normalizeTensor()则用data.sub(dataMean).div(dataStd)完成归一化。它对应「数据已转成 Tensor2D」的场景而示例主流程选择在 Dataset 管道内、转为张量之前做归一化体现了 tfjs-data 管道风格的写法。模型构建线性回归 vs 神经网络回归示例在 index.ts 中定义了两个可切换的模型1. 线性回归模型——单 Dense 层、无激活函数const model tf.sequential(); model.add(tf.layers.dense({inputShape: [bostonData.numFeatures], units: 1}));2. 多层感知机回归模型——两个各含 50 个单元的 sigmoid 隐藏层再接 1 单元输出层model.add(tf.layers.dense({inputShape: [numFeatures], units: 50, activation: sigmoid})); model.add(tf.layers.dense({units: 50, activation: sigmoid})); model.add(tf.layers.dense({units: 1}));两者的inputShape都取自动推导的numFeatures输出单元数为 1连续房价预测属于回归而非分类。训练与评估fitDataset / evaluateDatasetrun()函数index.ts负责编译、训练与评估model.compile({optimizer: tf.train.sgd(LEARNING_RATE), loss: meanSquaredError});优化器SGD学习率LEARNING_RATE 0.01损失函数meanSquaredErrorMSE与回归任务匹配训练轮数NUM_EPOCHS 250。训练直接消费 Dataset而不是x/y张量await model.fitDataset(preparedData.trainData, { epochs: NUM_EPOCHS, validationData: preparedData.validationData, callbacks: { onEpochEnd: async (epoch, logs) { trainLoss logs.loss; valLoss logs.val_loss; await ui.plotData(epoch, trainLoss, valLoss); } } });model.fitDataset()每轮消费一个批次并把每轮结束时的loss与val_loss通过onEpochEnd回调交给 UI 绘图。训练完成后用测试集评估const result (await model.evaluateDataset(preparedData.testData, {})) as tf.Tensor; const testLoss result.dataSync()[0];最终在页面状态区输出三项指标训练集最终损失、验证集最终损失、测试集损失均保留 4 位小数。基线与可视化判断模型「有没有用」基线损失computeBaseline()index.ts始终预测「训练集目标均值」在测试集上计算 MSE作为模型性能的下限参照const baseline testSquareError / testCount;如果训练后的模型 MSE 不显著低于基线说明模型没有学到有效信号。基线通过forEach()流式遍历测试集计算同样不把数据整体载入内存。训练曲线ui.ts每轮结束后用 Vega-Lite 绘制 Train Loss 与 Validation Loss 两条折线x 轴为 epochy 轴为 loss颜色按数据集划分页面通过 index.html 中的两个按钮触发对应模型训练。观察曲线是否收敛、训练/验证损失是否同步下降即可判断是否存在欠拟合或过拟合。小结一份可复用的浏览器端回归模板从本示例可以抽象出在浏览器中用 tfjs 做「表格数据回归」的通用四步法数据读取tfd.csv(url, {columnConfigs})下载 CSV 并用isLabel切分特征与标签对应 data.ts管道构建map → shuffle → batch组合出惰性数据集配合columnNames()推导特征数归一化仅用训练集统计量做标准分数变换再应用到验证/测试集对应 stats.ts 与 statistics.ts训练评估model.compile({optimizer, loss: meanSquaredError})model.fitDataset()/model.evaluateDataset()并用基线损失与训练曲线验证模型有效性。替换数据 URL、columnConfigs与网络结构即可迁移到其他回归任务整套流程无需任何后端服务。【免费下载链接】tfjsA WebGL accelerated JavaScript library for training and deploying ML models.项目地址: https://gitcode.com/gh_mirrors/tf/tfjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →