【问题标题】:Load (pretrained) CNTK model using C#使用 C# 加载(预训练的)CNTK 模型
【发布时间】:2017-10-19 12:21:20
【问题描述】:

我正在使用 CNTK.GPU v2.2.0 并使用以下方法保存了一个模型:

model.Save(modelFilePath);

现在我想再次加载它,例如继续训练或只评估样本。我可以看到两种可能的方式。一种方法可行,但不切实际。第二个不行。

  1. 我再次从头开始构建我的神经网络的整个结构,然后在其上调用以下方法:

    model.Restore(modelFilePath);
    

确实,这行得通。

  1. 我使用以下静态方法创建模型:

    Function.Load(modelFilePath, DeviceDescriptor.GPUDevice(0));
    

这不起作用。

在这些操作之后,我只是为模型创建了一个训练器,创建一个 minibatchSource 并尝试以与保存模型之前相同的方式训练模型。

但是对于第二种策略,我得到以下异常:

System.ArgumentOutOfRangeException: 'Values for 1 required arguments 'Input('features', [28 x 28 x 1], [, #])', 请求的输出 'Output('aggregateLoss ', [], []), Output('lossFunction', [1], [, #]), Output('aggregateEvalMetric', [], [])' 依赖,未提供。

[CALL STACK]
    > CNTK::Internal::  UseSparseGradientAggregationInDataParallelSGD
    - CNTK::Function::  Forward
    - CNTK::  CreateTrainer
    - CNTK::Trainer::  TotalNumberOfSamplesSeen
    - CNTK::Trainer::  TrainMinibatch (x2)
    - CSharp_CNTK_Trainer_TrainMinibatch__SWIG_0
    - 00007FFA34AE8967 (SymFromAddr() error: The specified module could not be found.)

它表示尚未提供输入功能。我在训练和从头开始创建模型时使用输入:

var input = CNTKLib.InputVariable(_imageDimension, DataType.Float, _featureName);
var scaledInput = CNTKLib.ElementTimes(Constant.Scalar<float>(0.002953125f, _device), input);
...

所以我想我必须用我为训练创建的模型替换加载模型的输入,并在我从头开始创建模型时使用——尽管输入没有不同。 但我坚持尝试这个,因为我无法检索模型对象的输入,我需要替换它(我认为)。

model.FindByName(inputLayerName);

只是返回 null,虽然我可以清楚地看到该名称与调试器中模型的“输入”列表中的层名称匹配。

因此我不知道如何正确加载保存的模型。我希望有人可以帮助我。

【问题讨论】:

    标签: c# cntk


    【解决方案1】:

    幸运的是,我自己找到了答案。我会在这里发布它,因为可能还有其他 CNTK 初学者,他们可能会偶然发现这个问题,或者一般想知道您如何正确加载模型。

    问题是我没有使用相同的输入对象进行训练和模型创建。换句话说,如果我让我用上面提到的静态方法创建我的模型,我仍然必须确保模型中的对象和用于训练的对象是相同的。这应该可以通过以下方式实现:

    1. 用您自己的输入对象替换加载模型的输入,并将其用于训练。我没有对此进行测试,但它应该可以工作。
    2. 提取加载模型的输入并将其用于训练。我刚刚对此进行了测试,并且可以正常工作。 有我用的代码:

      var labels =
          CNTKLib.InputVariable(new int[] {_classesNumber}, DataType.Float, _labelNa
      
      Variable input;
      Function model;
      if (File.Exists(_modelFile))
      {
          model = Function.Load(_modelFile, DeviceDescriptor.GPUDevice(0));
          input = model.Arguments.Single(a => a.Name == _featureName);
      }
      else
      {
          input = CNTKLib.InputVariable(_imageDimension, DataType.Float, _featureName);
          model = BuildNetwork(input);
      }
      
      var trainer = CreateTrainer(model, labels);
      
      IList<StreamConfiguration> streamConfigurations = new StreamConfiguration[]
      {
          new StreamConfiguration(_featureName, _imageSize), 
          new StreamConfiguration(_labelName, _classesNumber)
      };
      
      var minibatchSource = MinibatchSource.TextFormatMinibatchSource(
          Path.Combine(_ressourceFolder, _trainingDataFile),
          streamConfigurations,
          MinibatchSource.InfinitelyRepeat);
      
      TrainModel(minibatchSource, trainer, labels, input);
      

    一开始我也犯了一个错误,就是使用

    Variable layer model.FindByName(inputLayerName)
    

    虽然我不得不使用

    Variable layer = model.Arguments.Single(a => a.Name == inputLayerName);
    

    【讨论】:

      猜你喜欢
      • 2020-08-16
      • 2017-08-19
      • 2021-04-05
      • 1970-01-01
      • 2021-02-19
      • 2021-01-02
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      相关资源
      最近更新 更多