多头注意中填充顺序的影响(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注意