self-attention
Self - Attention(自注意力机制)的核心公式为:
\[
\text{Attention}(Q, K, V) = \text{softmax}\left( \frac{QK^T}{\sqrt{d_k}} \right) V
\]
以下是对公式中各部分的详细解释:
符号含义:
- $Q$(Query,查询矩阵):代表当前需要关注的焦点信息,由输入数据经过线性变换得到。
- $K$(Key,键矩阵):与输入序列相关,用于计算与查询的匹配程度,由输入数据线性变换生成。
- $V$(Value,值矩阵):包含输入序列的具体信息,是最终用于加权求和的内容,通过输入线性变换得到。
- $d_k$:键向量的维度。矩阵相乘($QK^T$)会使结果的标准差增大,约为$\sqrt{d_k}$倍,除以$\sqrt{d_k}$可将标准差缩放回原大小,避免 softmax 函数饱和,保证训练稳定性。
公式各部分运算意义:
- $QK^T$:计算查询与键之间的相似度,得到注意力分数矩阵。
- $\text{softmax}\left( \frac{QK^T}{\sqrt{d_k}} \right)$:对注意力分数进行归一化,转化为概率形式(权重),表示每个键与查询的相关程度,所有权重之和为 1。
- $\text{softmax}\left( \frac{QK^T}{\sqrt{d_k}} \right) V$:用归一化后的权重对值矩阵 $V$ 进行加权求和,得到最终的自注意力输出。该输出融合了输入序列中与查询相关的信息,本质是通过计算输入序列中各元素间的关联程度(注意力权重),有选择地聚合 $V$ 的信息,从而捕捉序列中的长距离依赖关系,为每个位置生成一个综合全局信息的表示。 这个公式是自注意力机制的核心,广泛应用于 Transformer 等模型中,用于处理序列数据并挖掘数据内部的关联信息。
class SelfAttention(tf.keras.layers.Layer): def __init__(self, d_model): super(SelfAttention, self).__init__() self.d_model = d_model self.query_layer = tf.keras.layers.Dense(d_model) self.key_layer = tf.keras.layers.Dense(d_model) self.value_layer = tf.keras.layers.Dense(d_model) def call(self, x): """ 实现自注意力机制的前向传播过程 :param x: 输入张量,形状为 (batch_size, seq_length, input_dim) :return: 输出张量,形状为 (batch_size, seq_length, d_model) """ # 获取查询、键和值向量 Q = self.query_layer(x) # (batch_size, seq_length, d_model) K = self.key_layer(x) # (batch_size, seq_length, d_model) V = self.value_layer(x) # (batch_size, seq_length, d_model) # 计算注意力分数 scores = tf.matmul(Q, K, transpose_b=True) # (batch_size, seq_length, seq_length) scores = scores / tf.math.sqrt(tf.cast(self.d_model, tf.float32)) # 缩放分数,防止梯度消失或爆炸 attention_weights = tf.nn.softmax(scores, axis=-1) # (batch_size, seq_length, seq_length) # 计算加权和 output = tf.matmul(attention_weights, V) # (batch_size, seq_length, d_model) return output # 示例使用 if __name__ == "__main__": # 输入张量,假设 batch_size=32,seq_length=10,input_dim=512 input_tensor = tf.random.normal([32, 10, 512]) # 初始化 SelfAttention 层,假设 d_model=256 self_attention = SelfAttention(d_model=256) # 调用 SelfAttention 层 output_tensor = self_attention(input_tensor) print(output_tensor.shape)
self-attentiom 计算时为什么要除以$\sqrt{d_k}$ ?
1. 向量点击后会时计算出来的数急剧增大,在用softmax计算权重时,会时权重分布拉的非常大,容易被权重大那个主导(除以$\sqrt{d_k}$相当与除了大于1的温度参数,可以拉近softmax后计算出来权重差距)
2. 矩阵相乘($QK^T$)会使结果的标准差增大,约为$\sqrt{d_k}$倍,除以$\sqrt{d_k}$可将标准差缩放回原大小,保证数据分布不发生变化提高训练稳定性

浙公网安备 33010602011771号