使用 TensorFlow.js 在 Node.js 中进行机器学习

2025-05-24

使用 TensorFlow.js 在 Node.js 中进行机器学习

TensorFlow.js是广受欢迎的开源库的新版本,它将深度学习引入 JavaScript。开发者现在可以使用高级库 API定义、训练和运行机器学习模型。

预先训练的模型意味着开发人员现在只需几行 JavaScript即可轻松执行复杂的任务,如视觉识别生成音乐检测人体姿势。

TensorFlow.js 最初是 Web 浏览器的前端库,最近的更新增加了对 Node.js 的实验性支持。这使得 TensorFlow.js 可以在后端 JavaScript 应用程序中使用,而无需使用 Python。

阅读有关该库的信息后,我想通过一个简单的任务来测试它... 🧐

使用 TensorFlow.js 通过 Node.js 中的 JavaScript 对图像进行视觉识别

遗憾的是,大部分文档示例代码都是在浏览器中使用该库的。项目提供的用于简化加载和使用预训练模型的实用程序尚未扩展 Node.js 支持。为了实现这一点,我花了很多时间阅读该库的 Typescript 源文件。👎

不过,经过几天的折腾,我终于完成!太棒了!🤩

在深入研究代码之前,让我们先概述一下不同的 TensorFlow 库。

TensorFlow

TensorFlow是一个用于机器学习应用的开源软件库。TensorFlow 可用于实现神经网络和其他深度学习算法。

TensorFlow 由 Google 于 2015 年 11 月发布,最初是一个Python 库。它使用基于 CPU 或 GPU 的计算来训练和评估机器学习模型。该库最初设计用于在配备昂贵 GPU 的高性能服务器上运行。

最近的更新扩展了该软件在移动设备和网络浏览器等资源受限的环境中运行的功能。

TensorFlow Lite

Tensorflow Lite是适用于移动和嵌入式设备的轻量级库版本,于 2017 年 5 月发布。同时发布的还有一系列用于视觉识别任务的预训练深度学习模型,名为MobileNet。MobileNet 模型旨在在移动设备等资源受限的环境中高效工作。

TensorFlow.js

继 Tensorflow Lite 之后,TensorFlow.js于 2018 年 3 月发布。该库版本旨在在浏览器中运行,基于早期项目deeplearn.js构建。WebGL 提供对该库的 GPU 访问。开发者使用 JavaScript API 来训练、加载和运行模型。

TensorFlow.js 最近扩展为在 Node.js 上运行,使用了名为的扩展库tfjs-node

Node.js 扩展是一个 alpha 版本,仍在积极开发中。

将现有模型导入 TensorFlow.js

现有的 TensorFlow 和 Keras 模型可以使用 TensorFlow.js 库执行。执行前,模型需要使用此工具转换为新格式。Github上提供了用于图像分类、姿态检测和 K 最近邻的预训练和转换模型

在 Node.js 中使用 TensorFlow.js

安装 TensorFlow 库

TensorFlow.js 可以从NPM 注册表安装

npm install @tensorflow/tfjs @tensorflow/tfjs-node
// or...
npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu
Enter fullscreen mode Exit fullscreen mode

这两个 Node.js 扩展都使用本机依赖项,​​这些依赖项将根据需要进行编译。

加载 TensorFlow 库

TensorFlow 的JavaScript API从核心库中公开。用于启用 Node.js 支持的扩展模块不会公开额外的 API。

const tf = require('@tensorflow/tfjs')
// Load the binding (CPU computation)
require('@tensorflow/tfjs-node')
// Or load the binding (GPU computation)
require('@tensorflow/tfjs-node-gpu')
Enter fullscreen mode Exit fullscreen mode

加载 TensorFlow 模型

TensorFlow.js 提供了一个NPM 库( ),以便于加载用于图像分类姿势检测k 最近邻的tfjs-models预训练和转换模型

用于图像分类的MobileNet 模型是一个经过训练可以识别 1000 个不同类别的深度神经网络。

在项目的README中,使用以下示例代码来加载模型。

import * as mobilenet from '@tensorflow-models/mobilenet';

// Load the model.
const model = await mobilenet.load();
Enter fullscreen mode Exit fullscreen mode

我遇到的第一个挑战是这在 Node.js 上不起作用。

Error: browserHTTPRequest is not supported outside the web browser.
Enter fullscreen mode Exit fullscreen mode

查看源代码,该mobilenet库是对底层类的包装tf.Model。当load()调用该方法时,它会自动从外部 HTTP 地址下载正确的模型文件,并实例化 TensorFlow 模型。

Node.js 扩展尚不支持通过 HTTP 请求动态检索模型。因此,必须手动从文件系统加载模型。

在阅读了该库的源代码后,我设法创建了一个解决方法......

从文件系统加载模型

load如果类是手动创建的,则无需调用模块的方法,而是可以使用本地文件系统路径覆盖包含模型 HTTP 地址的MobileNet自动生成变量。完成此操作后,在类实例上调用该方法将触发文件系统加载器类,而不是尝试使用基于浏览器的 HTTP 加载器。pathload

const path = "mobilenet/model.json"
const mn = new mobilenet.MobileNet(1, 1);
mn.path = `file://${path}`
await mn.load()
Enter fullscreen mode Exit fullscreen mode

太棒了,它有效!

但是模型文件从何而来?

MobileNet 模型

TensorFlow.js 的模型包含两种文件类型:以 JSON 格式存储的模型配置文件和二进制格式的模型权重。为了便于浏览器缓存,模型权重通常会被分片到多个文件中。

查看MobileNet 模型的自动加载代码,模型配置和权重分片是从此地址的公共存储桶中检索的。

https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v${version}_${alpha}_${size}/
Enter fullscreen mode Exit fullscreen mode

URL 中的模板参数指的是此处列出的模型版本。该页面上还显示了每个版本的分类准确率结果。

根据源代码,只能使用该库加载 MobileNet v1 模型tensorflow-models/mobilenet

HTTP 检索代码model.json从此位置加载文件,然后递归获取所有引用的模型权重分片。这些文件的格式为groupX-shard1of1

手动下载模型

通过检索模型配置文件、解析引用的权重文件并手动下载每个权重文件,可以将所有模型文件保存到文件系统。

我想使用 alpha 值为 1.0 且图像大小为 224 像素的 MobileNet V1 模块。这为我提供了以下模型配置文件的URL 。

https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/model.json
Enter fullscreen mode Exit fullscreen mode

一旦该文件被下载到本地,我就可以使用该jq工具解析所有权重文件名。

$ cat model.json | jq -r ".weightsManifest[].paths[0]"
group1-shard1of1
group2-shard1of1
group3-shard1of1
...
Enter fullscreen mode Exit fullscreen mode

使用该sed工具,我可以在这些名称前加上 HTTP URL 前缀来为每个权重文件生成 URL。

$ cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//'
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group1-shard1of1
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group2-shard1of1
https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_1.0_224/group3-shard1of1
...
Enter fullscreen mode Exit fullscreen mode

使用parallelcurl命令,我可以将所有这些文件下载到我的本地目录。

cat model.json | jq -r ".weightsManifest[].paths[0]" | sed 's/^/https:\/\/storage.googleapis.com\/tfjs-models\/tfjs\/mobilenet_v1_1.0_224\//' |  parallel curl -O
Enter fullscreen mode Exit fullscreen mode

图像分类

此示例代码由 TensorFlow.js 提供,用于演示如何返回图像的分类。

const img = document.getElementById('img');

// Classify the image.
const predictions = await model.classify(img);
Enter fullscreen mode Exit fullscreen mode

由于缺少 DOM,这在 Node.js 上不起作用。

classify 方法接受多个 DOM 元素(canvasvideoimage),并将自动从这些元素中检索图像字节并将其转换为类tf.Tensor3D用作模型的输入。或者,也tf.Tensor3D可以直接传递输入。

我发现,与尝试使用外部包来模拟 Node.js 中的 DOM 元素相比,手动构建更容易tf.Tensor3D

从图像生成 Tensor3D

阅读将 DOM 元素转换为 Tensor3D 类的方法的源代码,以下输入参数用于生成 Tensor3D 类。

const values = new Int32Array(image.height * image.width * numChannels);
// fill pixels with pixel channel bytes from image
const outShape = [image.height, image.width, numChannels];
const input = tf.tensor3d(values, outShape, 'int32');
Enter fullscreen mode Exit fullscreen mode

pixels是一个二维数组(Int32Array),其中包含每个像素的通道值顺序列表。numChannels是每个像素的通道值数量。

为 JPEG 创建输入值

jpeg-js是一个纯 JavaScript 的 JPEG 编码器和解码器,适用于 Node.js。使用该库可以提取每个像素的 RGB 值。

const pixels = jpeg.decode(buffer, true);
Enter fullscreen mode Exit fullscreen mode

这将返回一个包含每个像素 ( ) 的Uint8Array四个通道值 ( ) 的数组。MobileNet 模型仅使用三个颜色通道 ( ) 进行分类,忽略了 Alpha 通道。此代码将四通道数组转换为正确的三通道版本。RGBAwidth * heightRGB

const numChannels = 3;
const numPixels = image.width * image.height;
const values = new Int32Array(numPixels * numChannels);

for (let i = 0; i < numPixels; i++) {
  for (let channel = 0; channel < numChannels; ++channel) {
    values[i * numChannels + channel] = pixels[i * 4 + channel];
  }
}
Enter fullscreen mode Exit fullscreen mode

MobileNet 模型输入要求

所使用的MobileNet 模型用于对宽高均为 224 像素的图像进行分类。输入张量必须包含介于 -1 和 1 之间的浮点值,用于三个通道的像素值。

不同尺寸图像的输入值在分类之前需要重新调整大小。此外,JPEG 解码器的像素值范围是0 - 255,而不是-1 到 1。这些值在分类之前也需要转换。

TensorFlow.js 提供了库方法来简化这个过程,但幸运的是,tfjs-models/mobilenet会自动处理这个问题! 👍

开发者可以将 Tensor3D 类型和不同维度的输入传递int32给该classify方法,它会在分类之前将输入转换为正确的格式。这意味着无需执行任何操作……太棒了🕺🕺🕺。

获取预测

Tensorflow 中的 MobileNet 模型经过训练,可以识别ImageNet数据集中前 1000 个类别的实体。这些模型输出每个实体出现在待分类图像中的概率。

所用模型的训练类别的完整列表可在此文件中找到。

tfjs-models/mobilenet库公开了一个classify类方法MobileNet,用于从图像输入中返回概率最高的前 X 个类。

const predictions = await mn_model.classify(input, 10);
Enter fullscreen mode Exit fullscreen mode

predictions是以下格式的 X 类和概率的数组。

{
  className: 'panda',
  probability: 0.9993536472320557
}
Enter fullscreen mode Exit fullscreen mode

例子

在研究了如何在 Node.js 上使用 TensorFlow.js 库和 MobileNet 模型之后,该脚本将对作为命令行参数给出的图像进行分类。

源代码

  • 将此脚本文件和包描述符保存到本地文件。

测试一下

  • mobilenet按照上述说明将模型文件下载到目录中。
  • 使用 NPM 安装项目依赖项
npm install
Enter fullscreen mode Exit fullscreen mode
  • 下载示例 JPEG 文件进行分类
wget http://bit.ly/2JYSal9 -O panda.jpg
Enter fullscreen mode Exit fullscreen mode

熊猫

  • 使用模型文件和输入图像作为参数运行脚本。
node script.js mobilenet/model.json panda.jpg
Enter fullscreen mode Exit fullscreen mode

如果一切正常,则应在控制台上打印以下输出。

classification results: [ {
    className: 'giant panda, panda, panda bear, coon bear',
    probability: 0.9993536472320557 
} ]
Enter fullscreen mode Exit fullscreen mode

该图像被正确分类为包含熊猫,概率高达 99.93%!🐼🐼🐼

结论

TensorFlow.js 为 JavaScript 开发者带来了深度学习的强大功能。结合使用 TensorFlow.js 库中的预训练模型,可以轻松扩展 JavaScript 应用程序,使其能够执行复杂的机器学习任务,并且只需极少的精力和代码。

TensorFlow.js 最初是基于浏览器的库,现在已扩展至 Node.js,但并非所有工具和实用程序都支持新的运行时。经过几天的调试,我终于能够将该库与 MobileNet 模型结合使用,对本地文件中的图像进行视觉识别。

在 Node.js 运行时中运行它意味着我现在可以开始我的下一个想法了……让它在无服务器函数中运行!欢迎回来阅读我接下来的 TensorFlow.js 冒险之旅。👋

文章来源:https://dev.to/ibmdeveloper/machine-learning-in-nodejs-with-tensorflowjs-1g1p
PREV
2020 年必须知道的 15 个 JavaScript 数组方法 1. some() 2. reduce() 3. every() 4. map() 5. flat() 6. filter() 7. forEach() 8. findIndex() 9. find() 10. sort() 11. concat() 12. fill() 13. includes() 14. reverse() 15. flatMap()
NEXT
10 个 GitHub 代码库助您提升开发者职业发展