TensorFlow.js 是 TensorFlow 的 JavaScript 版本,支持 GPU 硬件加速,可以運行在 Node.js 或瀏覽器環(huán)境中。它不但支持完全基于 JavaScript 從頭開發(fā)、訓(xùn)練和部署模型,也可以用來運行已有的 Python 版 TensorFlow 模型,或者基于現(xiàn)有的模型進行繼續(xù)訓(xùn)練。
TensorFlow.js 支持 GPU 硬件加速。在 Node.js 環(huán)境中,如果有 CUDA 環(huán)境支持,或者在瀏覽器環(huán)境中,有 WebGL 環(huán)境支持,那么 TensorFlow.js 可以使用硬件進行加速。
微信小程序
微信小程序也提供了官方插件,封裝了 TensorFlow.js 庫,利用小程序 WebGL API 給第三方小程序調(diào)用時提供 GPU 加速。
本章,我們將基于 TensorFlow.js 1.0,向大家簡單地介紹如何基于 ES6 的 JavaScript 進行 TensorFlow.js 的開發(fā),然后提供兩個例子,并基于例子進行詳細的講解和介紹,最終實現(xiàn)使用純 JavaScript 進行 TensorFlow 模型的開發(fā)、訓(xùn)練和部署。
章節(jié)代碼地址
本章中提到的 JavaScript 版 TensorFlow 的相關(guān)代碼,使用說明,和訓(xùn)練好的模型文件及參數(shù),都可以在作者的 GitHub 上找到。
地址:https://github.com/huan/tensorflow-handbook-javascript
瀏覽器中使用 TensorFlow.js 的優(yōu)勢
TensorFlow.js 可以讓我們直接在瀏覽器中加載 TensorFlow,讓用戶立即通過本地的 CPU/GPU 資源進行我們所需要的機器學(xué)習(xí)運算,更靈活地進行 AI 應(yīng)用的開發(fā)。
瀏覽器中進行機器學(xué)習(xí),相對比與服務(wù)器端來講,將擁有以下四大優(yōu)勢:
不需要安裝軟件或驅(qū)動(打開瀏覽器即可使用);
可以通過瀏覽器進行更加方便的人機交互;
可以通過手機瀏覽器,調(diào)用手機硬件的各種傳感器(如:GPS、電子羅盤、加速度傳感器、攝像頭等);
用戶的數(shù)據(jù)可以無需上傳到服務(wù)器,在本地即可完成所需操作。
通過這些優(yōu)勢,TensorFlow.js 將給開發(fā)者帶來極高的靈活性。比如在 Google Creative Lab 在 2018 年 7 月發(fā)布的 Move Mirror 里,我們可以在手機上打開瀏覽器,通過手機攝像頭檢測視頻中用戶的身體動作姿勢,然后通過對圖片數(shù)據(jù)庫中類似身體動作姿勢的檢索,給用戶顯示一個最能夠和他當(dāng)前動作相似的照片。在 Move Mirror 的運行過程中,數(shù)據(jù)沒有上傳到服務(wù)器,所有的運算都是在手機本地,基于手機的 CPU/GPU 完成的,而這項技術(shù),將使 Servreless 與 AI 應(yīng)用結(jié)合起來成為可能。
Move Mirror
https://experiments.withgoogle.com/move-mirror
Move Mirror 所使用的 PoseNet
https://github.com/tensorflow/tfjs-models/tree/master/posenet
TensorFlow.js 環(huán)境配置
在瀏覽器中使用 TensorFlow.js
在瀏覽器中加載 TensorFlow.js ,最方便的辦法是在 HTML 中直接引用 TensorFlow.js 發(fā)布的 NPM 包中已經(jīng)打包安裝好的 JavaScript 代碼。
在 Node.js 中使用 TensorFlow.js
服務(wù)器端使用 JavaScript ,首先需要按照NodeJS.org官網(wǎng)的說明,完成安裝最新版本的 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 的輸出信息,那么就說明環(huán)境配置沒有問題了。
然后,在 JavaScript 程序中,通過以下指令,即可引入 TensorFlow.js:
import * as tf from '@tensorflow/tfjs' console.log(tf.version.tfjs) //Output: 1.3.1
使用import加載 JavaScript 模塊
import 是 JavaScript ES6 版本新開始擁有的新特性。粗略可以認為等價于 require。比如:import * as tf from '@tensorflow/tfjs'和 const tf = require('@tensorflow/tfjs')對上面的示例代碼是等價的。希望了解更多的讀者,可以訪問MDN 文檔(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)。
在微信小程序中使用 TensorFlow.js
TensorFlow.js 微信小程序插件封裝了 TensorFlow.js 庫,用于提供給第三方小程序調(diào)用。
在使用插件前,首先要在小程序管理后臺的 “設(shè)置 - 第三方服務(wù) - 插件管理” 中添加插件。開發(fā)者可登錄小程序管理后臺,通過 appid _wx6afed118d9e81df9_ 查找插件并添加。本插件無需申請,添加后可直接使用。
例子:TFJS Mobilenet:物體識別小程序
https://github.com/tensorflow/tfjs-wechat/tree/master/demo/mobilenet
TensorFlow.js 微信小程序官方文檔地址
https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx6afed118d9e81df9
TensorFlow.js 微信小程序教程
為了推動微信小程序中人工智能應(yīng)用的發(fā)展,Google 專門為微信小程序打造了最新 TensorFlow.js 插件,并聯(lián)合 Google 認證機器學(xué)習(xí)專家、微信、騰訊課堂 NEXT 學(xué)院,聯(lián)合推出了 “NEXT 學(xué)院:TensorFlow.js 遇到小程序” 課程,幫助小程序開發(fā)者帶來更加易于上手和流暢的 TensorFlow.js 開發(fā)體驗。
上述課程主要介紹了如何將 TensorFlow.js 插件嵌入到微信小程序中,并基于其進行開發(fā)。課程中以一個姿態(tài)檢測的模型 PoseNet 作為案例,介紹了 TensorFlow.js 插件導(dǎo)入到微信小程序開發(fā)工具中后,在項目開發(fā)中的配置,功能調(diào)用,加載模型等方法應(yīng)用;此外,還介紹了在 Python 環(huán)境下訓(xùn)練好的模型如何轉(zhuǎn)換并載入到小程序中。
本章作者也參與了課程制作,課程中的案列簡單有趣易上手,通過學(xué)習(xí),可以快速熟悉 TensorFlow.js 在小程序中的開發(fā)和應(yīng)用。有興趣的讀者可以前往 NEXT 學(xué)院,進行后續(xù)深度學(xué)習(xí)。
課程地址
https://ke.qq.com/course/428263
TensorFlow.js 模型部署
在瀏覽器中加載 Python 模型
一般 TensorFlow 的模型,會被存儲為 SavedModel 格式。這也是 Google 目前推薦的模型保存最佳實踐。SavedModel 格式可以通過 tensorflowjs-converter 轉(zhuǎn)換器轉(zhuǎn)換為可以直接被 TensorFlow.js 加載的格式,從而在 JavaScript 語言中進行使用。
1. 安裝tensorflowjs_converter
$ pip install tensorflowjs
tensorflowjs_converter的使用細節(jié),可以通過--help參數(shù)查看程序幫助:
$ tensorflowjs_converter --help
2. 以下我們以 MobilenetV1 為例,看一下如何對模型文件進行轉(zhuǎn)換操作,并將可以被 TensorFlow.js 加載的模型文件,存放到/mobilenet/tfjs_model 目錄下。
轉(zhuǎn)換 SavedModel:將/mobilenet/saved_model 轉(zhuǎn)換到/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
轉(zhuǎn)換完成的模型,保存為了兩類文件:
model.json:模型架構(gòu)
group1-shard*of*:模型參數(shù)
舉例來說,我們對 MobileNet v2 轉(zhuǎn)換出來的文件,如下:
/mobilenet/tfjs_model/model.json /mobilenet/tfjs_model/group1-shard1of5 … /mobilenet/tfjs_model/group1-shard5of5
3. 為了加載轉(zhuǎn)換完成的模型文件,我們需要安裝tfjs-converter和@tensorflow/tfjs模塊:
$ npm install @tensorflow/tfjs
4. 然后,我們就可以通過 JavaScript 來加載 TensorFlow 模型了!
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))
轉(zhuǎn)換 TFHub 模型
將 TFHub 模型https://tfhub.dev/google/imagenet/mobilenet_v1_100_224/classification/1轉(zhuǎn)換到/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 中執(zhí)行原生 SavedModel 模型
除了通過轉(zhuǎn)換工具 tfjs-converter 將 TensorFlow SavedModel、TFHub 模型或 Keras 模型轉(zhuǎn)換為 JavaScript 瀏覽器兼容格式之外,如果我們在 Node.js 環(huán)境中運行,那么還可以使用 TensorFlow C++ 的接口,直接運行原生的 SavedModel 模型。
在 TensorFlow.js 中運行原生的 SavedModel 模型非常簡單。我們只需要把預(yù)訓(xùn)練的 TensorFlow 模型存為 SavedModel 格式,并通過@tensorflow/tfjs-node 或 tfjs-node-gpu 包將模型加載到 Node.js 進行推理即可,無需使用轉(zhuǎn)換工具 tfjs-converter。
預(yù)訓(xùn)練的 TensorFlow SavedModel 可以通過一行代碼在 JavaScript 中加載模型并用于推理:
const model = await tf.node.loadSavedModel(path) const output = model.predict(input)
也可以將多個輸入以數(shù)組或圖的形式提供給模型:
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 版本中訓(xùn)練和導(dǎo)出的 TensorFlow SavedModel。由此帶來的好處除了無需進行任何轉(zhuǎn)換,原生執(zhí)行 TensorFlow SavedModel 意味著您可以在模型中使用 TensorFlow.js 尚未支持的算子。這要通過將 SavedModel 作為 TensorFlow 會話加載到 C++ 中進行綁定予以實現(xiàn)。
使用 TensorFlow.js 模型庫
TensorFlow.js 提供了一系列預(yù)訓(xùn)練好的模型,方便大家快速地給自己的程序引入人工智能能力。
模型庫中模型分類包括圖像識別、語音識別、人體姿態(tài)識別、物體識別、文字分類等。
模型庫 GitHub 地址
https://github.com/tensorflow/tfjs-models
由于這些 API 默認模型文件都存儲在谷歌云上,直接使用會導(dǎo)致中國用戶無法直接讀取。在程序內(nèi)使用模型 API 時要提供 modelUrl 的參數(shù),可以指向谷歌中國的鏡像服務(wù)器。
谷歌云的 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 頁面,來調(diào)用 TensorFlow.js 和與訓(xùn)練好的 MobileNet ,在用戶的瀏覽器中,通過攝像頭來識別圖像中的物體是什么。
1. 我們建立一個 HTML 文件,在頭信息中,通過將 NPM 模塊轉(zhuǎn)換為在線可以引用的免費服務(wù) unpkg.com,來加載@tensorflow/tfjs 和@tensorflow-models/mobilenet 兩個 TFJS 模塊:
2. 我們聲明三個 HTML 元素:用來顯示視頻的
3. 我們通過 JavaScript ,將對應(yīng)的 HTML 元素進行初始化:video, image, status 三個變量分別用來對應(yīng) 三個 HTML 元素,canvas 和 ctx 用來做從攝像頭獲取視頻流數(shù)據(jù)的中轉(zhuǎn)存儲。model 將用來存儲我們從網(wǎng)絡(luò)上加載的 MobileNet:
const video = document.querySelector('video') const image = document.querySelector('img') const status = document.querySelector("p") const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') let model
4. main()用來初始化整個系統(tǒng),完成加載 MobileNet 模型,將用戶攝像頭的數(shù)據(jù)綁定
async function main () { status.innerText = "Model loading..." model = await mobilenet.load() status.innerText = "Model is loaded!" const stream = await navigator.mediaDevices.getUserMedia({ video: true }) video.srcObject = stream await video.play() canvas.width = video.videoWidth canvas.height = video.videoHeight refresh() }
5. refresh()函數(shù),用來從視頻中取出當(dāng)前一幀圖像,然后通過 MobileNet 模型進行分類,并將分類結(jié)果,顯示在網(wǎng)頁上。然后,通過 setTimeout,重復(fù)執(zhí)行自己,實現(xiàn)持續(xù)對視頻圖像進行處理的功能:
async function refresh(){ ctx.drawImage(video, 0,0) image.src = canvas.toDataURL('image/png') await model.load() const predictions = await model.classify(image) const className = predictions[0].className const percentage = Math.floor(100 * predictions[0].probability) status.innerHTML = percentage + '%' + ' ' + className setTimeout(refresh, 100) }
整體功能,只需要一個文件,幾十行 HTML/JavaScript 即可實現(xiàn)。可以直接在瀏覽器中運行,完整的 HTML 代碼如下:
運行效果截圖如下。可以看到,水杯被系統(tǒng)識別為了 “beer glass” 啤酒杯,置信度 90% :
TensorFlow.js 模型訓(xùn)練 *
與 TensorFlow Serving 和 TensorFlow Lite 不同,TensorFlow.js 不僅支持模型的部署和推斷,還支持直接在 TensorFlow.js 中進行模型訓(xùn)練。
在 TensorFlow 基礎(chǔ)章節(jié)中,我們已經(jīng)用 Python 實現(xiàn)過,針對某城市在 2013-2017 年的房價的任務(wù),通過對該數(shù)據(jù)進行線性回歸,即使用線性模型 y=ax+b 來擬合上述數(shù)據(jù),此處 a 和 b 是待求的參數(shù)。
下面我們改用 TensorFlow.js 來實現(xiàn)一個 JavaScript 版本。
首先,我們定義數(shù)據(jù),進行基本的歸一化操作。
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()))
接下來,我們來求線性模型中兩個參數(shù) a和 b的值。
使用 loss()計算損失;使用 optimizer.minimize()自動更新模型參數(shù)。
JavaScript 中的胖箭頭函數(shù) (Fat Arrow Function)
從 JavaScript 的 ES6 版本開始,允許使用箭頭函數(shù)(=>)來簡化函數(shù)的聲明和書寫,類似于 Python 中的 lambda 表達式。例如,以下箭頭函數(shù):
const sum = (a, b) => { return a + b }
在效果上等價為如下的傳統(tǒng)函數(shù):
const sum = function (a, b) { return a + b }
不過箭頭函數(shù)中沒有自己的 this 和 arguments,不可以被當(dāng)做構(gòu)造函數(shù) (new),也不可以被當(dāng)做 Generator (無法使用 yield)。感興趣的讀者可以參考MDN 文檔 以了解更多。
MCN 文檔:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
TensorFlow.js 中的dataSync()系列數(shù)據(jù)同步函數(shù)
它的作用是把 Tensor 數(shù)據(jù)從 GPU 中取回來,可以理解為與 Python 中的.numpy()功能相當(dāng),即將數(shù)據(jù)取回,供本地顯示,或本地計算使用。感興趣的讀者可以參考TensorFlow.js 文檔 以了解更多。
TensorFlow.js 文檔:https://js.tensorflow.org/api/latest/#tf.Tensor.dataSync
TensorFlow.js 中的sub()系列數(shù)學(xué)計算函數(shù)
TensorFlow.js 支持tf.sub(a, b)和a.sub(b)兩種方法的數(shù)學(xué)函數(shù)調(diào)用。其效果是等價的,讀者可以根據(jù)自己的喜好來選擇。感興趣的讀者可以參考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) // 訓(xùn)練模型 for (let i = 0; i < 10000; i++) { optimizer.minimize(() => loss(f(xs), ys)) } // 預(yù)測 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)}`) })
從下面的輸出樣例中我們可以看到,已經(jīng)擬合得比較接近了。
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 性能對比
關(guān)于 TensorFlow.js 的性能,Google 官方做了一份基于 MobileNet 的評測,可以作為參考。具體評測是基于 MobileNet 的 TensorFlow 模型,將其 JavaScript 版本和 Python 版本各運行兩百次,其評測結(jié)論如下。
手機瀏覽器性能:(單位:毫秒 ms)
TensorFlow.js 在手機瀏覽器中運行一次推理:
在 iPhoneX 上需要時間為 22ms
在 Pixel3 上需要時間為 100ms
與 TensorFlow Lite 代碼基準(zhǔn)相比,手機瀏覽器中的 TensorFlow.js 在 IPhoneX 上的運行時間為基準(zhǔn)的 1.2 倍,在 Pixel3 上運行的時間為基準(zhǔn)的 1.8 倍。
臺式機瀏覽器性能:(單位:毫秒 ms)
在瀏覽器中,TensorFlow.js 可以使用 WebGL 進行硬件加速,將 GPU 資源使用起來。
TensorFlow.js 在瀏覽器中運行一次推理:
在 CPU 上需要時間為 97ms
在 GPU (WebGL) 上需要時間為 10ms
與 Python 代碼基準(zhǔn)相比,瀏覽器中的 TensorFlow.js 在 CPU 上的運行時間為基準(zhǔn)的 1.7 倍,在 GPU (WebGL) 上運行的時間為基準(zhǔn)的 3.8 倍。
Node.js 性能:
在 Node.js 中,TensorFlow.js 可以用 JavaScript 加載轉(zhuǎn)換后模型,或使用 TensorFlow 的 C++ Binding ,分別接近和超越了 Python 的性能。
TensorFlow.js 在 Node.js 運行一次推理:
在 CPU 上運行原生模型時間為 19.6ms
在 GPU (CUDA) 上運行原生模型時間為 7.68ms
與 Python 代碼基準(zhǔn)相比,Node.js 的 TensorFlow.js 在 CPU 和 GPU 上的運行時間都比基準(zhǔn)快 4% 。
責(zé)任編輯:xj
原文標(biāo)題:【抽獎送書】簡單粗暴 TensorFlow.js:從安裝到訓(xùn)練全程實例教學(xué)
文章出處:【微信公眾號:TensorFlow】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
gpu
+關(guān)注
關(guān)注
28文章
4702瀏覽量
128709 -
API
+關(guān)注
關(guān)注
2文章
1486瀏覽量
61820 -
python
+關(guān)注
關(guān)注
56文章
4782瀏覽量
84456 -
tensorflow
+關(guān)注
關(guān)注
13文章
329瀏覽量
60499
原文標(biāo)題:【抽獎送書】簡單粗暴 TensorFlow.js:從安裝到訓(xùn)練全程實例教學(xué)
文章出處:【微信號:tensorflowers,微信公眾號:Tensorflowers】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論