TensorFlow in JavaScript(Huan) ========================================================== **Atwood’s Law** “Any application that can be written in JavaScript, will eventually be written in JavaScript.” -- Jeff Atwood, Founder of StackOverflow.com “JavaScript now works.” -- Paul Graham, YC Founder TensorFlow.js 简介 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. figure:: /_static/image/javascript/tensorflow-js.png :width: 60% :align: center TensorFlow.js 是 TensorFlow 的 JavaScript 版本,支持GPU硬件加速,可以运行在 Node.js 或浏览器环境中。它不但支持完全基于 JavaScript 从头开发、训练和部署模型,也可以用来运行已有的 Python 版 TensorFlow 模型,或者基于现有的模型进行继续训练。 .. figure:: /_static/image/javascript/architecture.png :width: 60% :align: center TensorFlow.js 支持 GPU 硬件加速。在 Node.js 环境中,如果有 CUDA 环境支持,或者在浏览器环境中,有 WebGL 环境支持,那么 TensorFlow.js 可以使用硬件进行加速。 .. admonition:: 微信小程序 微信小程序也提供了官方插件,封装了TensorFlow.js库,利用小程序WebGL API给第三方小程序调用时提供GPU加速。 本章,我们将基于 TensorFlow.js 1.0,向大家简单地介绍如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发,然后提供两个例子,并基于例子进行详细的讲解和介绍,最终实现使用纯 JavaScript 进行 TensorFlow 模型的开发、训练和部署。 .. admonition:: 章节代码地址 本章中提到的 JavaScript 版 TensorFlow 的相关代码,使用说明,和训练好的模型文件及参数,都可以在作者的 GitHub 上找到。地址: https://github.com/huan/tensorflow-handbook-javascript 浏览器中使用 TensorFlow.js 的优势 -------------------------------------------- .. figure:: /_static/image/javascript/chrome-ml.png :width: 60% :align: center TensorFlow.js 可以让我们直接在浏览器中加载 TensorFlow,让用户立即通过本地的CPU/GPU资源进行我们所需要的机器学习运算,更灵活地进行AI应用的开发。 浏览器中进行机器学习,相对比与服务器端来讲,将拥有以下四大优势: * 不需要安装软件或驱动(打开浏览器即可使用); * 可以通过浏览器进行更加方便的人机交互; * 可以通过手机浏览器,调用手机硬件的各种传感器(如:GPS、电子罗盘、加速度传感器、摄像头等); * 用户的数据可以无需上传到服务器,在本地即可完成所需操作。 通过这些优势,TensorFlow.js 将给开发者带来极高的灵活性。比如在 Google Creative Lab 在2018年7月发布的 Move Mirror 里,我们可以在手机上打开浏览器,通过手机摄像头检测视频中用户的身体动作姿势,然后通过对图片数据库中类似身体动作姿势的检索,给用户显示一个最能够和他当前动作相似的照片。在Move Mirror的运行过程中,数据没有上传到服务器,所有的运算都是在手机本地,基于手机的CPU/GPU完成的,而这项技术,将使Servreless与AI应用结合起来成为可能。 .. figure:: /_static/image/javascript/move-mirror.jpg :width: 60% :align: center - Move Mirror 地址:https://experiments.withgoogle.com/move-mirror - Move Mirror 所使用的 PoseNet 地址:https://github.com/tensorflow/tfjs-models/tree/master/posenet TensorFlow.js 环境配置 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 在浏览器中使用 TensorFlow.js -------------------------------------------- 在浏览器中加载 TensorFlow.js ,最方便的办法是在 HTML 中直接引用 TensorFlow.js 发布的 NPM 包中已经打包安装好的 JavaScript 代码。 .. literalinclude:: /_static/code/zh/deployment/javascript/regression.html :lines: 1-3 在 Node.js 中使用 TensorFlow.js -------------------------------------------- 服务器端使用 JavaScript ,首先需要按照 `NodeJS.org `_ 官网的说明,完成安装最新版本的 Node.js 。 然后,完成以下四个步骤即可完成配置: 1. 确认 Node.js 版本(v10 或更新的版本):: $ node --verion v10.5.0 $ npm --version 6.4.1 2. 建立 TensorFlow.js 项目目录:: $ mkdir tfjs $ cd tfjs 3. 安装 TensorFlow.js:: # 初始化项目管理文件 package.json $ npm init -y # 安装 tfjs 库,纯 JavaScript 版本 $ npm install @tensorflow/tfjs # 安装 tfjs-node 库,C Binding 版本 $ npm install @tensorflow/tfjs-node # 安装 tfjs-node-gpu 库,支持 CUDA GPU 加速 $ npm install @tensorflow/tfjs-node-gpu 4. 确认 Node.js 和 TensorFlow.js 工作正常:: $ node > require('@tensorflow/tfjs').version { 'tfjs-core': '1.3.1', 'tfjs-data': '1.3.1', 'tfjs-layers': '1.3.1', 'tfjs-converter': '1.3.1', tfjs: '1.3.1' } > 如果你看到了上面的 ``tfjs-core``, ``tfjs-data``, ``tfjs-layers`` 和 ``tfjs-converter`` 的输出信息,那么就说明环境配置没有问题了。 然後,在 JavaScript 程序中,通过以下指令,即可引入 TensorFlow.js: .. code-block:: javascript import * as tf from '@tensorflow/tfjs' console.log(tf.version.tfjs) // Output: 1.3.1 .. admonition:: 使用 `import` 加载 JavaScript 模块 ``import`` 是 JavaScript ES6 版本新开始拥有的新特性。粗略可以认为等价于 ``require``。比如:``import * as tf from '@tensorflow/tfjs'`` 和 ``const tf = require('@tensorflow/tfjs')`` 对上面的示例代码是等价的。希望了解更多的读者,可以访问 `MDN 文档 `_ 。 在微信小程序中使用 TensorFlow.js -------------------------------------------- TensorFlow.js 微信小程序插件封装了 TensorFlow.js 库,用于提供给第三方小程序调用。 在使用插件前,首先要在小程序管理后台的“设置-第三方服务-插件管理”中添加插件。开发者可登录小程序管理后台,通过 appid _wx6afed118d9e81df9_ 查找插件并添加。本插件无需申请,添加后可直接使用。 例子可以看 TFJS Mobilenet: `物体识别小程序 `_ `TensorFlow.js 微信小程序官方文档地址 `_ .. admonition:: TensorFlow.js 微信小程序教程 为了推动微信小程序中人工智能应用的发展,Google 专门为微信小程序打造了最新 TensorFlow.js 插件,并联合 Google 认证机器学习专家、微信、腾讯课堂 NEXT 学院,联合推出了“NEXT学院:TensorFlow.js遇到小程序”课程,帮助小程序开发者带来更加易于上手和流畅的 TensorFlow.js 开发体验。 上述课程主要介绍了如何将 TensorFlow.js 插件嵌入到微信小程序中,并基于其进行开发。课程中以一个姿态检测的模型 PoseNet 作为案例,介绍了 TensorFlow.js 插件导入到微信小程序开发工具中后,在项目开发中的配置,功能调用,加载模型等方法应用;此外,还介绍了在 Python 环境下训练好的模型如何转换并载入到小程序中。 本章作者也参与了课程制作,课程中的案列简单有趣易上手,通过学习,可以快速熟悉 TensorFlow.js 在小程序中的开发和应用.有兴趣的读者可以前往 NEXT 学院,进行后续深度学习。 课程地址:https://ke.qq.com/course/428263 TensorFlow.js 模型部署 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 在浏览器中加载 Python 模型 -------------------------------------------- 一般 TensorFlow 的模型,会被存储为 SavedModel 格式。这也是 Google 目前推荐的模型保存最佳实践。SavedModel 格式可以通过 tensorflowjs-converter 转换器转换为可以直接被 TensorFlow.js 加载的格式,从而在JavaScript语言中进行使用。 1. 安装 ``tensorflowjs_converter`` :: $ pip install tensorflowjs ``tensorflowjs_converter`` 的使用细节,可以通过 ``--help`` 参数查看程序帮助:: $ tensorflowjs_converter --help 2. 以下我们以 MobilenetV1 为例,看一下如何对模型文件进行转换操作,并将可以被 TensorFlow.js 加载的模型文件,存放到 ``/mobilenet/tfjs_model`` 目录下。 转换 SavedModel:将 ``/mobilenet/saved_model`` 转换到 ``/mobilenet/tfjs_model`` :: tensorflowjs_converter \ --input_format=tf_saved_model \ --output_node_names='MobilenetV1/Predictions/Reshape_1' \ --saved_model_tags=serve \ /mobilenet/saved_model \ /mobilenet/tfjs_model 转换完成的模型,保存为了两类文件: - ``model.json``:模型架构 - ``group1-shard*of*``:模型参数 举例来说,我们对 MobileNet v2 转换出来的文件,如下: /mobilenet/tfjs_model/model.json /mobilenet/tfjs_model/group1-shard1of5 ... /mobilenet/tfjs_model/group1-shard5of5 3. 为了加载转换完成的模型文件,我们需要安装 ``tfjs-converter`` 和 ``@tensorflow/tfjs`` 模块:: $ npm install @tensorflow/tfjs 4. 然后,我们就可以通过 JavaScript 来加载 TensorFlow 模型了! .. code-block:: javascript import * as tf from '@tensorflow/tfjs' const MODEL_URL = '/mobilenet/tfjs_model/model.json' const model = await tf.loadGraphModel(MODEL_URL) const cat = document.getElementById('cat') model.execute(tf.browser.fromPixels(cat)) .. admonition:: 转换 TFHub 模型 将 TFHub 模型 ``https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/1`` 转换到 ``/mobilenet/tfjs_model``:: tensorflowjs_converter \\ --input_format=tf_hub \\ 'https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/1' \\ /mobilenet/tfjs_model 在 Node.js 中执行原生 SavedModel 模型 -------------------------------------------- 除了通过转换工具 tfjs-converter 将 TensorFlow SavedModel、TFHub 模型或 Keras 模型转换为 JavaScript 浏览器兼容格式之外,如果我们在 Node.js 环境中运行,那么还可以使用 TensorFlow C++ 的接口,直接运行原生的 SavedModel 模型。 在 TensorFlow.js 中运行原生的 SavedModel 模型非常简单。我们只需要把预训练的 TensorFlow 模型存为 SavedModel 格式,并通过 ``@tensorflow/tfjs-node`` 或 ``tfjs-node-gpu`` 包将模型加载到 Node.js 进行推理即可,无需使用转换工具 ``tfjs-converter``。 预训练的 TensorFlow SavedModel 可以通过一行代码在 JavaScript 中加载模型并用于推理: .. code-block:: javascript const model = await tf.node.loadSavedModel(path) const output = model.predict(input) 也可以将多个输入以数组或图的形式提供给模型: .. code-block:: javascript const model1 = await tf.node.loadSavedModel(path1, [tag], signatureKey) const outputArray = model1.predict([inputTensor1, inputTensor2]) const model2 = await tf.node.loadSavedModel(path2, [tag], signatureKey) const outputMap = model2.predict({input1: inputTensor1, input2:inputTensor2}) 此功能需要 ``@tensorflow/tfjs-node`` 版本为 1.3.2 或更高,同时支持 CPU 和 GPU。它支持在 TensorFlow Python 1.x 和 2.0 版本中训练和导出的 TensorFlow SavedModel。由此带来的好处除了无需进行任何转换,原生执行 TensorFlow SavedModel 意味着您可以在模型中使用 TensorFlow.js 尚未支持的算子。这要通过将 SavedModel 作为 TensorFlow 会话加载到 C++ 中进行绑定予以实现。 使用 TensorFlow.js 模型库 -------------------------------------------- TensorFlow.js 提供了一系列预训练好的模型,方便大家快速地给自己的程序引入人工智能能力。 模型库 GitHub 地址:https://github.com/tensorflow/tfjs-models,其中模型分类包括图像识别、语音识别、人体姿态识别、物体识别、文字分类等。 由于这些API默认模型文件都存储在谷歌云上,直接使用会导致中国用户无法直接读取。在程序内使用模型API时要提供 modelUrl 的参数,可以指向谷歌中国的镜像服务器。 谷歌云的base url是 https://storage.googleapis.com, 中国镜像的base url是 https://www.gstaticcnapps.cn 模型的url path是一致的。以 posenet模型为例: - 谷歌云地址是:**https://storage.googleapis.com**/tfjs-models/savedmodel/posenet/mobilenet/float/050/model-stride16.json - 中国镜像地址是:**https://www.gstaticcnapps.cn**/tfjs-models/savedmodel/posenet/mobilenet/float/050/model-stride16.json 在浏览器中使用 MobileNet 进行摄像头物体识别 -------------------------------------------- 这里我们将通过一个简单的 HTML 页面,来调用 TensorFlow.js 和与训练好的 MobileNet ,在用户的浏览器中,通过摄像头来识别图像中的物体是什么。 1. 我们建立一个 HTML 文件,在头信息中,通过将 NPM 模块转换为在线可以引用的免费服务 ``unpkg.com``,来加载 ``@tensorflow/tfjs`` 和 ``@tensorflow-models/mobilenet`` 两个 TFJS 模块: .. literalinclude:: /_static/code/zh/deployment/javascript/mobilenet.html :lines: 3-6 2. 我们声明三个 HTML 元素:用来显示视频的 ``