面向纯新手的TensorFlow.js速成课程

欢迎来到面向纯新手的TensorFlow.js速成课程的第一课。

本课程由CodingTheSmartWay.com出品,在本系列的第一部分中,你将学到:

  • TensorFlow.js是什么
  • 如何将TensorFlow.js添加到Web应用程序中
  • 如何使用TensorFlow.js向Web应用程序添加机器学习功能

什么是TensorFlow.js

TensorFlow.js是一个JavaScript库,它可以将机器学习功能添加到任何Web应用程序中。使用TensorFlow.js,可以从头开发机器学习脚本。你可以使用API​​在浏览器或Node.js服务器应用程序中构建和训练模型。并且,你可以使用TensorFlow.js在JavaScript环境中运行现有模型。

甚至,你可以使用TensorFlow.js用自己的数据再训练预先存在的机器学习模型,这些其中包括浏览器中客户端可用的数据。例如,你可以使用网络摄像头中的图像数据。

该项目的网站在https://js.tensorflow.org/:

新手TensorFlow.js课程

TensorFlow.js基础知识

在进行实际示例之前,让我们来看看TensorFlow中的主要构建块。

新手TensorFlow.js课程

张量

张量(Tensor)是TensorFlow中的主要数据单位。张量包含一组数值,可以是任何形状:一维或多维。当你创建新的张量时,你还需要定义形状(shape)。你可以通过使用tensor函数并传入第二个参数来定义形状,如下所示:

const t1 = tf.tensor([1,2,3,4,2,4,6,8]), [2,4]);

这是定义具有两行四列的形状的张量。产生的张量如下所示:

[[1,2,3,4],
[2,4,6,8]]

也可以让TensorFlow推断出张量的形状:

const t2 = tf.tensor([[1,2,3,4],[2,4,6,8]]);

结果与之前相同。

此外,你可以使用以下函数来增强代码可读性:

  • tf.scalar:只有一个值的张量
  • tf.tensor1d:具有一个维度的张量
  • tf.tensor2d:具有两个维度的张量
  • tf.tensor3d:具有三维的张量
  • tf.tensor4d:具有四个维度的张量

如果要创建一个所有值都设置为0的张量,可以使用tf.zeros函数,如下所示:

const t_zeros = tf.zeros([2,3]);

这行代码创建了以下张量:

[[0,0,0],
[0,0,0]]

在TensorFlow.js中,所有张量都是不可变的。这意味着张量一旦创建,之后就无法改变。如果你执行一个更改量值的操作,总是会创建一个新的张量并返回结果值。

操作

通过使用TensorFlow操作,你可以操纵张量的数据。由于张量运算的不变性,结果值总是返回一个新的张量。

TensorFlow.js提供了许多有用的操作,如square,add,sub和mul。你可以直接应用操作,如下所示:

const t3 = tf.tensor2d([1,2], [3, 4]);
const t3_squared = t3.square();

执行此代码后,新张量包含以下值:

[[1, 4 ],
[9, 16]]

模型和层

模型和层是深度学习的两个最重要的构建模块。每个模型都由一个或多个层构成。TensorFlow支持不同类型的层。对于不同的机器学习任务,你需要使用并组合不同类型的层。目前,你只需要理解:层是用来建立神经网络(模型)的,神经网络可以用数据训练,然后用训练后的信息来预测下一步的数值。

设置项目

让我们先来看一个例子。在第一步中,我们需要设置项目。创建一个新的空目录:

$ mkdir tfjs01

切换到新创建的项目文件夹:

$ cd tfjs01

在文件夹中,我们现在准备创建一个package.json文件,以便我们能够通过使用Node.js包管理器来管理依赖项:

$ npm init -y

因为我们将在项目文件夹中本地安装依赖项(例如Tensorflow.js库),所以我们需要为Web应用程序使用模块捆绑器(bundler)。为了尽可能简单,我们将使用Parcel Web应用程序捆绑器,因为Parcel不需要进行配置。让我们通过在项目目录中执行以下命令来安装Parcel捆绑器:

$ npm install -g parcel-bundler

接下来,让我们为我们的实现创建两个新的空文件:

$ touch index.html index.js

最后让我们将Bootstrap库添加为依赖项,因为我们将为我们的用户界面元素使用一些Bootstrap CSS类:

$ npm install bootstrap

在index.html中,让我们插入以下基本html页面的代码:

<html>
<body>
    <div class="container">
        <h1>Welcome to TensorFlow.js</h1>
        <div id="output"></div>
    </div>

    <script src="./index.js"></script>
</body>
</html>

另外,将以下代码添加到index.js:

import 'bootstrap/dist/css/bootstrap.css';

document.getElementById('output').innerText = "Hello World";

我们将文本Hello World写入具有ID输出的元素,以在屏幕上查看第一个结果并获得正确处理JS代码的确认。

最后,让我们通过使用parcel命令启动构建程序和开发的Web服务:

$ parcel index.html

你现在应该可以在浏览器中通过URL http://localhost:1234打开网站。结果应与你在以下截图中看到的内容对应:

新手TensorFlow.js课程

添加TensorFlow.js

为了Tensorflow.js添加到项目中,我们再次使用NPM并在项目目录中执行以下命令:

$ npm install @tensorflow/tfjs

这将下载并将其安装到node_modules文件夹中。成功执行此命令后,我们现在可以通过在文件顶部添加以下import语句来导入index.js中的Tensorflow.js库:

import * as tf from '@tensorflow/tfjs';

当我们将TensorFlow.js导入为tf后我们现在可以通过在代码中使用tf对象来访问TensorFlow.js API 。

定义模型

现在TensorFlow.js已经可用,让我们从一个简单的机器学习练习开始。下面的示例应用程序涵盖的机器学习脚本是公式Y = 2X-1,这是个线性回归。

此函数返回给定X对应的Y值。如果绘制点(X,Y),你将得到一条直线,如下所示:

新手TensorFlow.js课程

我们想要在下面实现的机器学习练习将使用来自该函数的输入数据(X,Y)并使用这些数字对训练模型。模型不会知道函数本身,我们将使用训练号模型根据X值输入预测Y值。期望从模型返回的Y结果接近函数返回的精确值。

让我们创建一个非常简单的神经网络来实现。此模型只需处理一个输入值和一个输出值:

// Define a machine learning model for linear regression
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));

首先,我们通过调用tf.sequential方法创建一个新的模型实例。我们得到一个新的序列模型。它是一种,其中一层的输出是下一层的输入,即模型拓扑是层的简单“堆叠”,没有分支或跳过。

创建好模型后,我们准备通过调用model.add来添加第一层。通过调用tf.layers.dense新层传递给add方法。这会创建一个稠密层。在稠密层中,层中的每个节点都连接到前一层中的每个节点。对于我们的示例,只需向神经网络添加一个具有一个输入和输出形状的密集层就足够了。

在下一步中,我们需要为模型指定损失函数和优化函数。

// Specify loss and optimizer for model
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});

这通过将配置对象传递给模型实例的编译方法调用来完成。配置对象包含两个属性:

  • loss:这里我们使用meanSquaredError损失函数。通常,损失函数用于将一个或多个变量的值映射到表示与该值相关联的一些“损失”的实数上。如果训练模型,它会尝试最小化损失函数的结果。估计量的均方误差是误差平方的平均值 – 即估计值与估计值之间的平均平方差。
  • optimizer:要使用的优化器函数。我们的线性回归机器学习任务使用的是sgd函数。Sgd代表Stochastic Gradient Descent,它是一个适用于线性回归任务的优化器函数。

现在该模型已配置,下一个要执行的任务是使用值训练模型。

训练模型

为了用函数Y=2X-1的值训练模型,我们定义了两个形状为6,1的张量。第一张量xs包含x值,第二张量ys包含相应的y值:

// Prepare training data
const xs = tf.tensor2d([-1, 0, 1, 2, 3, 4], [6, 1]);
const ys = tf.tensor2d([-3, -1, 1, 3, 5, 7], [6, 1])

现在让我们通过将两个张量传递给调用的model.fit方法来训练模型。

// Train the model
model.fit(xs, ys, {epochs: 500}).then(() => {
});

对于第三个参数,我们传递一个对象,该对象包含一个名为epochs的属性,该属性设置为值500。此处指定的数字是指定TensorFlow.js通过训练集的次数。

fit方法的结果是一个Promise,所以我们注册一个回调函数,该函数在训练结束时被激活。

预测

现在让我们在这个回调函数中执行最后一步,并根据给定的x值预测y值:

// Train the model
model.fit(xs, ys, {epochs: 500}).then(() => {
    // Use model to predict values
    model.predict(tf.tensor2d([5], [1,1])).print();
});

使用model.predict方法完成预测。该方法以张量的形式接收输入值作为参数。在这个特定情况下,我们在内部创建一个只有一个值(5)的张量并将其传递给预测。通过调用print函数,我们确保将结果值打印到控制台,如下所示:

新手TensorFlow.js课程

输出显示预测值为8.9962864并且非常接近9(如果x设置为5,函数Y=2X-1的Y值为9)。

优化用户界面

已上面经实现的示例是使用固定输入值进行预测(5)并将结果输出到浏览器控制台。让我们引入一个更复杂的用户界面,让用户能够输入用于预测的值。在index.html中添加以下代码:

<html>
<body>
    <div class="container" style="padding-top: 20px">
        <div class="card">
            <div class="card-header">
                <strong>TensorFlow.js Demo - Linear Regression</strong>
            </div>
            <div class="card-body">
                <label>Input Value:</label> <input type="text" id="inputValue" class="form-control"><br>
                <button type="button" class="btn btn-primary" id="predictButton" disabled>Model is being trained, please wait ...</button><br><br>
                <h4>Result: </span></h4>
                <h5><span class="badge badge-secondary" id="output"></span></h5>
            </div>
        </div>
    </div>

    <script src="./index.js"></script>
</body>
</html>

这里我们使用各种Bootstrap CSS类,向页面添加输入和按钮元素,并定义用于输出结果的区域。

我们还需要在index.js中做一些更改:

import * as tf from '@tensorflow/tfjs';
import 'bootstrap/dist/css/bootstrap.css';

// Define a machine learning model for linear regression
const model = tf.sequential();
model.add(tf.layers.dense({units: 1, inputShape: [1]}));

// Specify loss and optimizer for model
model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});

// Prepare training data
const xs = tf.tensor2d([-1, 0, 1, 2, 3, 4], [6, 1]);
const ys = tf.tensor2d([-3, -1, 1, 3, 5, 7], [6,1]);

// Train the model and set predict button to active
model.fit(xs, ys, {epochs: 500}).then(() => {
    // Use model to predict values
    document.getElementById('predictButton').disabled = false;
    document.getElementById('predictButton').innerText = "Predict";
});

// Register click event handler for predict button
document.getElementById('predictButton').addEventListener('click', (el, ev) => {
    let val = document.getElementById('inputValue').value;
    document.getElementById('output').innerText = model.predict(tf.tensor2d([val], [1,1]));
});

注册了预测按钮的click事件的事件处理程序。在此函数内部,读取input元素的值并调用model.predict方法。此方法返回的结果将插入具有id输出的元素中。

现在的结果应该如下所示:

新手TensorFlow.js课程

用户现在能够输入值(x),然后预测Y值。单击“ Predict ”按钮完成预测:

新手TensorFlow.js课程

结果会直接显示在网站上。

新手TensorFlow.js课程

总结

在本系列的第一集中,你学到了Tensorflow.js的基础知识,通过使用该库,我们实现了基于线性回归的第一个简单的机器学习示例。现在你应该对主要的Tensorflow.js构建块有基本的了解。

 

本文为ATYUN(www.atyun.com)编译作品,ATYUN专注人工智能
请扫码或微信搜索ATYUN订阅号及时获取最新内容

发表评论