在 CNTK 中实现带有注意力的 Seq2Seq 时轴的多个问题

Multiple issues with axes while implementing a Seq2Seq with attention in CNTK

我正在尝试在 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 Tutorial 并使用 cntk.logging.plot 将其图形转储到 .dot 文件时,我看到它的输入形状是 [#](-2,)。这怎么可能?

问题 2: 在同一个教程中,我们有 attention_axis = -3。我不明白这一点。在我的模型中有 2 个动态轴和 1 个静态轴,因此 "third to last" 轴将是 #,批处理轴。但是绝对不应该在批处理轴上计算注意力。
我希望查看教程代码中的实际坐标轴可以帮助我理解这一点,但上面的 [#](-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 是解码器中最后 Dense 层之前的 Stabilizer。我可以在点文件中看到,在 AttentionModel 实现的中间出现了大小为 1 的虚假尾随维度。

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]'.

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

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

感谢您的解释!

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

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

关于您的问题:

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

attention_axis 是本应隐藏的实现细节。基本上 attention_axis=-3 将创建 (1, 1, 200) 的形状,attention_axis=-4 将创建 (1, 1, 1, 200) 的形状,依此类推。一般来说,任何超过 -3 的值都不能保证有效,任何小于 -3 的值只会增加更多的 1,而没有任何明显的好处。当然,好消息是你可以在最新的 master 中忽略这个参数。

TL;DR: 如果你在 master 中(或几天后开始使用 CNTK 2.2),请将 AttentionModel(attention_dim, attention_span=200, attention_axis=-3) 替换为 AttentionModel(attention_dim)。它更快并且不包含令人困惑的参数。从 CNTK 2.2 开始,原来的 API 已弃用。