TensorFlow位置编码实现是否与Transformer论文要求不符?
Transformer位置编码实现差异疑问
我在查阅TensorFlow官方Transformer教程时,发现其中的位置编码函数实现如下:
def positional_encoding(length, depth): depth = depth/2 positions = np.arange(length)[:, np.newaxis] # (seq, 1) depths = np.arange(depth)[np.newaxis, :]/depth # (1, depth) angle_rates = 1 / (10000**depths) # (1, depth) angle_rads = positions * angle_rates # (pos, depth) pos_encoding = np.concatenate( [np.sin(angle_rads), np.cos(angle_rads)], axis=-1) return tf.cast(pos_encoding, dtype=tf.float32)
该实现将cosine结果直接拼接在sine结果之后,而非Transformer论文中要求的sine与cosine交替排列的形式,可视化结果也显示了这一差异。而我自行编写的如下实现:
def positional_encoding(len, token_size): depth = tf.range(token_size/2, dtype=tf.float32) * 2 / token_size divisor = 10000 ** depth position = tf.range(len, dtype=tf.float32) argument = (position[:,None] / divisor[None, :])[...,None] pre_alternation = tf.concat((tf.math.sin(argument), tf.math.cos(argument)), axis=-1) return tf.reshape(pre_alternation, (len,token_size))
其可视化结果符合论文中的交替排列形式。请问我在此处忽略了什么细节?
核心结论:两种实现完全等价,无效果差异
- 本质上,官方实现是把所有正弦分量放在特征维度前半段、余弦分量放在后半段;你的实现是正弦和余弦交替排列。但对Transformer的注意力机制而言,这只是特征维度的顺序重排——注意力权重是对所有维度计算的,维度顺序不会改变最终的注意力输出逻辑。
- 从数学层面看,两种位置编码的特征空间完全一致,只是维度排列方式不同。模型训练时会自动适应这种顺序,最终的性能表现没有区别。
- 官方采用拼接实现仅为了代码简洁高效:直接拼接比交替排列少了一次reshape操作,计算逻辑更直观,运行效率也略高。
内容的提问来源于stack exchange,提问作者Alberto
相关产品推荐
相关产品推荐

