You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras MultiHeadAttention输出与《Python深度学习》自注意力实现结果不符问题

结果不一致的核心原因
  • 无参数与带参数实现的本质差异
    你手写的self_attention是无参数的基础自注意力实现,直接用输入向量同时作为查询(Q)、键(K)、值(V)进行计算。而Keras的MultiHeadAttention默认带有四组可训练的投影矩阵:分别对输入做Q、K、V的线性变换,以及对注意力输出做最终线性变换。你测试时仅设置了use_bias=False,并没有固定投影矩阵的取值,随机初始化的参数会完全改变Q、K、V的数值,最终得到的注意力权重和输出自然和手写版本不一致。
  • 维度处理逻辑的默认差异
    你手写的实现针对单头、输入维度等于key_dim的场景设计,没有额外的维度拆分和投影逻辑。而MultiHeadAttention内部默认会先把输入投影到key_dim * num_heads的维度再按头拆分,只要投影矩阵不是单位矩阵,计算结果就会偏离手写实现。
对齐结果的修改方案

你只需要在初始化MultiHeadAttention后,手动将所有投影权重设置为单位矩阵,即可和手写的无参数自注意力结果对齐,修改后的测试代码如下:

import numpy as np
from scipy.special import softmax
from tensorflow.keras.layers import MultiHeadAttention

def self_attention(input_sequence):
    output = np.zeros(shape=input_sequence.shape)
    for i, pivot_vector in enumerate(input_sequence):
        scores = np.zeros(shape=(len(input_sequence),))
        for j, vector in enumerate(input_sequence):
            scores[j] = np.dot(pivot_vector, vector.T)
        scores /= np.sqrt(input_sequence.shape[1])
        scores = softmax(scores)
        new_pivot_representation = np.zeros(shape=pivot_vector.shape)
        for j, vector in enumerate(input_sequence):
            new_pivot_representation += vector * scores[j]
        output[i] = new_pivot_representation
    return output

test_input_sequence = np.array([[[1.0, 0.0, 0.0, 1.0],
                                 [0.0, 1.0, 0.0, 0.0],
                                 [0.0, 1.0, 1.0, 1.0]]])

# 手写自注意力结果
print("手写自注意力输出:")
print(self_attention(test_input_sequence[0]))

att_layer = MultiHeadAttention(num_heads=1,
                               key_dim=4,
                               use_bias=False,
                               attention_axes=(1,))
# 手动设置所有投影矩阵为单位矩阵
att_layer.build(input_shape=(None, 3, 4))
att_layer._query_kernel.assign(np.eye(4, 4))
att_layer._key_kernel.assign(np.eye(4, 4))
att_layer._value_kernel.assign(np.eye(4, 4))
att_layer._output_kernel.assign(np.eye(4, 4))

# 调用MultiHeadAttention
output, scores = att_layer(test_input_sequence,
                          test_input_sequence,
                          test_input_sequence,
                          return_attention_scores=True)
print("Keras MultiHeadAttention输出:")
print(output[0].numpy())
print("Keras注意力权重:")
print(scores[0, 0].numpy())

运行上述代码后,两者的注意力权重和输出会完全匹配,仅存在浮点数精度导致的微小误差。

内容的提问来源于stack exchange,提问作者Pierre Nugues

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:36:01