【问题标题】:TensorFlow.js: Saving different model instances during trainingTensorFlow.js:在训练期间保存不同的模型实例
【发布时间】:2019-06-30 12:54:23
【问题描述】:

我在 NODE 上运行 TensorFlow.JS,我希望能够在训练过程中的某个时间点保存模型。

我尝试将实际模型复制到全局变量,但 JavaScript 对象是通过引用复制的,最后全局变量具有与上一个训练时期相同的模型。

然后我使用许多不同的 JavaScript 方法进行深度克隆(包括 lodash 深度克隆),但我在复制的模型上遇到错误,例如最终丢失的函数(例如 model.evaluate)。

我想知道我可以保存某个检查点的唯一方法是直接使用 model.save() 还是有任何其他方法可以将模型对象复制(按值而不是引用)到全局或类属性。

非常感谢!

** 更新 **

目前对我来说最好的解决方案是创建模型的副本:

  const copyModel = (model) => {
    const copy = tf.sequential();
    model.layers.forEach(layer => {
      copy.add(layer);
    });
    copy.compile({ loss: model.loss, optimizer: model.optimizer });
    return copy;
  }
  • 请考虑您可能需要将一些其他设置从原始模型复制到新模型(副本)。

【问题讨论】:

  • 能否请您出示代码?

标签: neural-network tensorflow.js


【解决方案1】:

tf.Model 对象包含权重值,通常存在于 GPU 上 (作为 WebGL 纹理)并且不容易克隆。所以这不是一个好主意 克隆一个tf.Model 对象。您应该将其序列化并将其保存在某处。 有两种选择:

  1. 如果你在Node.js,你应该有比较充足的存储空间。只是 使用Model.save() 将模型“快照”到磁盘上,可以加载回来 稍后。
  2. 如果您不想通过文件系统,您可以在内存中进行序列化和反序列化。使用方法tf.io.withSaveHandlertf.io.fromMemory()。请参见下面的示例:
const tf = require('@tensorflow/tfjs');
require('@tensorflow/tfjs-node');

(async function main() {
  const model = tf.sequential();
  model.add(tf.layers.dense({units: 1, inputShape: [3], useBias: false}));
  model.compile({loss: 'meanSquaredError', optimizer: 'sgd'});

  const xs = tf.randomUniform([4, 3]);
  const ys = tf.randomUniform([4, 1]);

  const artifactsArray = [];

  // First save, before training.
  await model.save(tf.io.withSaveHandler(artifacts => {
    artifactsArray.push(artifacts);
  }));

  // First load.
  const model2 = await tf.loadModel(tf.io.fromMemory(
      artifactsArray[0].modelTopology, artifactsArray[0].weightSpecs,
      artifactsArray[0].weightData));

  // Do some training.
  await model.fit(xs, ys, {epochs: 5});

  // Second save, before training.
  await model.save(tf.io.withSaveHandler(artifacts => {
    artifactsArray.push(artifacts);
  }));

  // Second load.
  const model3 = await tf.loadModel(tf.io.fromMemory(
      artifactsArray[1].modelTopology, artifactsArray[1].weightSpecs,
      artifactsArray[1].weightData));

  // The two loaded models should have different weight values.
  model2.getWeights()[0].print();
  model3.getWeights()[0].print();
})();

【讨论】:

  • 这个解决方案完美,感谢@scai !能够将检查点保存在内存中是我的需要。
  • 虽然这行得通,但我发现当运行像 evaluate 这样的模型方法时,我收到以下错误:“错误:模型需要在使用前进行编译。”我用我自己的代码以及你使用model2和model3的例子对此进行了测试。 TensorFlow.JS API 说:“损失和指标是在 compile() 期间指定的,这需要在调用 evaluate() 之前发生。”也许某些模型配置没有通过这种方法转移?再次感谢!
  • 对。保存的模型工件当前不包括损失和优化器信息。加载模型后可以再次调用compile吗?
  • 保存后为什么需要加载?保存然后继续训练肯定会更有效率吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 1970-01-01
相关资源
最近更新 更多