[译]来自p1-jj.byteimg.com/tos-cn-i-t2…
这篇文章解释了如何使用TensorFlow.js在浏览器中运行机器学习。 它涵盖了用于模型训练,传递学习和预测功能的TensorFlow.js API。这里呈现了一个APP demo, 它有助于预测业务报告执行的等待时间。
我已经实现了一个包含TensorFlow.js API使用情况的APP。 首先,我将向您介绍其功能,然后深入探讨实现细节。 该APP实现了业务报告执行时间预测用例(在JavaScript中),在我之前的文章《使用Keras和TensorFlow进行报告时间执行预测》中对此进行了解释。 对于模型训练,我使用了50个epochs (数据以10个为批处理),学习率设置为0.001。 神经网络基于两个处理层和一个输出层。 模型训练过程在浏览器中运行:
APP部署并在此处实时可用: regressiontfjs-node.herokuapp.com/训练模型可以预测业务报告执行的预期等待时间。实现是基于这本书中的解释和资料完成的-《使用JavaScript进行深度学习》和多元回归示例-《Boston Housing》。
功能性
首次打开APP时,需要对模型进行训练。训练模型后,它将被保存到本地indexeddb
。重新打开浏览器后,该模型将从indexeddb
中保持可用,您可以选择要重用它或训练新模型(以前保存的模型将被替换)。
训练过程完成后,它将打印一组显示模型情况的参数:
- Baseline loss(基线损失):这是根据训练数据计算出的平均平方误差。平方根值:237秒。这意味着,如果我们始终假设预测的平均值,则错误范围将为237秒。
- Average time(平均时间):为训练数据计算的平均时间
- Final train-set loss(最终训练设定损失):训练期间计算出的损失
- Final validation-set loss(最终验证集损失):通过验证训练期间计算出的损失
- Test-set loss(测试集损失):针对训练数据针对训练数据计算出的损失
- Prediction off by (sec)(预测偏差(秒)):测试集损失的平方根值。这表明模型出错能力。此模型训练得很好,只有4.5秒的错误,比基线损失要好
实操
APP结构非常简单。 所有逻辑均在appController.js
中实现。 UI
在index.html
中实现。 Web应用程序是通过Oracle JavaScript
库— Oracle JET
实现的。 要在本地运行该应用程序,请执行以下两个步骤:
- 使用NPM安装
Oracle JET
:npm install -g @ oracle / ojet-cli
- 进入应用程序并运行:
ojet restore
- 运行应用程序:
ojet服务
appController.js
中定义了一个侦听器。 加载应用程序时,将调用此侦听器,并负责加载数据,将其转换为张量并计算基线。
数据通过帮助程序模块data.js
加载。 我正在使用Papaparse
库来解析CSV
。 原始数据集基于四列:
var features = results['data'].map(report => ({
report_params: parseFloat(report.report_params),
report_1: parseFloat(report.report_id) === 1 ? 1 : 0,
report_2: parseFloat(report.report_id) === 2 ? 1 : 0,
report_3: parseFloat(report.report_id) === 3 ? 1 : 0,
report_4: parseFloat(report.report_id) === 4 ? 1 : 0,
report_5: parseFloat(report.report_id) === 5 ? 1 : 0,
day_morning: parseFloat(report.day_part) === 1 ? 1 : 0,
day_midday: parseFloat(report.day_part) === 2 ? 1 : 0,
day_afternoon: parseFloat(report.day_part) === 3 ? 1 : 0,
}));
这种数据转换有助于进行更精确的训练。 我正在使用1200行数据进行训练,并使用300行数据进行测试。 在将数据拆分为训练数据集和测试数据集之前,请确保先对其进行混洗。 我正在使用helper
方法,该方法取自Boston Housing
APP。
使用TensorFlow.js
函数tensor2d
将数据数组转换为张量:
tensors.rawTrainFeatures = tf.tensor2d(dataHelper.trainFeatures);
tensors.trainTarget = tf.tensor2d(dataHelper.trainTarget);
tensors.rawTestFeatures = tf.tensor2d(dataHelper.testFeatures);
tensors.testTarget = tf.tensor2d(dataHelper.testTarget);
TensorFlow.js
模型由两个处理层和一个输出层构成,以返回预测值:
const model = tf.sequential();
model.add(tf.layers.dense({
inputShape: [dataHelper.trainFeatures[0].length],
units: 25,
activation: 'sigmoid',
kernelInitializer: 'leCunNormal'
}));
model.add(tf.layers.dense({
units: 25,
activation: 'sigmoid',
kernelInitializer: 'leCunNormal'
}));
model.add(tf.layers.dense({ units: 1 }));
构建模型后,对其进行编译并运行拟合函数以训练模型。 我建议使用验证拆分选项,这样在训练过程中它将验证训练的质量
model.compile({ optimizer: tf.train.sgd(LEARNING_RATE), loss: 'meanSquaredError' });
await model.fit(tensors.trainFeatures, tensors.trainTarget, {
batchSize: BATCH_SIZE,
epochs: NUM_EPOCHS,
shuffle: true,
validationSplit: 0.2,
callbacks: {
onEpochEnd: async (epoch, logs) => {
函数拟合提供onEpochEnd
回调,我们可以在其中记录训练进度并将数据推送到UI。
训练完成后,通过针对测试数据运行模型来评估模型。 从返回的数字中取平方根,这将基于当前模型训练在几秒钟内被容忍的错误(如果结果不能容忍,请尝试通过更改神经网络层的结构来重新训练模型,并尝试调整训练参数):
result = model.evaluate(tensors.testFeatures, tensors.testTarget, { batchSize: BATCH_SIZE });
testLoss = result.dataSync()[0];
最后保存模型。 有多个保存模型的选项,您甚至可以将其推送到服务器。 在此示例中,我将模型保存在浏览器本地的indexeddb
中:
await model.save('indexeddb://report-exec-time-model');
训练模型后,我们可以运行预测功能。 我正在从indexeddb
中的保存状态加载模型,构造输入张量并执行TensorFlow.js
预测:
model = await tf.loadLayersModel('indexeddb://report-exec-time-model');
input = [{
report_id: parseFloat(self.reportIdP()),
report_params: self.reportParamsP(),
day_part: parseFloat(self.reportExecSlotP())
}];
convertInputToTensor(input);
res = model.predict(tensors.inputFeatures);
score = res.dataSync()[0];
最后一步——转移学习,使用附加数据对现有模型进行再训练(在这种情况下,数据形状相同,我们为新目标进行训练)。 为了使重新训练更有效率,我们必须冻结原始模型中的部分图层。 这样,先前训练的模型权重将不会受到影响,并且模型训练将运行得更快。 通常,您应该使用多个新元素进行培训,在这种情况下,出于简单原因,我会使用一个新条目进行培训。 可以通过将可训练属性设置为false来冻结模型层:
model = await tf.loadLayersModel('indexeddb://report-exec-time-model');
model.layers[0].trainable = false;
model.compile({
loss: 'meanSquaredError',
optimizer: tf.train.sgd(LEARNING_RATE)
});
model.summary();
input = [{
report_id: parseFloat(self.reportId()),
report_params: self.reportParams(),
day_part: parseFloat(self.reportExecSlot()),
exec_time: self.reportExecTime()
}];
convertInputToTensor(input, 'Y');
在现有模型之上使用新数据运行函数拟合:
await model.fit(tensors.inputFeatures, tensors.inputTarget, {
batchSize: BATCH_SIZE,
epochs: NUM_EPOCHS,
shuffle: true,
callbacks: {
onEpochEnd: async (epoch, logs) => {