Tensorflow.js是一个开源的、使用WebGL加速的机器智能JavaScript库。它允许你在浏览器里训练神经网络或者在推断模式下执行预先训练好的模型。
Tensorflow.js里最重要的数据单元就是Tensors。它是被塑造成一维或多维数组形式的一系列数字。一个张量有一个shape属性,是它决定了张量的构造。(每个维度里有多少个数字)
张量主要的构造器就是tf.tensor函数
//2x3 张量,可理解为2维数组,每个数组3个数字
const shape = [2,3];
const a = tf.tensor([1.0, 2.0, 3.0, 10.0, 20.0, 30.0], shape);
a.print()
//结果是:[[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]
//shape属性也可以这样隐式指定
const b = tf.tensor([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
//结果是:[[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]
然而,如果要创建低阶的张量,我们可以使用下列的方法来创建来提高代码的可阅读性:
const c = tf.tensor2d([[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]);
c.print()
//结果是:[[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]]
Tensorflow.js也提供了一些方便的方法来创建全是0(tf.zeros)或者全是1(tf.ones)的张量
//传入一个shape属性,即为一个三维数组,每个数组长度为5,且每个元素都为0
const zeros = tf.zeros([3, 5]);
//结果是:[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
在Tensorflow.js里,张量一旦被建立是不可更改的。但是你可以在张量上执行一些操作来产生新的张量。
变量使用一个张量来初始化。不像张量,变量是可以被更改的。你可以使用assign方法给一个已经存在的变量指定一个新的张量。
const initialValues = tf.zeros([5]);
const biases = tf.variable(initialValues);
biases.print();
//结果是:[0, 0, 0, 0, 0]
const updatedValues = tf.tensor1d([0, 1, 0, 1, 0]);
biases.assign(updatedValues);
biases.print();
//结果是:[0, 1, 0, 1, 0]
变量主要被用来在模型训练时存储和更新数值。
张量允许你存储数据,操作允许你操纵这些数据。Tensorflow.js提供了许多种适合于线性代数和机器学习的操作,它们可以对张量进行操作。因为张量是不可更改的,所以这些操作不会改变它们的值,而是返回一个新的张量。
可用的操作有一元操作,例如square:
const d = tf.tensor2d([[1.0, 2.0], [3.0, 4.0]]);
const d_square = d.square();
d_square.print();
//结果是:[[1, 4], [9, 16]]
还有二元操作,例如add, sub和mul:
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,例如:
const sq_sum = e.add(f).square();
sq_sum.print();
//结果是:[[36, 64], [100, 144]]
概念上,一个模型就是一个你给出一些指定的输入便会产生一些期望中的输出的函数。
在TensorFlow.js中,有两种方法可以创建模型。一种是使用操作来直接描述模型中的流程,例如:
function predict(input){
//计算y=ax^2+bx+c
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
});
}
//定义常量a,b,c
const a = tf.scalar(2);
const b = tf.scalar(4);
const c = tf.scalar(8);
const result = predict(2);
result.print();
你还可以使用高级的API tf.model 来创建一个由层组成的模型,这是一种在深度学习里很流行的抽象,例如:
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.simpleRNN, tf,layers.gru和tf.layers.lstm。
因为TensorFlow.js使用GPU来加速数学运算,所以在使用张量和变量进行运算的时候管理显存是有必要的。
TensorFlow.js提供了两种方法来处理这个问题:dispose和tf.tidy
我们可以在张量或者变量上使用dispose方法来清除它并释放它所占用的显存。例如:
const x = tf.tensor2d([[0.0, 2.0], [4.0, 6.0]]);
const x_squared = x.square();
x.dispose();
x_squared.dispose();
在执行大量的张量操作时使用dispose方法未免有限繁琐。TensorFlow.js还提供了另外一个方法 tf.tidy。若没有基于GPU的张量,那么它跟JavaScript中常规的作用域一致。
tf.tidy执行一个函数并清除函数执行过程中产生所有中间张量且释放它们所占有的显存。它并不会清除返回值。
const average = tf.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可以帮助防止应用的内存溢出。
两条重要的提示: