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

正弦位置编码是否需交错sin与cos?两种实现方案正确性咨询

正弦位置编码两种实现的有效性验证

我正在实现正弦位置编码(sinusoidal positional encoding),发现两种不同的实现方案生成的编码结果存在差异,附上两种方案的代码及可视化结果,想确认这两种方案是否存在错误,或是均为有效实现?

方案1实现代码

class SinusoidalPosEmb(nn.Module):
    def __init__(self, dim):
        super().__init__()
        self.dim = dim
    def forward(self, x):
        device = x.device
        half_dim = self.dim // 2
        emb = math.log(10000) / (half_dim - 1)
        emb = torch.exp(torch.arange(half_dim, device=device) * -emb)
        emb = x[:, None] * emb[None, :]
        emb = torch.cat((emb.sin(), emb.cos()), dim=-1)
        return emb

方案1编码可视化:
方案1编码可视化

方案2实现代码

class TransformerPositionalEmbedding(nn.Module):
    """
    From paper "Attention Is All You Need", section 3.5
    """
    def __init__(self, dimension, max_timesteps=1000):
        super(TransformerPositionalEmbedding, self).__init__()
        assert dimension % 2 == 0, "Embedding dimension must be even"
        self.dimension = dimension
        self.pe_matrix = torch.zeros(max_timesteps, dimension)
        # Gather all the even dimensions across the embedding vector
        even_indices = torch.arange(0, self.dimension, 2)
        # Calculate the term using log transforms for faster calculations
        log_term = torch.log(torch.tensor(10000.0)) / self.dimension
        div_term = torch.exp(even_indices * -log_term)
        # Precompute positional encoding matrix based on odd/even timesteps
        timesteps = torch.arange(max_timesteps).unsqueeze(1)
        self.pe_matrix[:, 0::2] = torch.sin(timesteps * div_term)
        self.pe_matrix[:, 1::2] = torch.cos(timesteps * div_term)
    def forward(self, timestep):
        # [bs, d_model]
        return self.pe_matrix[timestep]

方案2编码可视化:
方案2编码可视化


两种实现的分析与结论

两种方案均为有效实现,差异源于对频率衰减参数的不同设置,并非错误:

  1. 方案2是严格对齐原论文的标准实现:
    完全遵循《Attention Is All You Need》3.5节的公式,计算div_term时使用log(10000)/dimension作为缩放因子,确保偶数维度的位置编码为sin(pos / 10000^(2i/dimension)),奇数维度为cos(pos / 10000^(2i/dimension)),是Transformer架构中最常用的正弦位置编码实现。

  2. 方案1是原论文的变体实现:
    它将频率衰减的分母从dimension改为half_dim - 1(即dimension//2 - 1),这会调整不同维度上的频率衰减速度,使得位置编码的频率变化节奏与标准实现不同,但依然通过正弦/余弦的不同频率组合为每个位置提供独特的编码标识,同样能起到位置编码的作用,常见于一些Diffusion模型的时间步编码场景。

两者的可视化差异正是由于频率参数的调整导致的,本质上都能满足位置编码的核心需求——让模型区分不同的序列位置。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 05:34:57