CNTK.GPU 托管 C# 评估 API:System.Runtime.InteropServices.SEHException 调用时 outputVal.CopyVariableValueTo

CNTK.GPU Managed C# Eval API: System.Runtime.InteropServices.SEHException when calling outputVal.CopyVariableValueTo

我训练了一个模型,通过抓取序列中最后一个单词的标签来标记序列:

Sequential([
            Embedding(emb_dim),
            cntk.ops.sequence.last(Recurrence(LSTM(hidden_dim), go_backwards=False)), 
            Dense(num_labels)
        ])

其中 num_labels = 8

我正在使用此处 https://github.com/Microsoft/CNTK/wiki/NuGet-Package 中的 GPU 库来使用来自 C# (CNTK v2.0.beta8.0) 的模型:

Variable outputVar = modelFunc.Outputs.Single(); 
var outputDataMap = new Dictionary<Variable, Value>();
outputDataMap.Add(outputVar, null);
modelFunc.Evaluate(inputDataMap, outputDataMap, device);
Value outputVal = outputDataMap[outputVar];

outputVal 是: 尺寸:计数 = 3 等级:3 总大小:8

而 outputVar 是: 尺寸:计数 = 1 等级:1 总大小:8

以上是否正确?我希望 outputVar 和 outputVal 是相同的 Dimensions/Rank/TotalSize。 另外,如何提取返回的 class ?基本上我应该为 outputData 使用什么 C# 类型?我尝试了 github 示例中的两个嵌套列表,但没有任何运气。 outputVal.CopyVariableValueTo(outputVar, outputData);

谢谢

是的,没错。 Variable 的形状基本上是张量形状,但 Value 对象的形状通常包含 2 个额外的维度:一个是序列轴,另一个是批次轴,因为 Value 对象可以表示一批多个序列,每个序列具有可变长度的样本。每个样本的形状应与变量的形状相同。在你的情况下,输出中似乎只有 1 个样本,因此序列和批长度为 1(你可以检查 outputVal.Shape.Dimensions1 和 [2]),并且 TotalSize 是相同的作为 outputVar.Shape.TotalSize。

要从 Value 中提取数据,您可以使用

outputVal.CopyVariableValueTo(outputVar, outputBuffer);

CopyVariableTo() 将存储在 Value 对象中的数据作为具有可变长度样本的序列列表复制到缓冲区中,采用 denst 格式或 one-hot 矢量格式。 outputVar 表示将数据从此 Value 复制到 outputBuffer 时的形状和动态轴。 outputBuffer 是一个长度可变的序列列表。外部序列列表中包含的项目数是 Value 中的序列数。外部列表的每个元素代表一个序列。由 List 表示的每个序列包含可变数量的样本。每个样本由固定数量的元素组成,类型为 T。样本的元素数量由 sampleVariable 的形状决定。您可以找到有关 API here

的详细信息

您在使用outputVal.CopyVariableValueTo(outputVar, outputData);时遇到了什么样的问题?

谢谢

CopyVariableValueTo 将存储在 Value 对象中的数据复制到提供的缓冲区中,可以是密集格式(缓冲区是 List>)或 one-hot 矢量格式(缓冲区是 List>)。作为输出的 one-hot 矢量格式要求每个样本只有 1 个 non-zero 值。如果输出包含多个 non-zeor 值,则应使用密集输出。有关 API 的更多详细信息是 here

谢谢, 周

CopyVaraibleTo() 有两种变体,一种是使用密集格式输出,另一种是使用 one-hot 矢量格式。对于 one-hot vecotr 格式,CopyVariableValueTo 要求输出中的每个样本只有 1 个 non-zero 值,否则会抛出异常。 Beta 9 具有更好的异常处理,可提供更精确的异常信息。你能试试吗?