【问题标题】:Effect of padding sequences in MultiHeadAttention (TensorFlow/Keras)MultiHeadAttention (TensorFlow/Keras) 中填充序列的效果
【发布时间】:2021-07-09 17:23:57
【问题描述】:

我正在尝试使用MultiHeadAttention 层来处理variable-length 元素集,即顺序不重要的序列(否则我会尝试RNNs)。问题是我不确定我是否理解输入序列中填充的效果。我的观点是,包含元素 1 和 2 的序列的输出应该等于相同序列的输出,其中 0 填充到给定长度。换句话说,输入[1, 2][1, 2, 0](甚至[1, 2, 0, 0, 0 ... ] 应该产生关于真实输入的相同输出(1 和 2,我不介意输出 0,因为我知道它是“假”输入到填充)。下面是一段代码,用于显示取决于填充的不同输出。

import tensorflow as tf
import numpy as np

max_tokens = 10  # maximum length of any sequence
dimension = 5  # dimension of the vectors in the embedding

# Variable-length int sequences.
query_input = tf.keras.layers.Input(shape=(None,), dtype='int32')
value_input = tf.keras.layers.Input(shape=(None,), dtype='int32')

handmade_embedding = np.arange(max_tokens).reshape(max_tokens, 1) * np.ones(dimension)

# Embedding lookup.
token_embedding = tf.keras.layers.Embedding(input_dim=max_tokens, output_dim=dimension, mask_zero=True,
                                            embeddings_initializer=tf.constant_initializer(handmade_embedding),
                                            trainable=False)

# Query embeddings of shape [batch_size, Tq, dimension].
query_embeddings = token_embedding(query_input)
# Value embeddings of shape [batch_size, Tv, dimension].
value_embeddings = token_embedding(value_input)

attention_output, weights = \
    tf.keras.layers.MultiHeadAttention(num_heads=10, key_dim=10)(query=query_embeddings,
                                                                 value=value_embeddings,
                                                                 return_attention_scores=True)

model = tf.keras.Model(inputs=[query_input, value_input],
                       outputs=[query_embeddings, attention_output])
names = ('query_embeddings', 'attention_output')

model.summary()

q = np.array([[1, 2, 0]])
prediction = model.predict([q, q])  # self-attention

print('\nWITH PADDING')
for n, v in zip(names, prediction):
    print(f'\n{n}:\n{v}')

q = q[:, :-1]  # remove the padding column in this example
prediction = model.predict([q, q])  # self-attention
print('\nWITHOUT PADDING')
for n, v in zip(names, prediction):
    print(f'\n{n}:\n{v}')

带有填充的MultiHeadAttention层的输出如下:

attention_output:
[[[-0.0374077  -0.03303239 -0.02354158 -0.04111823  0.08189851]
  [-0.04877335 -0.04348412 -0.012391   -0.04778382  0.09745573]
  [-0.02586985 -0.02244503 -0.03482261 -0.03429744  0.06620502]]]

并且没有填充:

attention_output:
[[[-0.04313684 -0.03764199 -0.04799934 -0.05400878  0.10519686]
  [-0.04743624 -0.041591   -0.04378954 -0.05654225  0.11106053]]]

我希望第一个和第二个输出向量是相同的,但事实并非如此。我计划稍后处理这些向量并将它们汇总为单个向量(平均值或其他),但我想要关于填充长度的确定性输出。我误会了什么?

【问题讨论】:

    标签: tensorflow keras padding masking attention-model


    【解决方案1】:

    您必须将attention_mask argument 添加到Multihead_Attention() 通话中。

    【讨论】:

    • 但是attention_mask是一个静态的,固定在层的定义中。但是,在训练过程中,批次会有不同的变长序列......所以我不知道如何使用它。我的意思是,第一批假设的示例可能是[[1, 2, 0, 0, 0], [3, 5, 4, 9, 0], ... [8, 3, 9, 5, 2]],而另一个可能没有填充:[[1, 2, 3, 4, 5] [4, 3, 2, 7, 8] ... [6, 3, 8, 9, 2]] 我想我正在寻找诸如mask_zero 之类的参数来自动丢弃填充向量,即 0's in输入序列。
    • 注意掩码是一个调用参数。所以它在层定义中并不固定。我没有安装每晚构建。所以我不能尝试。但我怀疑它是静态的。您可以使用tf.math.equal(seq, 0) 之类的方式轻松地将输入转换为掩码。但是由于这个附加参数,您需要使用自定义循环(而不是fit()predict()
    • 好的,谢谢,我会在不久的将来尝试,但我需要更多时间来熟悉 TensorFlow 的所有这些内部结构。但是,我希望 MultiHeadAttention 的稳定(不是每晚)版本考虑到参数 mask,例如 LSTM。这对我来说是完美的解决方案。
    • MultiHeadAttention 已经像 LSTM 一样考虑了掩码。我刚刚发现 MultiHeadAttention 已经是稳定版本(但在 tfa 包中):请参阅 tfa.layers.MultiHeadAttention
    【解决方案2】:

    好吧,在我的计算机中放置了几个月的代码后,现在看来甚至不需要 attention_mask。现在输出就是我所期望的,即,对于真实的条目来说是一样的。也许 TensorFlow 的一些内部变化会影响到这一点。我有点疯了……

    【讨论】:

      猜你喜欢
      • 2021-08-20
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多