TensorFlow.js入门教程(2)核心概念

(本文译自Core Concepts in TensorFlow.js

(未经作者同意,请勿转载)

TensorFlow.js是一个用于机器智能的开源基于WebGL加速的JavaScript库。 它将高性能机器学习构建块带到您的指尖,使您能够在浏览器中训练神经网络或在推理模式下运行预先训练的模型。 有关安装/配置TensorFlow.js的指南,请参阅入门指南

TensorFlow.js为机器学习提供低级构建模块,以及构建神经网络的高级Keras启发式API。 我们来看看库的一些核心组件。

张量(Tensor)

TensorFlow.js中数据的中心单位是张量:一组数值形成一个或多个维度的数组。 张量实例具有定义数组形状的形状属性(即,数组的每个维度中有多少个值)。

张量的主要构造函数是tf.tensor函数:

// 2x3 Tensor
const shape = [2, 3]; // 2 行, 3 列
const a = tf.tensor([1.0, 2.0, 3.0, 10.0, 20.0, 30.0], shape);
a.print(); // 打印张量值
// 输出:    [[1 , 2 , 3 ],
//          [10, 20, 30]]

// shape也可以用下面的方式实现:
const b = tf.tensor([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
b.print();
// 输出:    [[1 , 2 , 3 ],
//          [10, 20, 30]]

但是,为了构造低秩张量,我们推荐使用以下函数来增强代码可读性:tf.scalartf.tensor1dtf.tensor2dtf.tensor3dtf.tensor4d

以下示例使用tf.tensor2d创建与上面相同的张量:

const c = tf.tensor2d([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
c.print();
// 输出:    [[1 , 2 , 3 ],
//          [10, 20, 30]]

TensorFlow.js还提供了创建所有值均为0(tf.zeros)或将所有值均为1(tf.ones)的张量的函数:

// 值全为零,大小为3x5的张量
const zeros = tf.zeros([3, 5]);
// 输出:     [[0, 0, 0, 0, 0],
//          [0, 0, 0, 0, 0],
//          [0, 0, 0, 0, 0]]

在TensorFlow.js中,张量是不变的; 一旦创建,你就不能改变它们的值。 但是,您可以对它们执行操作来生成新的张量。

变量(Variable)

变量用张量的值进行初始化。 然而,与张量不同的是,它们的值是可变的。 您可以使用assign方法为现有变量分配一个新的张量:

const initialValues = tf.zeros([5]);
const biases = tf.variable(initialValues); // 初始化biases
biases.print(); // 输出: [0, 0, 0, 0, 0]

const updatedValues = tf.tensor1d([0, 1, 0, 1, 0]);
biases.assign(updatedValues); // 更新 biases的值
biases.print(); // 输出: [0, 1, 0, 1, 0]

变量主要用于在模型训练期间存储和更新值。

操作(Ops)

张量允许您存储数据,而操作(ops)允许您操作该数据。 TensorFlow.js提供了适用于线性代数和机器学习的可以在张量上执行的各种操作。 因为张量是不变的,所以这些运算不会改变它们的值; 相反,ops会返回新的张量。

可用的操作包括一元操作,如square

const d = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
const d_squared = d.square();
d_squared.print();
//    输出:  [[1, 4 ],
//          [9, 16]]

和二元操作,如addsubmul

const e = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
const f = tf.tensor2d([[5.0, 6.0], [7.0, 8.0]]);

const e_plus_f = e.add(f);
e_plus_f.print();
// 输出:    [[6 , 8 ],
//          [10, 12]]

TensorFlow.js支持链式API; 你可以在Op的结果上调用Op:

const sq_sum = e.add(f).square();
sq_sum.print();
// 输出:    [[36 , 64 ],
//          [100, 144]]

//所有的操作在主名空间内也作为函数,
// 所以你也可以这样做:
const sq_sum = tf.square(tf.add(e, f));

模型和层

从概念上讲,模型是一个函数,给定一些输入会产生一些期望的输出。

在TensorFlow.js中有两种创建模型的方法。 您可以直接使用ops来表示模型所做的工作。 例如:

// 定义函数
function predict(input) {
  // y = a * x ^ 2 + b * x + c
  // More on tf.tidy in the next section
  return tf.tidy(() => {
    const x = tf.scalar(input);

    const ax2 = a.mul(x.square());
    const bx = b.mul(x);
    const y = ax2.add(bx).add(c);

    return y;
  });
}

// 定义常量: y = 2x^2 + 4x + 8
const a = tf.scalar(2);
const b = tf.scalar(4);
const c = tf.scalar(8);

// 为输入2预测输出
const result = predict(2);
result.print() // 输出: 24

您还可以使用高级API tf.model构建由层组成的模型,这是深度学习中的流行抽象。 以下代码构建了一个tf.sequential模型:

const model = tf.sequential();
model.add(
  tf.layers.simpleRNN({
    units: 20,
    recurrentInitializer: 'GlorotNormal',
    inputShape: [80, 4]
  })
);

const optimizer = tf.train.sgd(LEARNING_RATE);
model.compile({optimizer, loss: 'categoricalCrossentropy'});
model.fit({x: data, y: labels)});

TensorFlow.js中有许多不同类型的层, 例如tf.layers.simpleRNNtf.layers.grutf.layers.lstm

内存管理:dispose和tf.tidy

由于TensorFlow.js使用GPU来加速数学运算,因此在处理张量和变量时需要管理GPU内存。

TensorFlow.js提供了两个帮助解决这个问题的函数:dispose和tf.tidy

dispose

您可以在张量或变量上调用dispose来清除它并释放其GPU内存:

const x = tf.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
const x_squared = x.square();

x.dispose();
x_squared.dispose();

tf.tidy

进行大量的张量操作时使用dispose可能会很麻烦。 TensorFlow.js提供了另一个函数tf.tidy,它对JavaScript中的常规范围起到类似的作用,不同的是它针对GPU支持的张量。

tf.tidy执行一个函数并清除所有创建的中间张量,释放它们的GPU内存。 它不清除内部函数的返回值。

// tf.tidy 接受一个函数作为参数,并在函数执行完后并清理它 
const average = tf.tidy(() => {
  // tf.tidy 会清除函数内使用的所有GPU内存,
  //  除了返回值的tensor.
  //
  //即便是像下面这个那么短的ops系列,
  //也会创建不少中间张量。
  //所以把数学ops放在tidy内是个好习惯!
  const y = tf.tensor1d([1.0, 2.0, 3.0, 4.0]);
  const z = tf.ones([4]);

  return y.sub(z).square().mean();
});

average.print() // 输出: 3.5

使用tf.tidy将有助于防止应用程序中的内存泄漏。它也可以用来更谨慎地控制内存何时回收。

两个重要的注意事项

传递给tf.tidy的函数应该是同步的,并且不会返回Promise。我们建议在tf.tidy内不要有更新UI或在发出远程请求的代码。

tf.tidy不会清理变量。变量通常持续到机器学习模型的整个生命周期,因此TensorFlow.js不会清理它们,即使它们是在tidy中创建的。不过,您可以手动调用dispose处理它们。

其他资源

有关Library的全面文档,请参阅TensorFlow.js API参考。

要深入了解机器学习基础知识,请参阅以下资源:

    原文作者:深度智能
    原文地址: https://zhuanlan.zhihu.com/p/35838887
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞