什么是tensorflow.jstensorflow.js是一个用于机器学习和机器训练的javascript库,可以运行在浏览器和nodejs上。众所周知在浏览器上用javascript计算是很慢的,而tensorflow.js会通过gpu加速基于WebGL的高性能机器学习模块的计算,让我们的前端开发者可以进行机器学习和在浏览器网络中训练神经网络。本文要讲解的项目代码是根据一些规则模拟数据,然后利用机器学习和训练,根据这些数据反向推断生成这些数据的公式函数。基本概念接下来,我们用五分钟的时间来谈谈tensorflow的基本概念。这部分主要介绍一些概念。笔者将通过一些类比的方式对一些概念进行简单的描述,旨在帮助大家快速理解,但限于篇幅和精力,具体概念的详细定义请读者参考官方文档。张量(tensors)张量其实就是一个数组,可以是一维数组,也可以是多维数组。张量是tensorflow.js中的数据单元。consttensors=tf.tensor([[1.0,2.0,3.0],[10.0,20.0,30.0]]);张量.print();将在浏览器中输出:tensorflow还提供语义张量创建函数:tf.scalar(创建零维张量)、tf.tensor1d(创建一维张量)、tf.tensor2d(创建二维张量)、tf.tensor3d(创建三维张量)、tf.tensor4d(创建四维张量)和tf.ones(张量中的值都为1)或tf.zeros(值在张量中都是0)。Variable(可变)Tensor张量是不可变的,而可变变量是可变的。变量通过张量进行初始化。代码如下:constantInitialValues=tf.zeros([5]);//[0,0,0,0,0]constbiases=tf.variable(initialValues);//通过tensorbiases.print()初始化变量;//Output[0,0,0,0,0]Operations(运算)可以通过TensorsOperators进行运算,比如add(加法)、sub(减法)、mul(乘法)、square(平方)、mean(平均的)。constf=tf.tensor2d([[1.0,2.0],[3.0,4.0]]);constf=tf.tensor2d([[5.0,6.0],[7.0,8.0]]);constee_plus_f=e.add(f);e_plus_f.print();上面例子的输出:内存管理(dispose和tf.tidy)dispose和tf.tidy是用来清空GPU缓存的,相当于我们写js代码的时候,通过给这个变量赋值null来清空缓存。vara={num:1};a=null;//清除缓存disposeTensors和变量可以通过dispose清除GPU缓存:constx=tf.tensor2d([[0.0,2.0],[4.0,6.0]]);constxx_squared=x.square();x.dispose();x_squared.dispose();tf.tidy当有多个tensors和variables的时候,一个一个调用dispose太麻烦了,于是有了tf.tidy,将张量或变量操作放在tf.tidy函数中会自动为我们优化和清除缓存。constaverage=tf.tidy(()=>{consty=tf.tensor1d([4.0,3.0,2.0,1.0]);constz=tf.ones([1]);returny.sub(z);});平均.print()上面例子的输出:模拟数据首先,我们需要模拟一组数据,根据这个三次方程,生成[-1,1],参数a=-0.8,b=-0.2,c=0.9,d=0.5这个区间的一些误差数据,数据可视化如下:假设我们不知道a,b,c,d四个参数的值,我们需要通过这个一堆数据,利用机器学习和机器训练,逆向推导出多项式函数方程及其四个参数值a、b、c、d。设置变量(Setupvariables)因为我们要反向推导多项式方程的a,b,c,d四个参数值,所以首先我们需要定义这四个变量,并给它们赋一些随机数作为初始值。constc=tf.variable(tf.scalar(Math.random()));constb=tf.variable(tf.scalar(Math.random()));constc=tf.variable(tf.scalar(Math.random()));constd=tf.variable(tf.scalar(Math.random()));上面四行代码,tf.scalar创建了一个零维张量,tf.variable是我们的张量转换并初始化成可变变量。如果我们平时用javascript来理解的话,以上四行代码相当于:leta=Math.random();letb=Math.random();letc=Math.random();letd=Math.random();我们给a、b、c、d四个参数赋初始随机值后,a=0.513,b=0.261,c=0.259,d=0.504,我们将这些参数代入方程后得到的曲线如下:我们可以看到根据随机生成的a、b、c、d四个参数生成的数据被并入了多项式,与真实数据模拟出的曲线有很大的不同,这就是我们接下来要做的,通过机器学习和训练,不断调整a、b、c、d这四个参数,让这条曲线尽可能接近实际的数据曲线。创建优化器(Createanoptimizer)constlearningRate=0.5;constoptimizer=tf.train.sgd(learningRate);变量learningRate定义了学习率,在每次机器训练时根据学习率计算Offset调整范围,学习率越低预测值越靠后越准确,但是响应会增加运行时间和计算量程序的数量。学习率高会加快学习过程,但由于偏移过大,容易造成围绕正确值的波动,导致计算结果不准确。tf.train.sgd是我们在tensorflow.js中为我们选择封装的SGD优化器,也就是随机梯度下降法。在机器学习算法中,通常使用梯度下降法来训练我们的算法。梯度下降法常用的有三种形式:BGD、SGD和MBGD。我们使用SGD的batchgradientdescent方法,因为每次梯度下降更新一个训练参数,机器训练的速度会随着样本数的增加而变得很慢。随机梯度下降被提出来解决这个问题。假设一般线性回归函数的作用是:SGD利用每个样本的损失函数计算θ的偏导数得到对应的梯度来更新θ:随机梯度下降对每个样本迭代更新一次,相比batchabove梯度下降要求所有训练样本都用于一次迭代。SGD迭代次数大,在解空间的搜索过程显得盲目。但总的来说,它正在朝着更好的价值发展。随机梯度下降收敛图如下:期望函数模型(trainingprocessfunctions)写期望函数模型,其实就是用一系列的操作来描述我们的函数模型functionpredict(x){//y=a*x^3+b*x^2+c*x+dreturntf.tidy(()=>{returna.mul(x.pow(tf.scalar(3,'int32'))).add(b.mul(x.square())).add(c.mul(x)).add(d);});}a.mul(x.pow(tf.scalar(3,'int32')))描述ax^3(a乘以x的立方),b.mul(x.square()))描述的是bx^2(b乘以x的平方),c.mul(x)同理。注意predict函数返回时用tf.tidy包裹,这是为了方便内存管理,优化机器训练过程的内存。定义损失函数(loss)接下来我们需要定义一个损失函数,使用MSE(meansquarederror,均方误差)。数理统计中的均方误差是指参数的估计值与参数真实值之差的平方的期望值,记为MSE。MSE是一种更方便的衡量“平均误差”的方法。MSE可以评估数据变化的程度。MSE的值越小,说明预测模型描述实验数据的准确性越好。MSE的计算很简单,就是先根据给定的x求出实际y值与预测y值的差值的平方,然后计算这些差值的平方的平均值。根据以上,我们的损失函数代码如下:functionloss(prediction,labels){consterror=prediction.sub(labels).square().mean();returnerror;}期望值预测减去实际值labels,然后平方然后求平均值。机器训练(training)好了,上面说了这么多,铺垫和准备也做了这么多,终于到了最关键的一步了。下面的代码和函数是真正根据数据进行计算,然后通过机器学习和训练得到的。获得预期结果的最重要步骤。我们定义了基于SGD随机梯度下降的optimizer优化器,然后定义了基于MSE均方误差的损失函数。我们应该如何结合这两种设备进行机器训练和机器学习?请参阅下面的代码。constnumIterations=75;asyncfunctiontrain(xs,ys,numIterations){for(letiter=0;iter
