一、关于TensorFlow.js
作为深度学习界的当红炸子鸡——TensorFlow 开源组织终于在 2018 年 3 月推出了首个 JavaScript 版本。TensorFlow.js 可以在浏览器端完成模型训练、执行和再训练等基本任务,并且借助 WebGL 技术,可以和 Python、C++ 版本一样能够通过 GPU 硬件加速完成计算过程。
二、基本概念
1.算法模型
y = f(x)
上述公式中,x是输入项,y是输出项,而f(x)就是模型的核心函数。需要注意的是这里的输入和输出通常都是张量而不是标量。
例如:
y = w1 * obstacleX + w2 * obstacleWidth + b
其中obstacleX和obstacleWidth是输入项, w1、w2为输入项的权重,b是偏移量
2.训练
通过已知输入项 obstacleX 、obstacleWidth和输出项 y 来调节模型中 w1、w2 和 b 参数直到“最佳效果”的过程,被称为训练(train)过程,而 y 因为是已知的输出项,又被称为标签(label),多组输入项(obstacleX 、obstacleWidth)和 输出项(y) 在一起被称为训练数据集(training data set)。训练通常需要反复执行很多次,才能达到“最佳效果”。
3.预测
机器学习中,已知输入项 x 和模型求 y 时,被称为预测(predict)过程。
4.评价
在训练过程中,将训练数据集中的 x 作为输入项,执行预测过程,将预测结果与标签 y 的实际结果进行对比,并通过一个函数得到一个分值用以表示当前模型的拟合能力,被称为评价(evaluatie)过程,这个函数被称为评价函数或损失函数(loss function)。
机器学习就是一个不断训练、评价迭代的模型训练过程,训练得越好,则未来预测得越准确。
5.张量
张量是TensorFlow.js中的最重要的数据单元,它是一个形状为一维或多维数组组成的数值的集合。tf.Tensor
和多维数组其实非常的相似。
标量 : 有些物理量,只有数值大小,没有方向,这种即称为标量,也可称做零阶张量。
向量(矢量 vector): 具有大小和方向的量,也可称做一阶张量
张量(tensor):我们的目的是要用数学量来表示物理量,可是标量加上向量,都不足以表达所有的物理量,所以就需要扩大数学量的概念,张量就出现了。
张量包含如下属性:
- rank: 张量的维度(张量的维数被描述为阶或者秩),例如纯量就是0阶,向量为1阶,矩阵为2阶。
- shape: 每个维度的数据大小
const a = tf.tensor([[1, 2], [3, 4]]);
console.log('a shape:', a.shape);
a.print();
const b = a.reshape([4, 1]);
console.log('b shape:', b.shape);
b.print();
//a shape: 2,2
//Tensor
// [[1, 2],
// [3, 4]]
//b shape: 4,1
//Tensor
// [[1],
// [2],
// [3],
// [4]]
- dtype: 张量中的数据类型,在默认的情况下,
tf.Tensor
的数据类型也就是dtype
为32位浮点型(float32
)。当然tf.Tensor
也可以被创建为以下数据类型:布尔(bool
), 32位整型(int32
), 64位复数(complex64
), 和字符串(string
)
三、TensorFlow.js API
1.初始化创建一个张量
tf.tensor(values,shape?,dtype?)
tf.tensor([1, 2, 3, 4]).print();
//Tensor [1, 2, 3, 4]
tf.tensor([[1, 2], [3, 4]]).print();
//Tensor [[1, 2], [3, 4]]
tf.tensor([1, 2, 3, 4], [2, 2]).print();
//Tensor[[1, 2],[3, 4]]
//其中dtype 为('float32'|'int32'|'bool'|'complex64'|'string')
tf.scalar(value, dtype?)创建零阶张量
tf.scalar(3.14).print();
//Tensor 3.140000104904175
tf.buffer(shape,dtype?,values?)
const buffer = tf.buffer([2, 2]);
buffer.set(3, 0, 0);
buffer.set(5, 1, 0);
buffer.toTensor().print();
//张量[[3,0],[5,0]]
tf.clone(x)
//创建一个具有与指定张量相同的值和形状的新张量。
const x = tf.tensor([1, 2]);
x.clone().print();
//张量[1,2]
tf.complex(real,imag)
//给定一个real表示复数的实部的张量和一个imag表示复数的虚部的张量,此操作将以[r0,i0,r1,i1]的形式逐元素返回复数,其中r表示实部,i代表imag的一部分。
const real = tf.tensor1d([2.25, 3.25]);
const imag = tf.tensor1d([4.75, 5.75]);
const complex = tf.complex(real, imag);
complex.print();
//张量[2.25 + 4.75j,3.25 + 5.75j]
tf.fill(shape,values,dtype?)
//创建一个用标量值填充的张量
tf.fill([2, 2], 4).print();
//张量[[4,4],[4,4]]
tf.imag(x)
//返回复数(或实数)张量的虚部。
const x = tf.complex([-2.25, 3.25], [4.75, 5.75]);
tf.imag(x).print();
Tensor [4.75, 5.75]
tf.linspace(start,stop,num)
//在给定的间隔内返回均匀间隔的数字序列。
// start (数字) 序列的起始值。
// stop (数字) 序列的结束值。
// num (数字) 要生成的值的数目。
tf.linspace(0, 9, 10).print();
//张量[0、1、2、3、4、5、6、7、8、9]
tf.real(x)
//返回复数(或实数)张量的实部。
const x = tf.complex([-2.25, 3.25], [4.75, 5.75]);
tf.real(x).print();
//张量[-2.25,3.25]
tf.variable(initialValue,trainable?,name?,dtype?)
//用提供的初始值创建一个新变量。
// initialValue:张量的初始值
// trainable: 如果为true,则允许优化器对其进行更新。
// name:变量的名称
const x = tf.variable(tf.tensor([1, 2, 3]));
x.assign(tf.tensor([4, 5, 6]));
x.print();
//张量[4,5,6]
2.修改张量的形状
张量中的元素数量是这个张量的形状的乘积(例如一个形状为[2,3]的张量所含有的元素个数为2*3=6个)
tf.reshape(x,shape)
//给定输入张量,返回一个新的张量
const x = tf.tensor1d([1, 2, 3, 4]);
x.reshape([2, 2]).print();
//张量[[1,2],[3,4]]
3. 操作张量
tf.square()
const x = tf.tensor([1, 2, 3, 4]);
const y = x.square(); // 相当于 tf.square(x)
y.print();
tf,add()
const a = tf.tensor([1, 2, 3, 4]);
const b = tf.tensor([10, 20, 30, 40]);
const y = a.add(b); // 相当于 tf.add(a, b)
y.print();
因为张量是不可变的,所以这些运算并不会更改他们的值。相应的这些操作总会返回一个新的张量。
tf.slice(x,begin,size?)
//x:要切片的输入张量
//begin:起始切片的坐标
//size:切片的大小
4.内存操作
tf.dispose()
const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose(); // 相当于 tf.dispose(a)
参考资料
怎么通俗地理解张量?
tensorflow.js实战