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}$可将标准差缩放回原大小,保证数据分布不发生变化提高训练稳定性

posted @ 2025-04-10 11:20  AI_Engineer  阅读(163)  评论(0)    收藏  举报