MultiHeadAttention 中填充序列的效果 (TensorFlow/Keras)
Effect of padding sequences in MultiHeadAttention (TensorFlow/Keras)
我正在尝试使用 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]]]
我希望第一个和第二个输出向量相同,但事实并非如此。我计划稍后处理这些向量并将它们汇总为单个向量(平均值或其他),但我想要关于填充长度的确定性输出。我误会了什么?
您必须将 attention_mask argument
添加到 Multihead_Attention()
调用。
好吧,在我的计算机中放置了几个月的代码之后,现在似乎甚至不需要 attention_mask。现在输出是我期望的原因,即与真实条目相同。可能 TensorFlow 的一些内部变化影响了这一点。我有点疯狂...
我正在尝试使用 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]]]
我希望第一个和第二个输出向量相同,但事实并非如此。我计划稍后处理这些向量并将它们汇总为单个向量(平均值或其他),但我想要关于填充长度的确定性输出。我误会了什么?
您必须将 attention_mask argument
添加到 Multihead_Attention()
调用。
好吧,在我的计算机中放置了几个月的代码之后,现在似乎甚至不需要 attention_mask。现在输出是我期望的原因,即与真实条目相同。可能 TensorFlow 的一些内部变化影响了这一点。我有点疯狂...