2

我正在尝试在 CNTK 中实现一个带有注意力的 Seq2Seq 模型,这与CNTK Tutorial 204非常相似。但是,几个小的差异会导致各种问题和错误消息,我不明白。这里有很多问题,它们可能是相互关联的,并且都源于我不明白的某件事。

注意(如果它很重要)。我的输入数据来自MinibatchSourceFromData,由适合 RAM 的 NumPy 数组创建,我不将其存储在 CTF 中。

ins = C.sequence.input_variable(input_dim, name="in", sequence_axis=inAxis)
y = C.sequence.input_variable(label_dim, name="y", sequence_axis=outAxis)

因此,形状是[#, *](input_dim)[#, *](label_dim)

问题 1:当我运行CNTK 204 教程并使用 将其图形转储到.dot文件中cntk.logging.plot时,我看到它的输入形状是[#](-2,). 这怎么可能?

  • 序列轴(*)在哪里消失了?
  • 维度怎么可能是负数?

问题 2:在同一个教程中,我们有attention_axis = -3. 我不明白这一点。在我的模型中,有 2 个动态轴和 1 个静态轴,因此“倒数第三个”轴将是#批处理轴。但是绝对不应该在批处理轴上计算注意力。
我希望查看教程代码中的实际坐标轴可以帮助我理解这一点,但[#](-2,)上面的问题使这更加混乱。

设置attention_axis-2会出现以下错误:

RuntimeError: Times: The left operand 'Placeholder('stab_result', [#, outAxis], [128])'
              rank (1) must be >= #axes (2) being reduced over.

在创建训练时间模型期间:

def train_model(m):
    @C.Function
    def model(ins: InputSequence[Tensor[input_dim]],                  
              labels: OutputSequence[Tensor[label_dim]]):
        past_labels = Delay(initial_state=C.Constant(seq_start_encoding))(labels)
        return m(ins, past_labels)  #<<<<<<<<<<<<<< HERE
    return model

其中stab_result是解码器Stabilizer最后一层之前的右边。Dense我可以在点文件中看到,在实现的中间出现了大小为 1 的虚假尾随维度AttentionModel

设置attention_axis-1会出现以下错误:

RuntimeError: Binary elementwise operation ElementTimes: Left operand 'Output('Block346442_Output_0', [#, outAxis], [64])'
              shape '[64]' is not compatible with right operand 
              'Output('attention_weights', [#, outAxis], [200])' shape '[200]'.

其中 64 是 my attention_dim, 200 是 my attention_span。据我了解,*注意模型中的 elementwise 绝对不应该将这两者混为一谈,因此-1这里绝对不是正确的轴。

问题3:我上面的理解正确吗?什么应该是右轴,为什么它会导致上述两个异常之一?

感谢您的解释!

4

1 回答 1

3

首先,有一个好消息:在最新的 master 中,AttentionModel 中修复了一些问题(几天后将在 CNTK 2.2 中普遍可用):

  • 您无需指定 anattention_spanattention_axis. 如果您不指定它们并将它们保留为默认值,则会在整个序列上计算注意力。事实上,这些论点已被弃用。
  • 如果您执行上述操作,204 笔记本的运行速度会快 2 倍,因此 204 笔记本不再使用这些参数
  • AttentionModel 中的一个错误已得到修复,它现在忠实地实现了 Bahdanau 等。人。纸。

关于你的问题:

维度不是负数。我们在不同的地方使用某些负数来表示某些事情:-1 是根据第一个 minibatch 推断一次的维度,-2 是我认为占位符的形状,-3 是将推断的维度每个小批量(例如当您将可变大小的图像输入卷积时)。我认为如果您在第一个 minibatch 之后打印图表,您应该会看到所有形状都是具体的。

attention_axis是一个应该被隐藏的实现细节。基本上attention_axis=-3会创建一个 (1, 1, 200)attention_axis=-4的形状,将创建一个 (1, 1, 1, 200) 的形状等等。一般来说,任何大于 -3 的东西都不能保证工作,小于 -3 的东西只会增加更多的 1,没有任何明显的好处。好消息当然是你可以在最新的大师中忽略这个论点。

TL;DR:如果您是 master(或几天后从 CNTK 2.2 开始),请替换AttentionModel(attention_dim, attention_span=200, attention_axis=-3)AttentionModel(attention_dim). 它更快,并且不包含令人困惑的论点。从 CNTK 2.2 开始,不推荐使用原始 API。

于 2017-09-13T00:02:32.293 回答