Tensor2Tensor中bias向量构建及注意力机制中bias作用咨询
我来帮你理清Tensor2Tensor(T2T)里注意力机制中bias的构建逻辑,不管是自注意力还是交叉注意力场景,核心都是用bias来屏蔽无效的padding位置(或者其他需要忽略的位置,比如因果掩码),让注意力只聚焦在有效内容上。
一、自注意力(Self-Attention)的Bias构建
你的输入是形状为(batch, max_input_length, hidden_unit)的张量T,以及记录每个句子实际长度的sequence_length(形状(batch))。自注意力中query、key、value都是同一个输入,所以我们需要屏蔽输入序列自身的padding部分。
具体步骤与代码实现
T2T的common_attention模块提供了现成的工具函数来生成padding对应的bias:
- 首先生成padding掩码:用
tf.sequence_mask根据sequence_length标记出哪些位置是有效内容(True),哪些是padding(False)。 - 用
attention_bias_ignore_padding将掩码转换为注意力bias——这个函数会把padding位置对应的注意力分数设为一个极小值(比如-1e9),这样经过softmax后,这些位置的权重会趋近于0,不会参与注意力计算。
示例代码:
import tensor2tensor.layers.common_attention as ca import tensorflow as tf # 模拟你的输入参数 batch_size = 32 max_input_length = 100 hidden_unit = 512 # 生成随机的句子长度(10到100之间) sequence_length = tf.random.uniform((batch_size,), minval=10, maxval=max_input_length, dtype=tf.int32) # 1. 生成padding掩码:形状 (batch, max_input_length) padding_mask = tf.sequence_mask(sequence_length, maxlen=max_input_length) # 2. 转换为自注意力bias:形状 (batch, 1, 1, max_input_length) self_att_bias = ca.attention_bias_ignore_padding(padding_mask) # 查看bias形状,符合T2T多头注意力的输入要求 print(self_att_bias.shape) # 输出 (32, 1, 1, 100)
如何使用这个Bias
调用T2T的multihead_attention时,把self_att_bias传入bias参数即可:
# 自注意力计算:query/key/value都是输入张量T self_att_output = ca.multihead_attention( query=T, memory_antecedent=T, # T2T中memory_antecedent对应key/value的输入 bias=self_att_bias, num_heads=8, hidden_size=hidden_unit )
这里的bias形状(batch,1,1,max_input_length)会自动广播到所有注意力头和所有query位置,确保每个query都忽略输入中的padding部分。
二、交叉注意力(Cross-Attention)的Bias构建
当query和key/value来自不同输入时(比如Transformer中decoder关注encoder的输出),你说得没错:我们需要针对key/value对应的序列长度来构建bias,因为要屏蔽的是key/value中的padding部分,而不是query的。
具体步骤与代码实现
假设你的key/value来自encoder的输出,对应的句子长度是encoder_sequence_length(形状(batch)),max长度是max_encoder_length:
# 模拟encoder的输入参数 max_encoder_length = 100 encoder_sequence_length = tf.random.uniform((batch_size,), minval=10, maxval=max_encoder_length, dtype=tf.int32) # 1. 生成key/value的padding掩码:形状 (batch, max_encoder_length) k_padding_mask = tf.sequence_mask(encoder_sequence_length, maxlen=max_encoder_length) # 2. 转换为交叉注意力bias:形状 (batch, 1, 1, max_encoder_length) cross_att_bias = ca.attention_bias_ignore_padding(k_padding_mask)
如何使用这个Bias
调用multihead_attention时,query传入decoder的输出,memory_antecedent传入encoder的输出,同时传入cross_att_bias:
# 假设decoder_output是decoder的输出,形状 (batch, max_decoder_length, hidden_unit) # encoder_output是encoder的输出,形状 (batch, max_encoder_length, hidden_unit) cross_att_output = ca.multihead_attention( query=decoder_output, memory_antecedent=encoder_output, bias=cross_att_bias, num_heads=8, hidden_size=hidden_unit )
这个bias会让decoder的每个query只关注encoder输出中的有效内容,忽略padding部分。
额外补充:因果掩码(如果需要)
如果是decoder的自注意力,还需要屏蔽未来的token(不能看到还没生成的内容),可以用attention_bias_lower_triangle生成因果掩码,再和padding bias叠加:
# 生成因果掩码:形状 (1, 1, max_decoder_length, max_decoder_length) causal_bias = ca.attention_bias_lower_triangle(max_decoder_length) # 叠加padding bias和因果掩码 decoder_self_att_bias = ca.attention_bias_ignore_padding(decoder_padding_mask) + causal_bias
内容的提问来源于stack exchange,提问作者Maruf

