十、tensorflow.js 入门
在前一章中,您已经了解了机器学习 ( ML )的基础知识,并学习了一些构建和使用 ML 模型所需的理论基础。
在本章中,我们将向您介绍一个高效且流行的 JavaScript 中的 ML 库,名为 TensorFlow.js,到本章结束时,您将了解如何安装和使用 TensorFlow.js,如何创建 tensor,如何使用 Core 应用编程接口 ( API )对 tensor 进行操作,以及如何使用 TensorFlow.js 的 Layer API 构建回归模型。
在本章中,我们将涵盖以下主题:
- 什么是 TensorFlow.js?
- 安装和使用 TensorFlow.js
- 张量和张量上的基本运算
- 用 TensorFlow.js 建立一个简单的回归模型
技术要求
要完成本章,您应该拥有以下工具或资源:
- 现代浏览器,如 Chrome、Safari、Opera 或 Firefox。
- 系统上安装的 Node.js
- 用于下载包和数据集的稳定互联网连接
- 本章的代码可从 GitHub 获得,可在https://GitHub . com/PacktPublishing/Building-Data-Driven-Applications-with-danfo . js/tree/main/chapter 10处克隆
什么是 TensorFlow.js?
TensorFlow.js(tfjs)是一个用于在浏览器或 Node.js 中创建、训练和部署 ML 模型的 JavaScript 库,由 Nikhil Thorat 和 Daniel Smilkov 在谷歌创建,最初名为 Deeplearn.js,2018 年被合并到 TensorFlow 团队,更名为 TensorFlow . js。
TensorFlow.js 提供了两个主要层,概述如下:
- CoreAPI :这是直接处理张量的低级 API——tensorflow . js 的核心数据结构。
- layer rapi:构建在 CoreAPI 层之上的高级层,用于轻松构建 ML 模型。
在后面的章节中,张量以及张量上的基本运算和使用 TensorFlow.js 构建一个简单的回归模型,您将了解到关于 CoreAPI 和 LayerAPI 层的更多细节。
使用 TensorFlow.js,您可以执行以下操作:
- 执行硬件加速的数学运算
- 为浏览器或 Node.js 开发 ML 模型
- 使用转移学习(T1)重新训练现有的 ML 模型
- 重用用 Python 训练的现有 ML 模型
在本章中,我们将介绍使用 TensorFlow.js 执行硬件加速的数学运算和开发 ML 模型。如果您想了解最后两个用例——再培训和重用 ML 模型——那么官方 TensorFlow.js 文档(https://www.tensorflow.org/js/guide)是一个很好的起点。
现在我们已经有了介绍,在下一节中,我们将向您展示如何在浏览器和 Node.js 环境中安装和使用 TensorFlow.js。
安装和使用 TensorFlow.js
正如我们前面提到的一样,TensorFlow.js 可以在浏览器和 Node.js 环境中安装和运行。在下面的段落中,我们将向您展示如何实现这一点,首先从浏览器开始。
在浏览器中设置 TensorFlow.js
安装 TensorFlow 有两种方式。浏览器中的 js。这些概述如下:
- 通过脚本标签
- 使用包管理器,如节点包管理器 ( npm )或纱线
通过脚本标签安装
通过script
标签安装 TensorFlow.js 很容易。只需将标签放入您的超文本标记语言 ( HTML )文件的头文件中,如以下代码片段所示:
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.6.0/dist/tf.min.js"></script>
要确认安装了 TensorFlow.js,请在浏览器中打开 HTML 文件,并检查网络选项卡。你应该看到名称tf.min.js
和一个200
的状态码,如下图截图所示:
图 10.1–显示 tfjs 成功安装的网络选项卡
您可以在您的 HTML 文件的正文中添加一个简单的脚本来确认tfjs
的成功安装。在 HTML 文件的script
部分,添加以下代码:
...
<script>
tf.ready().then(()=>{
console.log("Tensorflow.js loaded successfully!");
})
</script>
...
一旦 TensorFlow.js 在页面上加载并准备好,前面的代码片段就会将文本Tensorflow.js loaded
successfully!
记录到浏览器控制台。要查看输出,请在浏览器中打开 HTML 文件并检查控制台输出。你应该会看到一个输出结果,如下图截图所示:
图 10.2–加法运算的张量输出
接下来,让我们看看如何通过包管理器安装tfjs
。
通过包管理器安装
可以通过npm
或yarn
等包管理器安装tfjs
。当您需要在客户端项目(如 React 和 Vue 项目)中使用tfjs
时,这非常有用。
要使用npm
进行安装,请在您的命令行界面 ( 命令行界面)中运行以下命令:
npm install @tensorflow/tfjs
要使用yarn
进行安装,也只需在命令行界面中运行以下命令:
yarn add @tensorflow/tfjs
注意
在通过命令行界面使用npm
或yarn
成功安装软件包之前,您必须在系统中安装它们中的任何一个,最好是全局安装。如果你安装了 Node.js,那么你已经有了npm
。安装yarn
可以按照这里的步骤:https://classic.yarnpkg.com/en/docs/install/#mac-stable。
在安装成功后,您可以导入并使用tfjs
,如以下代码片段所示:
import * as tf from '@tensorflow/tfjs';
const x = tf.tensor2d([1, 2, 3, 4], [2, 2]);
const y = tf.tensor2d([1, 3, 5, 7], [2, 2]);
const sum = x.add(y)
sum.print()
运行前面的代码片段将在控制台中产生以下输出:
图 10.3–测试安装了包管理器的 tfjs 的输出
通过遵循前面代码块中的步骤,您应该能够在浏览器或客户端框架中安装和使用tfjs
。在下一节中,我们将向您展示如何在 Node.js 环境中安装tfjs
。
在 Node.js 中安装 TensorFlow.js
在节点中安装tfjs
。 js 很简单,但是首先要保证你的系统上安装了 node . js、npm
或者yarn
。
Node.js 中的 TensorFlow.js 有三个选项,安装的选择将取决于您的系统规格。在下面的小节中,我们将向您展示这三个选项。
使用本机 C++绑定安装 TensorFlow.js
@tensorflow/tfjs-node
()版本的tfjs
直接连接到 TensorFlow 的原生 C++绑定。这使得它速度很快,并且与 Python 版本的 TensorFlow 性能相当。这意味着tfjs-node
和tf.keras
在引擎盖下使用相同的 C++绑定。
要安装tfjs-node
,只需通过命令行界面运行以下命令:
npm install @tensorflow/tfjs-node
或者,如果使用yarn
,通过命令行界面运行以下命令:
yarn add @tensorflow/tfjs-node
在 GPU 支持下安装 TensorFlow.js
tfjs
的@tensorflow/tfjs-node-gpu
版本支持在图形处理单元 ( GPU )启用的 硬件上运行操作。使用tfjs-node-gpu
运行的操作通常比tfjs-node
运行的更快,因为操作可以很容易地矢量化。
要安装tfjs-node-gpu
,只需通过命令行界面运行以下命令:
npm install @tensorflow/tfjs-node-gpu
或者,如果使用yarn
,通过命令行界面运行以下命令:
yarn add @tensorflow/tfjs-node-gpu
安装普通 TensorFlow.js
@tensorflow/tfjs
版本是tfjs
的纯 JavaScript 版本。在性能方面是最慢的,应该很少使用。
要安装此版本,只需通过命令行界面运行以下命令:
npm install @tensorflow/tfjs
或者,如果使用yarn
,通过命令行界面运行以下命令:
yarn add @tensorflow/tfjs
如果您按照前面的步骤操作,那么您应该至少安装了一个版本的tfjs
。您可以使用以下代码示例测试安装是否成功:
const tf = require('@tensorflow/tfjs-node')
// const tf = require('@tensorflow/tfjs-node-gpu') GPU version
// const tf = require('@tensorflow/tfjs') Pure JS version
const xs = tf.randomNormal([100, 10])
const ys = tf.randomNormal([100, 1])
const sum = xs.add(ys)
const xsSum = xs.sum()
const xsMean = xs.mean()
console.log("Sum of xs and ys")
sum.print()
console.log("Sum of xs")
xsSum.print()
console.log("Mean of xs")
xsMean.print()
注意
当我们想要查看底层数据时,我们在张量上调用print()
函数。如果我们使用默认的console.log
,我们会得到Tensor
对象。
运行前面的代码应该会在控制台中输出以下内容:
图 10.4–测试安装在 Node.js 中的 tfjs 的输出
现在你已经在你的项目中成功安装了tfjs
,在下一节中,我们将向你介绍tfjs
的核心数据结构——张量。
张量和张量上的基本运算
张量是tfjs
中基本的数据结构。你可以认为张量是向量、矩阵或高维数组的推广。我们在中介绍的 CoreAPI 是什么?部分,展示了创建和使用张量的不同功能。
下面的截图显示了标量、向量和带有张量的矩阵之间的简单比较:
图 10.5–简单 n 维数组和张量之间的比较
小费
一个矩阵是一个由m x n
个数字组成的网格,其中m
代表行数,n
代表列数。矩阵可以是一维或多维的,相同形状的矩阵支持相互之间的直接数学运算。
另一方面,向量是具有形状(1,1)的一维矩阵;也就是说,它只有一行和一列,例如,[2,3],[3,1,4]。
我们之前提到张量更像是一个广义矩阵——也就是说,它扩展了矩阵的概念。张量可以用它们的等级来描述。等级类似于形状的概念,但由单个数字表示,而不是形状。在下面的列表中,我们通过示例看到了不同类型的张量等级:
- 秩为 0 的张量是标量,例如 1、20 或 100。
- 秩为 1 的张量是向量,例如[1,20]或[20,100,23.6]。
- 秩为 2 的张量是矩阵,例如[[1,3,6],[2.3,5,7]]。
请注意,我们可以有等级为 4 或更高的张量,这些张量被称为高维张量,很难可视化。请参见下面的截图,以更好地理解张量:
图 10.6–不同等级张量的比较
除了等级外,张量还有dtype
、data
、axis
和shape
等属性。这些在这里有更详细的描述:
dtype
属性(数据类型)是张量持有的数据类型,例如,具有以下数据[2.5,3.8]的秩 1 张量的数据类型为float32
。默认情况下,数字张量的数据类型为float32
,但这可以在创建过程中更改。TensorFlow.js 支持float32
、int32
、bool
、complex64
和string
数据类型。data
属性是张量的内容。这通常存储为数组。axis
属性是张量的特定维度,例如, m x n 张量的轴为 m 或 n 。该轴可用于指定在哪个维度上执行操作。shape
属性是张量的维数。把形状想象成张量每个轴上的元素数量。
现在您已经对张量有了基本的了解,在下一小节中,我们将向您展示如何创建张量,并对它们执行一些基本操作。
创造张量
可以用tf.tensor()
方法创建张量,如下面的代码片段所示:
const tf = require('@tensorflow/tfjs-node')
const tvector = tf.tensor([1, 2, 3, 4]);
console.log(tvector)
//output
Tensor {
kept: false,
isDisposedInternal: false,
shape: [ 4 ],
dtype: 'float32',
size: 4,
strides: [],
dataId: {},
id: 0,
rankType: '1'
}
在前面的代码片段中,我们将一个平面数组(向量)传递给tf.tensor()
方法来创建一个tfjs
张量。创建这个之后,我们现在可以使用不同的属性和函数来操纵或变换张量。
其中一个属性是shape
属性,我们可以调用它,如下面的代码片段所示:
console.log('shape:', tvector.shape);
//outputs: shape: [ 4 ]
注意,当你用console.log
记录张量时,你会得到一个张量对象。如果需要查看底层张量数组,可以调用张量上的print()
函数,如下面代码片段中的所示:
tvector.print();
//outputs
Tensor
[1, 2, 3, 4]
如果需要访问张量的底层数据,可以调用array()
或arraySync()
方法。两者的区别在于array()
异步运行并返回解析到底层数组的承诺,而arraySync()
同步运行。你可以在这里看到一个例子:
const tvectorArray = tvector.array()
const tvectorArraySync = tvector.arraySync()
console.log(tvectorArray)
console.log(tvectorArraySync)
//outputs
Promise { <pending> }
[ 1, 2, 3, 4 ]
也可以通过指定shape
参数来创建张量。例如,在下面的代码片段中,我们从一个平面数组创建一个 2×2(二维 ( 2D ))张量:
const ts = tf.tensor([1, 2, 3, 4], [2, 2]);
console.log('shape:', ts.shape);
ts.print();
//outputs
shape: [ 2, 2 ]
Tensor
[[1, 2],
[3, 4]]
或者,我们可以创建一个 1×4(一维 ( 1D )张量,如下面的代码片段所示:
const ts = tf.tensor([1, 2, 3, 4], [1, 4]);
console.log('shape:', ts.shape);
ts.print();
//outputs
shape: [ 1, 4 ]
Tensor
[[1, 2, 3, 4],]
然而,请注意,形状必须与元素的数量相匹配——例如,您不能从具有四个元素的平面阵列创建2 x 5
维张量。以下代码将引发形状错误:
const ts = tf.tensor([1, 2, 3, 4], [2, 5]);
输出如下所示:
图 10.7–形状不匹配引发的错误
Tfjs
明确提供功能用于创建 1D、2D、三维 ( 3D )、四维 ( 4D )、五维 ( 5D )、六维 ( 6D )张量。您可以使用它来代替指定shape
参数。你可以从官方的tfjs
应用编程接口这里阅读更多关于创建张量的信息:https://js.tensorflow.org/api/latest/#Tensors-Creation。
默认情况下,张量具有float32
的dtype
属性,因此您创建的任何张量都将具有float32
的dtype
。如果这不是期望的dtype
,您可以指定张量创建的类型,如我们在下面的代码片段中所演示的:
const tsInt = tf.tensor([1, 2, 3, 4], [1, 4], 'int32');
console.log('dtype:', tsInt.dtype);
//outputs
dtype: int32
现在你知道如何创建张量,我们将继续操作张量。
在张量上操作
张量,正如我们前面所说的,将数据存储在网格中,并允许大量操作来操纵或转换这些数据。tfjs
为线性代数和 ML 提供了很多算子。
tfjs
中的操作分为不同的部分。以下是一些常见操作的解释:
- 算术:这些运算符用于对张量进行算术计算。张量是不可变的,所以所有运算总是返回新的张量,从不修改输入张量——例如,
add()
表示张量的加法,sub()
表示张量的减法,mul()
表示张量的乘法,div()
表示张量的除法。参见完整列表并在此举例:https://js.tensorflow.org/api/3.7.0/#Operations-Arithmetic。 - 基本数学:这些算子用于对张量进行基本的数学计算——例如,
cos()
用于计算张量的余弦,sin()
用于计算张量的正弦,exp()
用于计算张量的指数,log()
用于计算张量的自然对数。见一个完整的列表,这里有例子:https://js . tensorflow . org/API/3 . 7 . 0/# Operations-Basic % 20m ath。 - 矩阵:这些运算符用于矩阵运算,如点积、范数或换位。您可以在这里看到支持的运算商的完整列表:https://js.tensorflow.org/api/3.7.0/#Operations-Matrices。
- 卷积:这些是计算张量卷积的运算符,例如
conv1d
,计算输入上的 1D 卷积x
,以及maxpool3D
,计算 3D 最大池运算。见此处完整列表:https://js.tensorflow.org/api/3.7.0/#Operations-Convolution。 - 约简:这些是计算张量约简的算子——例如
min
、max
、sum
、mean
、argMax
和argMin
。你可以在这里看到完整的例子列表:https://js.tensorflow.org/api/3.7.0/#Operations-Reduction。 - 逻辑:这些是在张量上计算布尔逻辑的运算符,例如
equal
、greater
、greaterEqual
和less
。你可以在这里看到带有例子的完整列表:https://js.tensorflow.org/api/3.7.0/#Operations-Logical。
您可以在这里的官方 API 中看到支持操作的完整列表:https://js.tensorflow.org/api/3.7.0/#Operations。
现在您已经对可用的张量算子有了基本的了解,我们将展示一些代码示例。
在张量上应用算术运算
我们可以通过在第一个张量上直接调用add()
方法并传递第二个张量作为参数来添加两个张量,如下面的代码片段所示:
const tf = require('@tensorflow/tfjs-node')
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([10, 20, 30, 40]);
a.add(b).print();
//outputs
Tensor
[11, 22, 33, 44]
请注意,您也可以通过在tf
对象上调用运算符来直接添加或应用任何运算符,如以下代码片段所示:
const tf = require('@tensorflow/tfjs-node')
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([10, 20, 30, 40]);
const sum = tf.add(a, b)
sum.print()
//outputs
Tensor
[11, 22, 33, 44]
利用这些知识,您可以执行其他算术运算,如减法、乘法、除法和幂运算,如我们在以下代码片段中演示的那样:
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([10, 20, 30, 40]);
const tfsum = tf.add(a, b)
const tfsub = tf.sub(b, a)
const tfdiv = tf.div(b, a)
const tfpow = tf.pow(b, a)
const tfmax = tf.maximum(a, b)
tfsum.print()
tfsub.print()
tfdiv.print()
tfpow.print()
tfmax.print()
//outputs
Tensor
[11, 22, 33, 44]
Tensor
[9, 18, 27, 36]
Tensor
[10, 10, 10, 10]
Tensor
[10, 400, 27000, 2560000]
Tensor
[10, 20, 30, 40]
值得一提的是,传递给算符的张量的顺序很重要,因为顺序的改变会导致结果不同。例如,如果我们将前面div
操作的顺序从const tfsub = tf.sub(b, a)
交换到const tfsub = tf.sub(a, b)
,那么我们会得到一个否定的结果,如下输出所示:
Tensor
[-9, -18, -27, -36]
注意所有涉及两个张量的运算只有在两个张量形状相同的情况下才会起作用。例如,以下操作将引发无效的形状错误:
const a = tf.tensor1d([1, 2, 3, 4]);
const b = tf.tensor1d([10, 20, 30, 40, 50]);
const tfsum = tf.add(a, b)
图 10.8–对不同形状的张量执行运算时出现无效形状错误
在下一小节中,我们看一些张量的基本数学运算的例子。
在张量上应用基本数学运算
遵循上一小节中的示例格式,在张量上应用算术运算,我们给出了在张量上计算数学运算的一些示例,如下所示:
const tf = require('@tensorflow/tfjs-node')
const x = tf.tensor1d([-1, 2, -3, 4]);
x.abs().print(); // Computes the absolute values of the tensor
x.cos().print(); // Computes the cosine of the tensor
x.exp().print(); // Computes the exponential of the tensor
x.log().print(); // Computes the natural logarithm of the tensor
x.square().print(); // Computes the sqaure of the tensor
输出如下所示:
Tensor
[1, 2, 3, 4]
Tensor
[0.5403023, -0.4161468, -0.9899925, -0.6536436]
Tensor
[0.3678795, 7.3890562, 0.0497871, 54.5981522]
Tensor
[NaN, 0.6931472, NaN, 1.3862944]
Tensor
[1, 4, 9, 16]
正如我们前面提到的,你可以直接从tf
对象调用操作符——例如,x.cos()
变成了tf.cos(x)
。
在张量上应用归约运算
我们也可以对张量进行mean
、min
、max
、argMin
、argMax
等归约运算。下面是以下代码片段中mean
、min
、max
、argMin
和argMax
的一些示例:
const x = tf.tensor1d([1, 2, 3]);
x.mean().print(); // or tf.mean(x) Returns the mean value of the tensor
x.min().print(); // or tf.min(x) Returns the smallest value in the tensor
x.max().print(); // or tf.max(x) Returns the largest value in the tensor
x.argMax().print(); // or tf.argMax(x) Returns the index of the largest value
x.argMin().print(); // or tf.argMin(x) Returns the index of the smallest value
输出如下所示:
Tensor 2
Tensor 1
Tensor 3
Tensor 2
Tensor 0
掌握了 ML、张量以及可以在张量上执行的操作的基本知识,现在就可以构建一个简单的 ML 模型了。在本章的下一节中,我们将巩固您在这一节中学到的所有知识。
用 TensorFlow.js 建立简单的回归模型
在前一章第九章机器学习基础中,你被介绍了 ML 的基础知识,尤其是回归和分类模型的理论方面。在本节中,我们将向您展示如何使用tfjs
layer rapi创建和训练回归模型。具体来说,到本节结束时,您将拥有一个可以根据超市数据预测销售价格的回归模型。
在本地设置环境
在构建回归模型之前,您必须在本地设置您的环境。在本节中,我们将在 Node.js 环境中工作。这意味着我们将使用 TensorFlow.js 和 Danfo.js 的node
版本。
按照以下步骤设置您的环境:
-
在新的工作目录中,为项目创建一个文件夹。我们将创建一个名为
sales_predictor
的,如下面的代码片段所示:js mkdir sales_predictor cd sales_predictor
-
接下来,在文件夹目录中打开一个终端,通过运行以下命令初始化一个新的
npm
项目:js npm init
-
接下来,安装
Danfo.js
节点包,如下所示:js yarn add danfojs-node or if using npm npm install danfojs-node
-
Also from the terminal, create an
src
folder and addtrain.js
,model.js
, anddata
_proc.js
files. You can create these folders/files manually from your code editor or by running the following command in the terminal:js mkdir src && cd src && touch train.js && touch data_proc.js && touch model.js
注意
请注意,在前面的代码片段中,我们在
src
文件夹中创建了三个文件(train.js
、data_proc.js
和model.js
)。这些文件将分别包含用于处理数据、创建tfjs
模型和模型训练的代码。
现在您已经设置了您的项目和文件,我们将进入下一节的数据检索和处理步骤。
检索和处理训练数据集
我们将用于模型训练的数据集被称为大润发销售数据集(https://www . kaggle . com/devash 0507/big-mart-sales-prediction)。它作为公共数据集在数据科学竞赛平台 Kaggle 上提供。
您可以直接从本章的代码库中下载数据集:https://github . com/PacktPublishing/Building-Data-Driven-Applications-with-danfo . js-/blob/main/chapter 10/sales _ predictor/src/dataset/train . CSV。下载成功后,在项目目录中创建一个名为dataset
的文件夹,并将数据集复制到其中。
为了确认一切正常,您的项目src
文件夹应该具有以下文件结构:
|-data-proc.js
|-dataset
| └── Train.csv
|-model.js
|-train.js
与所有数据科学问题一样,一般问题陈述可用于指导您解决问题。就 BigMart 销售数据集而言,问题陈述如下:
BigMart 收集了 2013 年不同城市 10 家门店 1559 款产品的销售数据。此外,还定义了每个产品和商店的某些属性。目的是建立一个预测模型,并找出每种产品在特定商店的销售额。
从前面的问题陈述中,你会注意到,建立这个模型的目的是帮助 BigMart 有效地预测每种产品在特定商店的销量。现在,这里的销售价格意味着连续的价值,因此,我们有一个回归问题。
现在您已经访问了数据并理解了问题陈述,您将使用Danfo.js
加载数据集并执行一些数据处理和清理。
注意
我们在这里的代码库中提供了一个单独的 Danfo Notebook(Dnotebook)文件:https://github . com/PacktPublishing/Building-Data-Driven-Applications-with-Danfo . js-/blob/main/chapter 10/sales _ predictor/src/big mart % 20 sales % 20 Notebook . JSON。在笔记本中,我们对销售数据集进行了一些数据探索和分析,其中大部分将帮助我们完成以下处理步骤。
在代码编辑器中打开data_proc.js
文件后,按照这里给出的步骤处理 BigMart 销售数据集:
-
首先我们导入
danfojs-node
,如下:js const dfd = require("danfojs-node")
-
然后,我们创建一个名为
processData
的函数,接受数据集路径,如下所示:js async function processData(trainDataPath) { //… process code goes here }
-
接下来,在
processData
函数的主体中,我们使用read_csv
函数加载数据集并打印标题,如下所示:js const salesDf = await dfd.read_csv(trainDataPath) salesDf.head().print()
-
为了确保数据加载工作,您可以将数据集的路径传递给
processData
函数,如以下代码片段所示:js processData("./dataset/train.csv")
-
And in your terminal, run the
data_proc.js
file using the following command:js node data_proc.js
这将输出以下内容:
图 10.9–显示 BigMart 销售数据集的头部值
-
从 Dnotebook 文件的分析中,我们注意到两列
Item_Weight
和Outlet_Sales
缺少值。在下面的代码片段中,我们将分别使用平均值和模态值来填充这些缺失值:js ... salesDf.fillna({ columns: ["Item_Weight", "Outlet_Size"], values: [salesDf['Item_Weight'].mean(), "Medium"], inplace: true }) ...
-
正如我们已经注意到的,数据集是分类(字符串)列和数值(
float32
和int32
)列的混合。这意味着我们必须将所有分类列转换为数字形式,然后才能将它们传递给我们的模型。在下面的代码片段中,我们使用 Danfo.js 的LabelEncoder
将每个分类列编码为一个数字:js ... let encoder = new dfd.LabelEncoder() let catCols = salesDf.select_dtypes(includes = ['string']).column_names // get all categorical column names catCols.forEach(col => { encoder.fit(salesDf[col]) enc_val = encoder.transform(salesDf[col]) salesDf.addColumn({ column: col, value: enc_val }) }) ...
-
接下来,我们将从训练数据集中分离目标。正如我们从问题陈述中注意到的,目标是销售价格。这对应于最后一列
Item_Outlet_Sales
。在下面的代码片段中,我们将使用iloc
函数分割数据集:js ... let Xtrain, ytrain; Xtrain = salesDf.iloc({ columns: [`1:${salesDf.columns.length - 1}`] }) ytrain = salesDf['Item_Outlet_Sales'] console.log(`Training Dataset Shape: ${Xtrain.shape}`) ...
-
接下来,我们将标准化我们的数据集。标准化我们的数据集迫使每一列都在比例中,因此改进了模型训练。在下面的代码片段中,我们使用 Danfo.js 的
StandardScaler
来标准化数据集:js ... let scaler = new dfd.MinMaxScaler() scaler.fit(Xtrain) Xtrain = scaler.transform(Xtrain) ...
-
Finally, to complete the
processData
function, we'll return the raw tensors, as shown in the following code snippet:js ... return [Xtrain.tensor, ytrain.tensor] ...
注意
在这里可以看到代码库中的完整代码:https://github . com/PacktPublishing/Building-Data-Driven-Applications-with-danfo . js/blob/main/chapter 10/sales _ predictor/src/Data-proc . js。
执行并打印最终data_proc.js
文件中的张量,应该会得到如下截图所示的张量:
图 10.10–处理后的最终 BigMart 数据张量
现在您有了一个可以处理原始数据集并返回张量的函数,让我们继续使用tfjs
创建模型。
用 TensorFlow.js 创建模型
正如我们前面提到的,tfjs
提供了一个图层应用编程接口,可以用来定义和创建 ML 模型。图层应用编程接口类似于流行的 Keras 应用编程接口,因此,已经熟悉 Keras 的 Python 开发人员可以轻松地将其代码移植到tfjs
。
图层应用编程接口提供了两种创建模型的方式——顺序和模型格式。我们将在下面的小节中简要解释并给出这些例子。
创建模型的顺序方式
这是最简单也是最常见的建模方式。它只是多个模型层的堆栈,其中堆栈中的第一层定义输入,最后一层定义输出,而中间层可以根据需要任意多。
下面的代码片段显示了一个两层顺序模型的示例:
const model = tf.sequential();
// First layer must have an input shape defined.
model.add(tf.layers.dense({units: 32, inputShape: [50]}));
model.add(tf.layers.dense({units: 24}));
model.add(tf.layers.dense({units: 1}));
您将从前面的代码片段中注意到,序列中的第一层提供了一个inputShape
参数。这意味着模型需要一个带有50
列的输入。
您也可以通过传递一系列层来创建一个顺序层,如下面的代码片段所示:
const model = tf.sequential({
layers: [tf.layers.dense({units: 32, inputShape: [50]}),
tf.layers.dense({units: 24}),
tf.layers.dense({units: 1})]
});
接下来,让我们看看模型格式。
创建模型的模型方式
创建模型的模型格式在创建模型时提供了更多的灵活性。不是简单地接受线性层的堆叠,用模型层定义的模型可以是非线性的、循环的,并且可以根据您的需要进行高级或连接。
例如,在下面的代码片段中,我们使用模型格式创建了一个两层网络:
const input = tf.input({ shape: [5] });
const denseLayer1 = tf.layers.dense({ units: 16, activation: 'relu' });
const denseLayer2 = tf.layers.dense({ units: 8, activation: 'relu' });
const denseLayer3 = tf.layers.dense({ units: 1 })
const output = denseLayer3.apply(denseLayer2.apply(denseLayer1.apply(input)))
const model = tf.model({ inputs: input, outputs: output });
从前面的示例代码中,您可以看到我们正在显式调用apply
函数,并将我们想要连接的图层作为参数传递。通过这种方式,我们可以构建具有图形连接的混合和高度复杂的模型。
您可以从这里的官方tfjs
文档中了解更多关于图层应用编程接口的信息:https://js.tensorflow.org/api/latest/#Models。
现在您知道了如何使用 Layer API 创建模型,我们将在下一节创建一个简单的三层回归模型。
创建简单的三层回归模型
回归模型,正如我们在前一章第九章机器学习基础所解释的,是一个具有连续输出的模型。为了用tfjs
创建一个回归模型,我们定义了层的堆叠,在最后一层,我们将units
的数量设置为1
。例如,打开代码库中的model.js
文件。在第 7-11 行中,您应该会看到以下顺序模型定义:
...
const model = tf.sequential();
model.add(tf.layers.dense({ inputShape: [11], units: 128, kernelInitializer: 'leCunNormal' }));
model.add(tf.layers.dense({units: 64, activation: 'relu' }));
model.add(tf.layers.dense({units: 32, activation: 'relu' }));
model.add(tf.layers.dense({units: 1}))
...
注意在第一层,我们将inputShape
参数设置为11
。这是因为我们的大集市数据集中有11
训练列。您可以通过打印处理过的张量的形状来确认这一点。在最后一层,我们将units
属性设置为1
,因为我们想要预测单个连续值。
中间的层可以是我们想要的任何数量,并且单元可以采用任何数量。因此,本质上,在两者之间增加更多的层会给我们一个更深的模型,而增加更多的单元会给我们一个更宽的模型。要使用的层的选择不仅取决于问题,还取决于执行多个实验和训练。
仅仅用这几行代码,你就成功地在tfjs
中创建了一个三层回归模型。
创建模型后,通常要做的下一件事是编译模型。那么,编译是做什么的?嗯,编译是为训练和评估准备模型的过程。这意味着,在编译阶段,我们必须设置模型的优化器、损失和/或训练度量。
必须先编译一个tfjs
模型,然后才能开始训练。那么,我们如何在tfjs
中编译模型呢?这可以通过在已定义的模型上调用compile
函数并设置您想要计算的优化器和度量来完成。
在model.js
文件的第 13-17 行中,我们通过将优化器设置为Adam
,将loss
和metrics
属性设置为meanSquaredError
来编译我们的回归模型。查看下面的代码片段:
...
model.compile({
optimizer: tf.train.adam(LEARNING_RATE),
loss: tf.losses.meanSquaredError,
metrics: ['mse']
});
...
值得一提的是有不同类型的优化器可供选择;查看 https://js.tensorflow.org/api/latest/#Training-Optimizers 的完整列表。选择使用哪种优化器将取决于您的经验以及多次实验。
就损失而言,问题将通知您使用哪个损失函数。在我们的例子中,由于这是一个回归问题,我们可以使用均方误差 ( 均方误差)函数。要查看可用损耗功能的完整列表,请访问https://js.tensorflow.org/api/latest/#Training-Losses。
最后,就模型训练期间计算和显示的指标而言,我们可以指定多个选项,就像损失一样,指定的指标将取决于您试图解决的问题。在我们的例子中,我们也可以计算一个均方误差。要查看支持指标的完整列表,请访问https://js.tensorflow.org/api/latest/#Metrics。
现在您已经定义并编译了模型,我们将进入本章的下一部分,也是最后一部分,这是关于训练模型的。
用处理后的数据集训练模型
train.js
文件包含代码,用于在处理后的数据集上训练三层回归模型。在以下步骤中,我们将引导您完成模型培训的整个过程:
-
首先,让我们使用
processData
函数加载和处理数据集,如下所示:js … const data = await processData("./dataset/train.csv") const Xtrain = data[0] const ytrain = data[1] …
-
接下来,我们使用
getModel
功能加载模型,如下所示:js … const model = getModel() …
-
Next, and very importantly, we call the
fit
function on the model, pass the training data, the target, and a couple of parameters such as theepoch
,batchSize
, andvalidationSplits
parameters, and a callback function calledonEpochEnd
, as follows:js … await model.fit(Xtrain, ytrain, { batchSize: 24, epochs: 20, validationSplit: 0.2, callbacks: { onEpochEnd: async (epoch, logs) => { const progressUpdate = `EPOCH (${epoch + 1}): Train MSE: ${Math.sqrt(logs.mse)}, Val MSE: ${Math.sqrt(logs.val_mse)}\n` console.log(progressUpdate); } } }); ...
让我们理解我们传递给
fit
函数的参数的作用,如下所示:Xtrain
:训练数据。ytrain
:目标数据。epoch
:历元大小是迭代训练数据的次数。batchSize
:批次大小是计算一次梯度更新时使用的数据点或样本数。validationSplit
:验证分割是一个方便的参数,它告诉tfjs
保留指定百分比的数据进行验证。当我们不想手动将数据集分割成训练集和测试集时,可以使用这种方法。callbacks
:回调,顾名思义,接受在模型训练的不同生命周期中调用的函数列表。回调在监控模型训练中很重要。查看完整的回调列表:https://js.tensorflow.org/api/latest/#tf.。- 最后,我们保存模型,以便在进行新的预测时使用,如下所示:
js ... await model.save("file://./sales_pred_model") ...
运行train.js
文件将加载和处理数据集,加载模型,并针对指定数量的时期运行模型训练。我们指定的回调(onEpochEnd
)会打印出每个历元后的损失和根 MSE,如下图截图所示:
图 10.11–显示损失和根均方误差的模型训练日志
就这样!您已经成功地创建、训练并保存了一个回归模型,该模型可以使用 TensorFlow.js 预测销售价格。在本章的下一部分也是最后一部分,我们将向您展示如何加载您保存的模型并使用它进行预测。
用训练好的模型进行预测
为了做出预测,我们必须加载保存的模型,并在其上调用predict
函数。TensorFlow.js 提供了一个loadLayersModel
函数,可以用来从文件系统加载保存的模型。在以下步骤中,我们将向您展示如何实现这一点:
- 创建一个名为
predict.js
的新文件。 -
In the
predict.js
file, add the following code:js const dfd = require("danfojs-node") const tf = dfd.tf async function loadModel() { const model = await tf.loadLayersModel('file://./sales_pred_model/model.json'); model.summary() return model } loadModel()
前面的代码从文件路径加载保存的模型并打印摘要。摘要的输出应该类似于下面屏幕截图中显示的内容:
图 10.12–已保存模型的模型摘要
-
Now, create a new function called
predict
that uses the saved model to make a prediction, as shown in the following code snippet:```js ... async function predict() { //You'll probably have to do some data pre-processing as we did before training const data = [0.1, 0.21, 0.25, 0.058, 0.0, 0.0720, 0.111, 1, 0, 0.5, 0.33] //sample processed test data const model = await loadModel() const value = model.predict(tf.tensor(data, [1, 11])) //cast data to required shape console.log(value.arraySync());
} predict() ```
输出如下所示:
js [ [ 738.65380859375 ] ] ...
在前面的函数中,我们在模型上调用
predict
函数,并传递一个具有我们的模型所期望的正确形状(batch,11)的张量。这返回预测的张量,从这个张量,我们得到基础值。由此,我们可以看出,具有这些特定价值的产品售价约为 739 美元 ( 美元)。注意
在现实世界的应用中,您通常会从另一个逗号分隔值 ( CSV )文件中加载一个测试数据集,并应用与我们在培训期间相同的数据处理步骤。该示例使用内联数据点,只是为了演示如何使用保存的模型进行预测。
这就把我们带到了这一章的结尾!祝贺你走到这一步。我相信你学到了很多。在下一章中,我们将通过构建一个更实际的应用——一个推荐系统来深入探讨!
总结
在本章中,我们向您介绍了 TensorFlow.js 的基础知识,具体来说,您学习了如何在浏览器和 Node.js 环境中安装 TensorFlow.js,您学习了 tensors 和tfjs
的核心数据结构,您学习了 core 和 Layer APIs,最后,您学习了如何构建、训练和保存回归模型。
在下一章中,我们将深入到一个更加实用和动手的项目中,这里获得的知识将帮助您使用 TensorFlow.js 和 Danfo.js 构建出色的产品。
版权属于:月萌API www.moonapi.com,转载请注明出处