多头注意中填充顺序的影响(TensorFlow/Keras)

多头注意中填充顺序的影响(TensorFlow/Keras),tensorflow,keras,padding,masking,attention-model,Tensorflow,Keras,Padding,Masking,Attention Model,我正在尝试使用MultiHeadAttention层来处理可变长度元素集,即顺序不重要的序列(否则我将尝试RNNs)。问题是我不确定我是否理解输入序列中填充的效果。我的观点是,包含元素1和2的序列的输出应该等于相同序列的输出,0的填充长度为给定长度。换句话说,输入[1,2]和[1,2,0](或者甚至[1,2,0,0…]应该产生关于真实输入的相同输出(1和2,我不介意0的输出,因为我知道这是对pad的“假”输入).下面是一段代码,用于根据填充显示不同的输出 import tensorflow as

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

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

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

您必须将
注意遮罩参数添加到
多头注意()
调用。

您必须将
注意遮罩参数添加到
多头注意()
call.

但是
注意遮罩是一个静态的,固定在图层的定义中。但是,在训练期间,批次将具有不同的可变长度序列…因此我不知道如何使用它。我的意思是,第一个假设的示例批次可能是
[[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\u zero
来自动丢弃填充向量,即输入序列中的0。注意掩码是一个调用参数。因此它在层定义中不是固定的。我没有安装夜间构建。因此我无法尝试。但我怀疑它是静态的。你可以轻松地转换你的r使用类似于
tf.math.equal(seq,0)
的东西来屏蔽输入。但是您需要使用自定义循环(而不是
fit()
predict()
),因为这个额外的参数好的,谢谢,我将在不久的将来尝试,但我需要更多的时间来熟悉TensorFlow的所有内部结构。不过,我希望稳定(不是每晚)版本的MultiHeadAttention会像LSTM一样考虑一个参数
mask
。这对我来说是完美的解决方案。MultiHeadAttention已经像LSTM一样考虑了mask。我刚刚发现MultiHeadAttention已经在稳定版本中(但在tfa包中):请参见tfa.layers.multiheadAttention,但是
注意\u掩码是静态的,在层的定义中是固定的。但是,在培训期间,批次将具有不同的可变长度序列…因此我不知道如何使用它。我的意思是,第一个假设批次的示例可能是
[[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\u zero
来自动丢弃填充向量,即输入序列中的0。注意掩码是一个调用参数。因此它在层定义中不是固定的。我没有安装夜间构建。因此我无法尝试。但我怀疑它是静态的。你可以轻松地转换你的r使用类似于
tf.math.equal(seq,0)
的东西来屏蔽输入。但是您需要使用自定义循环(而不是
fit()
predict()
),因为这个额外的参数好的,谢谢,我将在不久的将来尝试,但我需要更多的时间来熟悉TensorFlow的所有内部结构。不过,我希望稳定(不是每晚)版本的MultiHeadAttention会像LSTM一样考虑一个参数
mask
。这对我来说是完美的解决方案。MultiHeadAttention已经像LSTM一样考虑了mask。我刚刚发现MultiHeadAttention已经在稳定版本中(但在tfa包中):参见tfa.layers.multihead注意