本文根据理解对原文进行了取舍,并非完全翻译。
原文地址:https://js.tensorflow.org/tutorials/fit-curve.html
目录
目标
使用给定的数据集训练一个模型,去拟合多项式曲线。给定的数据集是某个多项式函数加了噪声后的采样点集,拟合方法是计算多项式各项的系数。
预备知识
熟悉Tensorflow.js基本构建单元(张量、变量、运算)。
输入数据
二维笛卡尔坐标系上的点集。
这些数据点根据一个三次多项式函数(y = ax3 + bx2 + cx + d)生成。
该函数中的四个系数为:a=-0.8,b=-0.2,c=0.9,d=0.5
我们的具体目的就是通过学习来获取最符合这个数据点集的a, b, c, d四个系数的值。
以下是具体操作。
第一步:创建变量并赋初始值
创建四个变量,用于存放a, b, c, d四个系数。
初值随机获取,以后训练的每一步都是对这四个值的优化。
const a = tf.variable(tf.scalar(Math.random()));
const b = tf.variable(tf.scalar(Math.random()));
const c = tf.variable(tf.scalar(Math.random()));
const d = tf.variable(tf.scalar(Math.random()));
第二步:构建模型
这个多项式函数在Tensorflow.js中就是一系列加法、乘法、乘方的链式运算:
function predict(x) {
// y = a * x ^ 3 + b * x ^ 2 + c * x + d
return tf.tidy(() => {
return a.mul(x.pow(tf.scalar(3))) // a * x^3
.add(b.mul(x.square())) // + b * x ^ 2
.add(c.mul(x)) // + c * x
.add(d); // + d
});
}
第三步:训练模型
最后一步,通过训练来获取四个系数的值。
想要训练这个模型,需要先定义三个东西:
- 损失函数,用于衡量拟合的程度。值越小表明拟合程度越好。
- 优化器,根据损失函数的返回值修改系数。目标是最小化损失函数的输出值。
- 训练循环,迭代地运行优化器以最小化损失。
定义损失函数:
这里使用“均方误差”(MSE, mean squared error)作为损失函数。均方误差计算的是数据集中每个真实值与期望值之差的平方的平均值,即先计算每一个“数据集里真实的y值”与“根据数据集里x值预测出的y值”的差的平方,然后取这些值的平均数。
把损失函数写成Tensorflow.js的形式是这样的:
function loss(predictions, labels) {
// 对predicts和labels作差,然后对差值取平方,最后取平均
const meanSquareError = predictions.sub(labels).square().mean();
return meanSquareError;
}
定义优化器:
优化器化器使用了“随机梯度下降”(SGD, Stochastic Gradient Descent)。随机梯度下降是随机获取了数据集中随机点的梯度,根据梯度值来决定增大或减小模型系数的值。
不用担心要做所有数学层面上的操作,因为Tensorflow.js提供了随机梯度下降的函数。tf.trian.sgd的输入是所需要的学习率,返回的是一个SGDOptimizer对象,可以通过调用这个对象来优化损失函数的值。
学习率控制的是。较低的学习率会使学习进度变得更慢(需要更多次的迭代训练,以得到合适的系数);而较高的学习率则会加快学习进度,但可能导致模型围绕正确的结果来回震荡,总会过度校正。
下面的代码根据0.5的学习率构建了一个SGD优化器:
const learningRate = 0.5;
const optimizer = tf.train.sgd(learningRate);
定义训练循环:
迭代执行SGD来优化模型的系数以最小化损失,循环的内容是这样的:
function train(xs, ys, numIterations = 75) {
const learningRate = 0.5;
const optimizer = tf.train.sgd(learningRate);
for (let iter = 0; iter < numIterations; iter++) {
optimizer.minimize(() => {
const predsYs = predict(xs);
return loss(predsYs, ys);
});
}
}
一步步看这段代码。
首先定义输入为数据集中的x和y,以及指定的迭代次数。
然后定义了学习率,以及前面提到的SGD优化器。
最后用for循环了numIterations次。每次循环中调用了optimizer的minimize函数。
minimize这个函数做了两件事情:
- 使用先前在第二步定义的predict模块对所有的x进行预测。
- 返回的是使用先前定义的loss函数对这些预测进行的均方误差计算。
为了最小化loss函数的返回值,minimize会函数自动调整所有这个函数使用的变量(在这里就是a, b, c ,d)。
75次的SGD迭代结束后,a, b, c ,d的值就是由模型学习到的系数值。
查看结果
训练后的系数分别是:a=-0.809, b = 0.214, c = 0.965, d = 0.557