我正在使用tensorflow.keras
制作一个转换器,并且在理解attention_mask
如何为MultiHeadAttention
层工作时遇到了问题。
我的输入是三维数据。例如,假设我的整个数据集有10个元素,每个元素的长度不超过4个:
# whole data
[
# first item
[
[ 1, 2, 3],
[ 1, 2, 3],
[np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan],
],
# second item
[
[ 1, 2, 3],
[ 5, 8, 2],
[ 3, 7, 8],
[ 4, 6, 2],
],
... # 8 more items
]
所以,我的面具看起来是这样的:
# assume this is a numpy array
mask = [
[
[1, 1, 1],
[1, 1, 1],
[0, 0, 0],
[0, 0, 0],
],
[
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
],
...
]
所以遮罩的形状现在是[10, 4, 3]
。假设我使用batch_size = 5
。现在,根据文档,attention_mask
形状应该是[B, T, S]
(Batch_Size,Query_Size,Key_Size)。在本例中应为[5, 4, 4]
?
问题
如果只计算一次掩码,我应该给哪5项作为掩码?在我看来,这听起来有违常理。我应该如何制作面具?
根据this的回答,HEAD_SIZE也应该考虑在内,因此它们也会这样做:
mask = mask[:, tf.newaxis, tf.newaxis, :]
我测试的内容
我使用attention_mask
成功运行转换器的唯一一次是在以下情况下:
mask = np.ones((batch_size, data.shape[1], data.shape[2]))
mask = mask[:, tf.newaxis, tf.newaxis, :]
显然,这个面具没有任何意义,因为它都是一个,但它只是为了测试它是否有正确的形状。
机型
我使用与keras
example转换器相同的代码进行时间序列分类
def transformer_encoder(inputs, head_size, num_heads, ff_dim, dropout=0.0, mask=None):
# Normalization and Attention
x = layers.LayerNormalization(epsilon=1e-6)(inputs)
x = layers.MultiHeadAttention(
key_dim=head_size, num_heads=num_heads, dropout=dropout
)(x, x, attention_mask=mask)
x = layers.Dropout(dropout)(x)
res = x + inputs
# Feed Forward Part
x = layers.LayerNormalization(epsilon=1e-6)(res)
x = layers.Conv1D(filters=ff_dim, kernel_size=1, activation="relu")(x)
x = layers.Dropout(dropout)(x)
x = layers.Conv1D(filters=inputs.shape[-1], kernel_size=1)(x)
return x + res
def build_model(
n_classes,
input_shape,
head_size,
num_heads,
ff_dim,
num_transformer_blocks,
mlp_units,
dropout=0.0,
mlp_dropout=0.0,
input_mask=None,
) -> keras.Model:
inputs = keras.Input(shape=input_shape)
x = inputs
for _ in range(num_transformer_blocks):
x = transformer_encoder(x, head_size, num_heads, ff_dim, dropout, input_mask)
x = layers.GlobalAveragePooling2D(data_format="channels_first")(x)
for dim in mlp_units:
x = layers.Dense(dim, activation="relu")(x)
x = layers.Dropout(mlp_dropout)(x)
outputs = layers.Dense(n_classes, activation="softmax")(x)
return keras.Model(inputs, outputs)
2条答案
按热度按时间8zzbczxx1#
首先,一个更简单的例子来理解
MultiHeadAttention
掩码。上面是给定查询的
attention scores
。attention_mask
用于防止注意此乐谱中的某些位置。因此,掩蔽维度应该与注意力得分维度相同。假设我们决定上面示例中的当前令牌只需要关注其自身和下一个令牌,那么我们可以将掩码定义为:
批次中的每一项都可以有不同的掩膜吗?
是的,我能想到的一个用例是,当您对同一批次中的不同样品进行填充时,因此可以设置掩码以忽略这些填充。
您的特定情况:掩码必须是
(batch_size, 4, 4)
。对于批次中的每个项目,掩码可以是相同的。oxalkeyp2#
经过一点研究和看了几个变压器模型的例子,这就解决了我的问题。
1.创建支持掩码的自定义
TransformerBlock
层1.在
TransformerBlock
的call
方法中添加一个mask
参数,并对其进行整形。1.在
TransformerBlock
之前增加一个Masking
层代码: