如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发

TensorFlow.js 是 TensorFlow 的 JavaScript 版本 , 支持 GPU 硬件加速 , 可以运行在 Node.js 或浏览器环境中 。它不但支持完全基于 JavaScript 从头开发、训练和部署模型 , 也可以用来运行已有的 Python 版 TensorFlow 模型 , 或者基于现有的模型进行继续训练 。

如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发

文章插图
TensorFlow.js 可以让我们直接在浏览器中加载 TensorFlow , 让用户立即通过本地的 CPU/GPU 资源进行我们所需要的机器学习运算 , 更灵活地进行 AI 应用的开发 。
浏览器中进行机器学习 , 相对比与服务器端来讲 , 将拥有以下四大优势:
不需要安装软件或驱动(打开浏览器即可使用);
可以通过浏览器进行更加方便的人机交互;
可以通过手机浏览器 , 调用手机硬件的各种传感器(如:GPS、电子罗盘、加速度传感器、摄像头等);
用户的数据可以无需上传到服务器 , 在本地即可完成所需操作 。
通过这些优势 , TensorFlow.js 将给开发者带来极高的灵活性 。比如在 Google Creative Lab 在 2018 年 7 月发布的 Move Mirror 里 , 我们可以在手机上打开浏览器 , 通过手机摄像头检测视频中用户的身体动作姿势 , 然后通过对图片数据库中类似身体动作姿势的检索 , 给用户显示一个最能够和他当前动作相似的照片 。在 Move Mirror 的运行过程中 , 数据没有上传到服务器 , 所有的运算都是在手机本地 , 基于手机的 CPU/GPU 完成的 , 而这项技术 , 将使 Servreless 与 AI 应用结合起来成为可能 。

如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发

文章插图
TensorFlow.js 模型训练 *
与 TensorFlow Serving 和 TensorFlow Lite 不同 , TensorFlow.js 不仅支持模型的部署和推断 , 还支持直接在 TensorFlow.js 中进行模型训练 。
在 TensorFlow 基础章节中 , 我们已经用 Python 实现过 , 针对某城市在 2013-2017 年的房价的任务 , 通过对该数据进行线性回归 , 即使用线性模型 y=ax+b 来拟合上述数据 , 此处 a 和 b 是待求的参数 。
下面我们改用 TensorFlow.js 来实现一个 JavaScript 版本 。
首先 , 我们定义数据 , 进行基本的归一化操作 。
const xsRaw = tf.tensor([2013, 2014, 2015, 2016, 2017]) const ysRaw = tf.tensor([12000, 14000, 15000, 16500, 17500]) // 归一化 const xs = xsRaw.sub(xsRaw.min()) .div(xsRaw.max().sub(xsRaw.min())) const ys = ysRaw.sub(ysRaw.min()) .div(ysRaw.max().sub(ysRaw.min()))
接下来 , 我们来求线性模型中两个参数 a和 b的值 。
使用 loss() 计算损失;使用 optimizer.minimize() 自动更新模型参数 。
JavaScript 中的胖箭头函数 (Fat Arrow Function)
从 JavaScript 的 ES6 版本开始 , 允许使用箭头函数(=>)来简化函数的声明和书写 , 类似于 Python 中的 lambda 表达式 。例如 , 以下箭头函数:
const sum = (a, b) => { return a + b }
在效果上等价为如下的传统函数:
const sum = function (a, b) { return a + b }
不过箭头函数中没有自己的 this 和 arguments , 不可以被当做构造函数 (new) , 也不可以被当做 Generator (无法使用 yield) 。感兴趣的读者可以参考 MDN 文档 以了解更多 。
MCN 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
TensorFlow.js 中的 dataSync() 系列数据同步函数
它的作用是把 Tensor 数据从 GPU 中取回来 , 可以理解为与 Python 中的 .numpy() 功能相当 , 即将数据取回 , 供本地显示 , 或本地计算使用 。感兴趣的读者可以参考 TensorFlow.js 文档 以了解更多 。
TensorFlow.js 文档:https://js.tensorflow.org/api/latest/#tf.Tensor.dataSync
TensorFlow.js 中的 sub() 系列数学计算函数
TensorFlow.js 支持 tf.sub(a, b) 和 a.sub(b) 两种方法的数学函数调用 。其效果是等价的 , 读者可以根据自己的喜好来选择 。感兴趣的读者可以参考 TensorFlow.js 文档 (https://js.tensorflow.org/api/latest/#sub) 以了解更多 。
const a = tf.scalar(Math.random()).variable() const b = tf.scalar(Math.random()).variable() // y = a * x + b. const f = (x) => a.mul(x).add(b) const loss = (pred, label) => pred.sub(label).square().mean() const learningRate = 1e-3 const optimizer = tf.train.sgd(learningRate) // 训练模型 for (let i = 0; i < 10000; i++) { optimizer.minimize(() => loss(f(xs), ys)) } // 预测 console.log(`a: ${a.dataSync()}, b: ${b.dataSync()}`) const preds = f(xs).dataSync() const trues = ys.arraySync() preds.forEach((pred, i) => { console.log(`x: ${i}, pred: ${pred.toFixed(2)}, true: ${trues[i].toFixed(2)}`) })
从下面的输出样例中我们可以看到 , 已经拟合得比较接近了 。
a: 0.9339302778244019, b: 0.08108722418546677 x: 0, pred: 0.08, true: 0.00 x: 1, pred: 0.31, true: 0.36 x: 2, pred: 0.55, true: 0.55 x: 3, pred: 0.78, true: 0.82 x: 4, pred: 1.02, true: 1.00
可以直接在浏览器中运行 , 完整的 HTML 代码如下:
TensorFlow.js 性能对比
关于 TensorFlow.js 的性能 , Google 官方做了一份基于 MobileNet 的评测 , 可以作为参考 。具体评测是基于 MobileNet 的 TensorFlow 模型 , 将其 JavaScript 版本和 Python 版本各运行两百次 , 其评测结论如下 。

如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发
文章插图
手机浏览器性能:(单位:毫秒 ms)
TensorFlow.js 在手机浏览器中运行一次推理:
在 iPhoneX 上需要时间为 22ms
在 Pixel3 上需要时间为 100ms
与 TensorFlow Lite 代码基准相比 , 手机浏览器中的 TensorFlow.js 在 IPhoneX 上的运行时间为基准的 1.2 倍 , 在 Pixel3 上运行的时间为基准的 1.8 倍 。

如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发
文章插图
台式机浏览器性能:(单位:毫秒 ms)
在浏览器中 , TensorFlow.js 可以使用 WebGL 进行硬件加速 , 将 GPU 资源使用起来 。
TensorFlow.js 在浏览器中运行一次推理:
在 CPU 上需要时间为 97ms
在 GPU (WebGL) 上需要时间为 10ms
与 Python 代码基准相比 , 浏览器中的 TensorFlow.js 在 CPU 上的运行时间为基准的 1.7 倍 , 在 GPU (WebGL) 上运行的时间为基准的 3.8 倍 。
Node.js 性能:
在 Node.js 中 , TensorFlow.js 可以用 JavaScript 加载转换后模型 , 或使用 TensorFlow 的 C++ Binding  , 分别接近和超越了 Python 的性能 。
TensorFlow.js 在 Node.js 运行一次推理:
在 CPU 上运行原生模型时间为 19.6ms
在 GPU (CUDA) 上运行原生模型时间为 7.68ms
与 Python 代码基准相比 , Node.js 的 TensorFlow.js 在 CPU 和 GPU 上的运行时间都比基准快 4%。
责任编辑:xj
原文标题:【抽奖送书】简单粗暴 TensorFlow.js:从安装到训练全程实例教学
【如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发】 文章出处:【微信公众号:TensorFlow】欢迎添加关注!文章转载请注明出处 。

    推荐阅读