使用 Coral Edge TPU 通过 TensorFlow.js 在 Node 中运行 TFlite 模型

1. 简介

54e81d02971f53e8.png

上次更新日期:2022 年 4 月 11 日

在此 Codelab 中,您将学习如何使用 会学习的机器 训练图片分类模型,以及如何使用 TensorFlow.js(一款适用于 JavaScript 的功能强大且灵活的机器学习库)通过 Coral 硬件加速来运行该模型。您构建了一个 Electron 应用,该应用可显示来自网络摄像头的图片,并使用 Coral Edge TPU 对这些图片进行分类。完全可运行的版本可在 sig-tfjs GitHub 代码库中找到。

我需要 Coral 设备吗?

可以。您可以在没有 Coral 设备的情况下尝试此 Codelab,并使用 WebNN 加速器在桌面设备上获得良好的性能。

构建内容

在此 Codelab 中,您将构建一个用于对图片进行分类的 Electron 应用。您的应用:

  • 将摄像头拍摄的图片分类到您训练的模型中定义的类别。
  • 使用 Coral 加速器来提高性能(如果有)。
  • 如果平台支持 WebNN,则使用 WebNN 来提高性能。

学习内容

  • 如何安装和设置 tfjs-tflite-node NPM 软件包,以便在 Node.js 中运行 TFLite 模型。
  • 如何安装 Edge TPU 运行时库,以便在 Coral 设备上运行模型。
  • 如何使用 Coral Edge TPU 加速模型推理。
  • 如何使用 WebNN 加速模型推理。

本 Codelab 重点介绍 Node.js 中的 TFLite。对于不相关的概念和代码块,我们仅会略作介绍,但是会提供相应代码块供您复制和粘贴。

所需条件

如要完成此 Codelab,您需要:

  • 一台配有摄像头的计算机。
  • 对于 Coral,我们建议使用运行 Raspberry Pi OS(64 位)桌面版的 Raspberry Pi。
  • 对于 WebNN,我们建议使用运行 Ubuntu 20.04 或 Windows 10 的 Intel x86-64 机器。
  • Node.js 版本 >= 12。
  • 了解 JavaScript。
  • (推荐)使用 Coral USB 加速器来加快模型运行速度。

2. 进行设置

获取代码

我们已将您完成此项目所需的所有代码都放入一个 Git 仓库中。首先,请获取相关代码,然后在您常用的开发环境中将其打开。在此 Codelab 中,我们建议使用运行 Raspberry Pi OS(64 位)桌面版的 Raspberry Pi。这样一来,您就可以轻松连接 Coral 加速器。

强烈建议:使用 Git 在 Raspberry Pi 上克隆代码库

如需获取代码,请打开新的终端窗口并克隆该代码库:

git clone https://github.com/tensorflow/sig-tfjs.git

Codelab 中需要修改的所有文件都位于 tfjs-tflite-node-codelab 目录(位于 sig-tfjs 内)。在此目录中,您会找到名为 starter_codecpu_inference_workingcoral_inference_workingwebnn_inference_working 的子目录。这些是本 Codelab 各个步骤的检查点。

存储库中的其他文件包括 tfjs-tflite-node-codelab 所依赖的 NPM 软件包。您无需修改任何这些文件,但需要运行其中一些测试,以确保您的环境设置正确无误。

安装 Edge TPU 运行时库

Coral 设备要求您在使用之前安装 Edge TPU 运行时库。按照适用于您平台的说明安装该插件。

在 Linux / Raspberry Pi 上

在 Linux 上,该库可从 Google 的 PPA 获取,以 Debian 软件包 libedgetpu1-std 的形式提供,适用于 x86-64 和 Armv8(64 位)架构。如果您的处理器使用其他架构,则需要从源代码进行编译

运行以下命令以添加 Google 的 Coral PPA 并安装 Edge TPU 运行时库。

# None of this is needed on Coral boards
# This repo is needed for almost all packages below
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list
# This repo is needed for only python3-coral-cloudiot and python3-coral-enviro
echo "deb https://packages.cloud.google.com/apt coral-cloud-stable main" | sudo tee /etc/apt/sources.list.d/coral-cloud.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo apt-get update
sudo apt-get install libedgetpu1-std

在 Windows / 其他操作系统上

预编译的二进制文件适用于 x86-64 版本的 MacOS 和 Windows,下载后,只需运行归档文件中的 install.shinstall.bat 脚本即可安装。

重启设备

安装 Edge TPU 运行时后,重启设备以激活安装程序添加的新 Coral Udev 规则。

验证是否检测到 Coral 设备

如需验证 Coral 设备是否已被检测到并正常运行,请针对 coral-tflite-delegate 软件包运行集成测试。此软件包位于代码库的根目录中。如需运行集成测试,请插入 Coral 加速器,然后在软件包的目录中运行以下命令:

npx yarn
npx yarn build-deps
npx yarn test-integration

您应该会看到如下所示的输出:

yarn run v1.22.17
$ yarn build && yarn test-integration-dev
$ tsc
$ jasmine --config=jasmine-integration.json
Platform node has already been set. Overwriting the platform with node.
Randomized with seed 78904
Started

============================
Hi there 👋. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.
============================
WARNING: converting 'int32' to 'uint8'
.


1 spec, 0 failures
Finished in 2.777 seconds
Randomized with seed 78904 (jasmine --random=true --seed=78904)
Done in 6.36s.

请勿担心日志中提到的安装 @tensorflow/tfjs-node,,因为您将在 TFLite 中运行模型。

如果输出包含 Encountered unresolved custom op: edgetpu-custom-op,则表示未检测到 Coral 设备。确保您已安装 Edge TPU 运行时库,并将 Coral 设备插入计算机。您还可以按照 Coral 的使用入门指南测试 Python 版 Coral 绑定。如果 Python 版本有效,但这些测试仍然失败,请提交 bug 报告告知我们。

运行起始代码

现在,您可以运行起始代码了。请按以下步骤开始操作。

  1. 移至 tfjs-tflite-node-codelab 目录下的 starter_code 目录。
  2. 运行 npm install 以安装依赖项。
  3. 运行 npm start 以启动项目。系统应会打开一个应用,其中显示来自电脑网络摄像头的视频画面。

我们从何处入手?

此项目的初始状态是已经构建好了一款专门为此 Codelab 设计的基本 Electron 相机应用。代码已简化为显示此 Codelab 中的概念,而且几乎没有错误处理功能。如果您选择在正式版应用中重复使用该代码的任意部分,请确保处理所有错误并全面测试所有代码。

一个基本的 Electron 应用,可显示设备的实时 Feed。

查看起始代码

此起始代码中有很多文件,但您只需修改 renderer.js。它控制着网页上显示的内容,包括视频 Feed 和 HTML 元素,您可以在其中将机器学习模型添加到应用中。在其他文件中,有一个 index.html 文件,但它所做的只是加载 renderer.js 文件。还有一个 main.js 文件,它是 Electron 的入口点。它控制着应用的生命周期,包括打开时显示的内容和关闭时执行的操作,但您无需对其进行任何更改。

打开调试器

在完成此 Codelab 的过程中,您可能需要调试应用。由于此应用基于 Electron,因此内置了 Chrome 调试器。在大多数平台上,您可以使用 Ctrl + Shift + i 打开它。点击控制台标签页,查看应用中的日志和错误消息。

这里没有太多其他内容可供探索,所以我们直接开始训练图片分类器吧!

3. 训练图像分类器

在本部分中,您将训练自定义图片分类模型的 TFLite 和 Coral 版本。

训练分类器

图片分类器会接收输入图片并为其分配标签。在此 Codelab 中,您将使用会学习的机器在浏览器中训练模型。为了加快本部分的训练速度,您可以使用桌面设备或笔记本电脑,而不是 Raspberry Pi,但您必须将生成的文件复制到 Pi。

现在,您可以训练模型了。如果您不确定要训练哪种模型,可以先训练一个人检测器,该模型只需检测画面中是否有人即可。

  1. 在新标签页中打开 会学习的机器训练页面
  2. 选择图片项目,然后选择标准图片模型
  3. 为每个类别添加图片样本。最简单的方法是使用摄像头输入。您还可以重命名课程。
  4. 当您为每个类别收集了足够的数据(通常 50 个样本就足够了)后,请按 Train Model(训练模型)。

模型完成训练后,您应该会看到模型输出的预览。

模型使用两个类别的图片进行训练,

尝试向模型提供不同的输入内容。如果您发现某个输入被错误分类,请将其添加到训练数据中,然后重新训练模型。

  1. 如果您对模型的准确率感到满意,请点击导出模型。您需要下载两个单独版本的模型。
  2. 将模型导出为 TensorFlow Lite 浮点模型。此操作会下载名为 converted_tflite.zip 的文件。在 CPU 上运行。
  3. 将模型导出为 TensorFlow Lite EdgeTPU 模型。此操作会下载名为 converted_edgetpu.zip 的文件,该文件可在 Coral Edge TPU 上运行。

4. 在应用中运行 CPU 模型

现在,您已经训练了一个模型,接下来需要将其添加到应用中。在本部分结束时,应用将能够使用设备的 CPU 运行您的模型。

将模型文件添加到应用

解压缩您在训练分类器时下载的 converted_tflite.zip 模型文件。归档中有两个文件。model_uquant.tflite 是保存的 TFLite 模型,包括模型图和权重。labels.txt 包含模型预测的类的简单易懂的标签。将这两个文件都放在 model 目录中。

安装依赖项

加载模型和预处理输入需要 TensorFlow.js 中的一些依赖项:

  • tfjs-tflite-node:TensorFlow.js 的软件包,用于在 Node.js 中运行 TFLite 模型。
  • @tensorflow/tfjs:TensorFlow.js 的主要软件包。

@tensorflow/tfjs 已安装,但您需要使用以下命令安装 tfjs-tflite-node

npm install --save tfjs-tflite-node

安装完成后,将其添加到 renderer.js 顶部的应用中:

Codelab 第 1 部分:导入 tfjs-tflite-node。

const {loadTFLiteModel} = require('tfjs-tflite-node');

加载模型

现在,您可以加载模型了。tfjs-tflite-node 提供了 loadTFLiteModel 函数来实现此目的。它可以从文件路径、ArrayBuffer 或 TFHub 网址加载模型。如需加载模型及其权重,请将以下内容添加到 main 函数中:

Codelab 第 1 部分:在此处加载模型。

const modelPath = './model/model_unquant.tflite';
const model = await loadTFLiteModel(modelPath);
const labels = fs.readFileSync('./model/labels.txt', 'utf8')
      .split('\n');

运行模型

运行模型需要三个步骤。首先,从网络摄像头中提取并预处理输入帧。然后,您在该帧上运行模型并获得预测结果。之后,您可以在网页上显示预测结果。

预处理摄像头输入

目前,网络摄像头只是一个 HTML 元素,其显示的帧无法供 JavaScript 渲染器 js 文件使用。为了从网络摄像头中提取帧,TensorFlow.js 提供了 tf.data.webcam,该模块提供了一个易于使用的 capture() 方法来从摄像头捕获帧。

如需使用此功能,请将以下设置代码添加到 main()

Codelab 第 1 部分:在此处设置 tf.data.webcam。

const tensorCam = await tf.data.webcam(webcam);

然后,如需每帧都捕获一张图片,请将以下内容添加到 run()

Codelab 第 1 部分:在此处捕获摄像头帧。

const image = await tensorCam.capture();

您还需要对每个帧进行预处理,以使其与模型兼容。此 Codelab 使用的模型的输入形状为 [1, 224, 224, 3],因此它需要一张 224x224 像素的 RGB 图片。tensorCam.capture() 的形状为 [224, 224, 3],因此您需要使用 tf.expandDims 在张量前面添加一个额外的维度。此外,CPU 模型需要介于 -1 和 1 之间的 Float32 输入,但摄像头捕获的值介于 0 到 255 之间。您可以将输入张量除以 127,将其范围从 [0, 255] 更改为 [0, ~2],然后减去 1,以获得所需的范围 [-1, ~1]。如需执行此操作,请将以下代码行添加到 run() 函数中的 tf.tidy()

Codelab 第 1 部分:在此处预处理摄像头帧。

const expanded = tf.expandDims(image, 0);
const divided = tf.div(expanded, tf.scalar(127));
const normalized = tf.sub(divided, tf.scalar(1));

使用完张量后,请务必将其处置。tf.tidy() 会自动为回调中包含的代码执行此操作,但不支持异步函数。您需要调用之前创建的图片张量的 dispose() 方法,手动处置该张量。

Codelab 第 1 部分:在此处处置摄像头帧。

image.dispose();

运行模型并显示结果

如需对预处理后的输入运行模型,请对归一化张量调用 model.predict()。此函数会返回一个一维张量,其中包含每个标签的预测概率。将此概率乘以 100,即可获得每个标签的百分比几率,然后使用起始代码中包含的 showPrediction 函数在屏幕上显示模型的预测结果。

此代码还使用 stats.js 通过在 model.predict 周围放置对 stats.beginstats.end 的调用来计时预测所花费的时间。

Codelab 第 1 部分:在此处运行模型并显示结果。

stats.begin();
const prediction = model.predict(normalized);
stats.end();
const percentage = tf.mul(prediction, tf.scalar(100));
showPrediction(percentage.dataSync(), labels);

使用 yarn start 再次运行应用,您应该会看到模型给出的分类。

TFLite CPU 模型在 Electron 应用中运行。它对来自网络摄像头的图像进行分类,并在下方显示每个类别的置信度值。

性能

按照目前的设置,模型在 CPU 上运行。对于台式电脑和大多数笔记本电脑来说,这没什么问题,但如果您在 Raspberry Pi 或其他低功耗设备上高效运转该命令,可能就不太理想了。在 Raspberry Pi 4 上,您可能会看到大约 10 FPS,这对于某些应用来说可能不够快。如需在不使用更快机器的情况下获得更好的性能,您可以采用 Coral Edge TPU 形式的应用专用芯片。

5. 在应用中运行 Coral 模型

如果您没有 Coral 设备,可以跳过此部分。

此 Codelab 步骤基于您在上一部分中编写的代码,但如果您想从头开始,也可以使用 cpu_inference_working 检查点。

运行 Coral 模型的步骤与运行 CPU 模型的步骤几乎完全相同。主要区别在于模型格式。由于 Coral 仅支持 uint8 张量,因此模型已量化。这会影响传递给模型的输入张量以及模型返回的输出张量。另一个区别是,模型需要使用 Edge TPU 编译器进行编译,才能在 Coral TPU 上运行。TeachableMachine 已完成此步骤,但您可以访问 Coral 文档,了解如何针对其他模型执行此操作。

将 Coral 模型文件添加到应用

解压缩您在训练分类器时下载的 converted_edgetpu.zip 模型文件。归档中包含两个文件。model_edgetpu.tflite 是保存的 TFLite 模型,包括模型图和权重。labels.txt 包含模型预测的类的简单易懂的标签。将模型文件放在 coral_model 目录中。

安装依赖项

运行 Coral 模型需要 Edge TPU 运行时库。请按照设置说明安装该应用,然后再继续。

Coral 设备以 TFLite 委托的形式进行访问。如需从 JavaScript 访问这些 API,请安装 coral-tflite-delegate 软件包:

npm install --save coral-tflite-delegate

然后,通过将以下行添加到 renderer.js 文件顶部来导入委托:

Codelab 第 2 部分:在此处导入委托。

const {CoralDelegate} = require('coral-tflite-delegate');

加载模型

现在,您可以加载 Coral 模型了。您可以通过与 CPU 模型相同的方式执行此操作,只不过现在您需要将选项传递给 loadTFLiteModel 函数,以加载 Coral 委托。

Codelab 第 2 部分:在此处加载委托模型。

const coralModelPath = './coral_model/model_edgetpu.tflite';
const options = {delegates: [new CoralDelegate()]};
const coralModel = await loadTFLiteModel(coralModelPath, options);

您无需加载标签,因为它们与 CPU 模型的标签相同。

添加了可在 CPU 和 Coral 之间切换的按钮

您将添加 Coral 模型,并将其与上一部分中添加的 CPU 模型一起使用。同时运行这两个模型很难看出性能差异,因此我们使用切换按钮在 Coral 和 CPU 执行之间切换。

使用以下代码添加按钮:

Codelab 第 2 部分:在此处创建委托按钮。

let useCoralDelegate = false;
const toggleCoralButton = document.createElement('button');
function toggleCoral() {
  useCoralDelegate = !useCoralDelegate;
  toggleCoralButton.innerText = useCoralDelegate
      ? 'Using Coral. Press to switch to CPU.'
      : 'Using CPU. Press to switch to Coral.';
}
toggleCoralButton.addEventListener('click', toggleCoral);
toggleCoral();
document.body.appendChild(toggleCoralButton);

我们来在 run() 函数中关联此条件。当 useCoralDelegate 为 false 时,应运行 CPU 版本。否则,它会运行 Coral 版本(但目前只会执行空操作)。将运行 CPU 模型的代码封装在 if 语句中。请注意,由于 Coral 模型会使用 expanded 张量,因此该张量未包含在 if 语句中。

Codelab 第 2 部分:检查此处是否使用委托。

// NOTE: Don't just copy-paste this code into the app.
// You'll need to edit the code from the CPU section.
const expanded = tf.expandDims(image, 0);
if (useCoralDelegate) {
  // CODELAB part 2: Run Coral prediction here.
} else {
  const divided = tf.div(expanded, tf.scalar(127));
  const normalized = tf.sub(divided, tf.scalar(1));
  stats.begin();
  const prediction = model.predict(normalized);
  stats.end();
  const percentage = tf.mul(prediction, tf.scalar(100));
  showPrediction(percentage.dataSync(), labels);
}

运行模型

Coral 版本的模型需要 0 到 255 之间的 uint8 张量,因此其输入不需要进行归一化处理。不过,输出也是一个范围介于 0 到 255 之间的 uint8 张量。在显示之前,需要将其转换为 0 到 100 之间的浮点数。

Codelab 第 2 部分:在此处运行 Coral 预测。(这是上述代码段的一部分)

stats.begin();
const prediction = coralModel.predict(expanded);
stats.end();
const percentage = tf.div(tf.mul(prediction, tf.scalar(100)), tf.scalar(255));
showPrediction(percentage.dataSync(), labels);

使用 yarn start 再次运行应用,它应该会显示来自 Coral 加速器的分类。

CPU 模型和 Coral 模型在应用中一次运行一个,并且可以通过按钮在它们之间切换。CPU 模型的帧速率约为 20 FPS,而 Coral 模型的帧速率约为 45 FPS。

您可以按相应按钮在 Coral 和 CPU 推理之间切换。您可能会注意到,Coral 模型的置信度排名不如 CPU 模型精确,并且通常以偶数位小数结尾。这种精度损失是在 Coral 上运行量化模型时需要做出的权衡。在实践中,这通常无关紧要,但需要牢记这一点。

关于效果的注意事项

您看到的帧速率包括预处理和后处理,因此无法代表 Coral 硬件的性能。您可以点击 FPS 计量器,直到它显示延迟时间(以毫秒为单位),从而更好地了解性能,延迟时间仅衡量对 model.predict 的调用。不过,这仍然包括将张量移至 TFLite 原生 C 绑定,然后再移至 Coral 设备所花费的时间,因此并非完美测量。如需了解以 C++ 编写的更准确的性能基准,请参阅 EdgeTPU 基准页面

另请注意,该视频是在笔记本电脑上录制的,而不是在 Raspberry Pi 上录制的,因此您可能会看到不同的 FPS。

加快 Coral 预处理速度

在某些情况下,您可以通过切换 TFJS 后端来加快预处理速度。默认后端是 WebGL,它非常适合大型可并行化操作,但此应用在预处理阶段并没有执行太多此类操作(它使用的唯一操作是 expandDims,该操作不可并行化)。您可以在文件顶部的导入语句后添加以下这行代码,切换到 CPU 后端,以避免将张量移入和移出 GPU 时产生的额外延迟。

tf.setBackend(cpu');

这也会影响 TFLite CPU 模型的预处理,而预处理并行化的,因此模型在进行此更改后运行速度会慢很多。

6. 使用 WebNN 加速 CPU 模型

如果您没有 Coral 加速器,或者只是想尝试其他加速模型的方法,可以使用 WebNN TFLite 委托。此委托使用 Intel 处理器中内置的机器学习硬件,通过 OpenVINO 工具包加速模型推理。因此,它有本 Codelab 的设置部分未涵盖的额外要求,您需要安装 OpenVINO 工具包。在继续操作之前,请务必根据支持的目标系统平台检查您的设置,但请注意,WebNN 委托目前尚不支持 macOS。

安装 OpenVINO 工具包

OpenVINO 工具包使用内置于 Intel 处理器中的机器学习硬件来加速模型。您可以从 Intel 下载预编译版本,也可以从源代码构建。您可以通过多种方式安装 OpenVINO,但在此 Codelab 中,我们建议您使用 WindowsLinux 的安装脚本。请务必安装 2021.4.2 LTS 运行时版本,因为其他版本可能不兼容。运行安装程序后,请务必按照 LinuxWindows 的安装说明(永久性解决方案)配置 shell 的环境变量,或者运行位于 webnn-tflite-delegate 目录中的 setupvars.sh (Linux) 或 setupvars.bat (Windows) 命令。

验证 WebNN 委托是否正常运行

如需验证 WebNN 委托是否正常运行,请运行代码库根目录中 webnn-tflite-delegate 软件包的集成测试。如需运行集成测试,请在软件包的目录中运行以下命令:

# In webnn-tflite-delegate/
npx yarn
npx yarn test-integration

您应该会看到如下所示的输出:

WebNN delegate: WebNN device set to 0.
INFO: Created TensorFlow Lite WebNN delegate for device Default and power Default.

============================
Hi there 👋. Looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, which binds to TensorFlow C++, by running npm i @tensorflow/tfjs-node, or npm i @tensorflow/tfjs-node-gpu if you have CUDA. Then call require('@tensorflow/tfjs-node'); (-gpu suffix for CUDA) at the start of your program. Visit https://github.com/tensorflow/tfjs-node for more details.
============================
label: wine bottle
score:  0.934505045413971
.


1 spec, 0 failures
Finished in 0.446 seconds
Randomized with seed 58441 (jasmine --random=true --seed=58441)
Done in 8.07s.

如果您看到如下所示的输出,则表示存在配置错误:

Platform node has already been set. Overwriting the platform with node.
Randomized with seed 05938
Started
error Command failed with exit code 3221225477.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

此输出很可能意味着您尚未设置 OpenVINO 的环境变量。目前,您可以通过运行 setupvars.sh (Linux) 或 setupvars.bat (Windows) 命令来设置这些变量,但您可能希望按照 LinuxWindows永久性解决方案)说明永久设置这些变量。如果您使用的是 Windows,

setupvars.bat

命令不支持 Git Bash,因此请确保您从 Windows 命令提示符运行此命令和此 Codelab 中的其他命令。

安装 WebNN 委托

安装 OpenVINO 后,您现在可以使用 WebNN 加速 CPU 模型。此 Codelab 部分基于您在“在应用中运行 CPU 模型”部分中编写的代码。您可以使用在此步骤中编写的代码,但如果您已完成 Coral 部分,请改用 cpu_inference_working 检查点,以便从头开始。

WebNN 委托的 Node.js 部分在 npmjs 上分发。如需安装,请运行以下命令:

npm install --save webnn-tflite-delegate

然后,通过将以下行添加到 renderer.js 文件顶部来导入委托:

Codelab 第 2 部分:在此处导入委托。

const {WebNNDelegate, WebNNDevice} = require('webnn-tflite-delegate');

WebNN 委托支持在 CPU 或 GPU 上运行;WebNNDevice 可让您选择使用哪个。

加载模型

现在,您就可以在启用 WebNN 委托的情况下加载模型了。对于 Coral,您必须加载不同的模型文件,但 WebNN 支持与 TFLite 相同的模型格式。将 WebNNDelegate 添加到传递给模型的委托列表中,以启用该委托:

Codelab 第 2 部分:在此处加载委托模型。

let webnnModel = await loadTFLiteModel(modelPath, {
  delegates: [new WebNNDelegate({webnnDevice: WebNNDevice.DEFAULT})],
});

由于这是同一模型,因此您无需再次加载标签。

添加了可在 TfLite CPU 和 WebNN 之间切换的按钮

现在,模型的 WebNN 版本已准备就绪,请添加一个按钮以在 WebNN 和 TfLite CPU 推理之间切换。同时运行这两个实验很难看出效果差异。

使用以下代码添加按钮(请注意,该按钮目前还无法实际切换模型):

Codelab 第 2 部分:在此处创建委托按钮。

let useWebNNDelegate = false;
const divElem = document.createElement('div');
const toggleWebNNButton = document.createElement('button');
function toggleWebNN() {
  useWebNNDelegate = !useWebNNDelegate;
  toggleWebNNButton.innerHTML = useWebNNDelegate
      ? 'Using WebNN. Press to switch to TFLite CPU.'
      : 'Using TFLite CPU. Press to switch to WebNN.';
  divElem.hidden = useWebNNDelegate ? false : true;
}

toggleWebNNButton.addEventListener('click', toggleWebNN);
toggleWebNN();
document.body.appendChild(toggleWebNNButton);
document.body.appendChild(divElem);

此代码还添加了一个 div 元素,您将在下一部分中使用该元素来配置 WebNN 设置。

添加下拉菜单以在 WebNN 设备之间切换

WebNN 支持在 CPU 和 GPU 上运行,因此添加一个下拉菜单以在这两者之间切换。在创建按钮的代码后面添加以下代码:

// Create elements for WebNN device selection
divElem.innerHTML = '<br/>WebNN Device: ';
const selectElem = document.createElement('select');
divElem.appendChild(selectElem);

const webnnDevices = ['Default', 'GPU', 'CPU'];
// append the options
for (let i = 0; i < webnnDevices.length; i++) {
  var optionElem = document.createElement('option');
  optionElem.value = i;
  optionElem.text = webnnDevices[i];
  selectElem.appendChild(optionElem);
}

现在,如果您运行应用,您会看到一个下拉菜单,其中列出了“默认”“GPU”和“CPU”。由于下拉菜单尚未连接,因此目前选择其中任何一个选项都不会有任何效果。该应用会显示一个下拉菜单,您可以在其中从“默认”“GPU”或“CPU”中选择 WebNN 设备。

使下拉菜单更改设备

如需连接下拉菜单,使其能够更改所使用的 WebNN 设备,请向下拉菜单选择器元素的 change 事件添加监听器。当所选值发生变化时,请在委托选项中选择相应的 WebNN 设备,然后重新创建 WebNN 模型。

在添加下拉菜单的代码后添加以下代码:

selectElem.addEventListener('change', async () => {
  let webnnDevice;
  switch(selectElem.value) {
    case '1':
      webnnDevice = WebNNDevice.GPU;
      break;
    case '2':
      webnnDevice = WebNNDevice.CPU;
      break;
    default:
      webnnDevice = WebNNDevice.DEFAULT;
      break;
  }
  webnnModel = await loadTFLiteModel(modelPath, {
    delegates: [new WebNNDelegate({webnnDevice})],
  });
});

进行此更改后,每次更改下拉菜单时,系统都会使用正确的设置创建一个新模型。现在,该连接 WebNN 模型并将其用于推理了。

运行 WebNN 模型

WebNN 模型已准备就绪,但用于在 WebNN 和 TfLite CPU 之间切换的按钮尚未实际切换模型。如需切换模型,您首先需要重命名在 Codelab 第一部分加载 TfLite CPU 模型时使用的 model 变量。

更改以下行...

const model = await loadTFLiteModel(modelPath);

...以便与此行匹配。

const cpuModel = await loadTFLiteModel(modelPath);

model 变量重命名为 cpuModel 后,将其添加到 run 函数中,以根据按钮的状态选择正确的模型:

Codelab 第 2 部分:检查此处是否使用委托。

let model;
if (useWebNNDelegate) {
  model = webnnModel;
} else {
  model = cpuModel;
}

现在,当您运行应用时,该按钮会在 TfLite CPU 和 WebNN 之间切换。TFLite CPU 模型以及 WebNN CPU 和 GPU 模型在应用中运行。当其中一个 WebNN 模型处于有效状态时,系统会显示一个下拉菜单,用于在这些模型之间切换。CPU 模型大约可实现 15 FPS,而 WebNN CPU 模型大约可实现 40 FPS。

如果您有集成的 Intel GPU,还可以在 WebNN CPU 和 GPU 推理之间切换。

关于效果的注意事项

您看到的帧速率包括预处理和后处理,因此无法代表 WebNN 的实际性能。您可以点击 FPS 计量器,直到它显示延迟时间(以毫秒为单位),从而更好地了解性能,延迟时间仅衡量对 model.predict 的调用。不过,这仍然包括将张量移至 TFLite 原生 C 绑定的时间,因此并非完美测量。

7. 恭喜

恭喜!您刚刚在 Electron 中使用 tfjs-tflite-node 完成了第一个 Coral / WebNN 项目。

试用一下,并使用各种图片进行测试。您还可以在 Teachable Machine 上训练新模型,以对完全不同的事物进行分类。

回顾

在本 Codelab 中,您学习了以下内容:

  • 如何安装和设置 tfjs-tflite-node npm 软件包,以便在 Node.js 中运行 TFLite 模型。
  • 如何安装 Edge TPU 运行时库,以便在 Coral 设备上运行模型。
  • 如何使用 Coral Edge TPU 加速模型推理。
  • 如何使用 WebNN 加速模型推理。

后续操作

您已经有了一个基准工作版本,那么,您可以想出哪些创意来扩展此机器学习模型运行程序,以处理现实中的用例?也许您能以快速且经济实惠的推理功能彻底改变您所在的行业,或者也许您能改造烤面包机,让它在面包烤得恰到好处时停止烘烤。这里将拥有无限可能

如需深入了解 Teachable Machine 如何训练您使用的模型,请查看我们关于迁移学习的 Codelab。如果您正在寻找可与 Coral 搭配使用的其他模型(例如语音识别和姿势估计),请访问 coral.ai/models。您还可以在 TensorFlow Hub 上找到这些模型的 CPU 版本以及许多其他模型。

与我们分享您的成果

您也可以轻松将今天的成果扩展到其他创意用例中,建议您跳出思维定式,做到持续改进。

请记得使用 #MadeWithTFJS 标签在社交媒体上标记我们,这样就有机会在我们的 TensorFlow 博客甚至未来的活动中展示您的项目。我们很期待看到您的成果。

参考网站