← 返回首页

嵌入与位置编码

词向量表示、绝对位置编码、相对位置编码(RoPE)技术

什么是词嵌入?

词嵌入(Word Embedding)是将离散的词汇符号映射到连续向量空间的技术。它将词汇转换为密集的实数向量,使计算机能够进行数学运算并捕捉词汇间的语义关系。

词汇到向量的映射示例

"国王" → [0.2, -0.1, 0.8, 0.4]

"女王" → [0.1, -0.2, 0.7, 0.5]

"男人" → [0.3, 0.1, -0.2, 0.6]

"女人" → [0.0, 0.0, -0.3, 0.7]

嵌入的数学表示

对于词汇表 $V$ 中的词 $w_i$,嵌入函数定义为:

$$E: w_i \rightarrow \mathbf{e_i} \in \mathbb{R}^d$$

其中 $d$ 是嵌入维度,$\mathbf{e_i}$ 是词 $w_i$ 的嵌入向量

嵌入矩阵的实现

在神经网络中,词嵌入通常通过查找表(Lookup Table)实现,即嵌入矩阵 $\mathbf{E} \in \mathbb{R}^{|V| \times d}$。

嵌入矩阵示例 (词汇表大小=5, 维度=4)

0.2
-0.1
0.8
0.4
0.1
-0.2
0.7
0.5
0.3
0.1
-0.2
0.6
0.0
0.0
-0.3
0.7
0.5
0.2
0.9
-0.1
PyTorch 嵌入层实现

import torch
import torch.nn as nn

# 创建嵌入层
vocab_size = 10000
embedding_dim = 512
embedding = nn.Embedding(vocab_size, embedding_dim)

# 输入token索引
input_ids = torch.tensor([1, 15, 234, 67])  # batch中的token IDs
embedded = embedding(input_ids)  # shape: [4, 512]

print(f"输入shape: {input_ids.shape}")
print(f"嵌入后shape: {embedded.shape}")
                    

位置编码的必要性

Transformer架构没有内在的位置信息概念,因为自注意力机制对输入序列的排列是不变的。位置编码为模型提供了序列中每个位置的信息。

问题示例:

"我爱你" 和 "你爱我" 在没有位置信息的情况下,Self-Attention会产生相同的结果,无法区分词序的重要性。

位置编码的作用

  • 序列顺序:告诉模型词汇在序列中的位置
  • 相对位置:帮助模型理解词汇间的相对距离
  • 语法结构:支持模型学习语言的语法规律

绝对位置编码

可学习位置编码

最简单的位置编码方法是为每个位置分配一个可学习的向量。

$$\mathbf{x_i} = \mathbf{e_i} + \mathbf{p_i}$$

其中 $\mathbf{e_i}$ 是词嵌入,$\mathbf{p_i}$ 是位置 $i$ 的位置编码

可学习位置编码实现

# 可学习位置编码
max_seq_length = 512
pos_embedding = nn.Embedding(max_seq_length, embedding_dim)

# 生成位置索引
position_ids = torch.arange(seq_length).unsqueeze(0)  # [1, seq_len]
position_embeddings = pos_embedding(position_ids)     # [1, seq_len, d]

# 添加到词嵌入
final_embeddings = word_embeddings + position_embeddings
                    

正弦位置编码

Transformer原论文提出的正弦位置编码,使用不同频率的正弦和余弦函数。

$$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$ $$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$

正弦位置编码的优势

  • 确定性:不需要训练,直接计算得出
  • 外推性:可以处理训练时未见过的序列长度
  • 相对位置:任意两个位置的相对偏移可以表示为线性变换

相对位置编码

相对位置编码关注的是词汇间的相对距离,而不是绝对位置。这种方法在很多任务中表现更好。

相对位置的表示

$$A_{ij} = \frac{(\mathbf{x_i W_Q})(\mathbf{x_j W_K} + \mathbf{r_{i-j}})^T}{\sqrt{d_k}}$$

其中 $\mathbf{r_{i-j}}$ 是位置 $i$ 和 $j$ 之间相对位置的编码

编码类型 优势 劣势 适用场景
绝对位置 简单直观 外推性差 固定长度序列
相对位置 更好的泛化 计算复杂 变长序列
RoPE 兼具两者优势 实现复杂 长序列任务

旋转位置编码 (RoPE)

RoPE(Rotary Position Embedding)是一种新颖的位置编码方法,通过旋转变换来编码相对位置信息。

RoPE 的核心思想

核心原理:将每个位置的嵌入向量在复数平面上进行旋转,旋转角度与位置相关。

对于位置 $m$ 的查询向量 $\mathbf{q}$ 和位置 $n$ 的键向量 $\mathbf{k}$:

$$f_q(\mathbf{x_m}, m) = \mathbf{R_m} \mathbf{W_q} \mathbf{x_m}$$ $$f_k(\mathbf{x_n}, n) = \mathbf{R_n} \mathbf{W_k} \mathbf{x_n}$$

其中 $\mathbf{R_m}$ 是旋转矩阵

维度 0,1
θ₁ × m
维度 2,3
θ₂ × m
维度 4,5
θ₃ × m
...
...

RoPE 的旋转矩阵

$$\mathbf{R_m} = \begin{pmatrix} \cos(m\theta_1) & -\sin(m\theta_1) & 0 & 0 & \cdots \\ \sin(m\theta_1) & \cos(m\theta_1) & 0 & 0 & \cdots \\ 0 & 0 & \cos(m\theta_2) & -\sin(m\theta_2) & \cdots \\ 0 & 0 & \sin(m\theta_2) & \cos(m\theta_2) & \cdots \\ \vdots & \vdots & \vdots & \vdots & \ddots \end{pmatrix}$$
RoPE (旋转位置编码) 实现

import torch
import torch.nn as nn

def apply_rope(x, position_ids, rope_cache):
    """
    应用旋转位置编码
    x: [batch_size, seq_len, num_heads, head_dim]
    position_ids: [batch_size, seq_len]
    """
    seq_len = x.size(1)
    head_dim = x.size(-1)
    
    # 生成旋转角度
    inv_freq = 1.0 / (10000 ** (torch.arange(0, head_dim, 2) / head_dim))
    sinusoid_inp = torch.einsum("i,j->ij", position_ids, inv_freq)
    
    # 计算cos和sin
    cos = sinusoid_inp.cos()
    sin = sinusoid_inp.sin()
    
    # 应用旋转变换
    x1, x2 = x[..., ::2], x[..., 1::2]
    rotated = torch.cat([
        x1 * cos - x2 * sin,
        x1 * sin + x2 * cos
    ], dim=-1)
    
    return rotated
                    

ALiBi (Attention with Linear Biases)

ALiBi是另一种相对位置编码方法,直接在注意力权重上添加线性偏置。

$$\text{softmax}(q_i K^T + m \cdot [-(i-1), -(i-2), \ldots, -1, 0])$$

其中 $m$ 是头部特定的斜率参数

ALiBi 的优势

  • 简单高效:计算开销小,实现简单
  • 外推能力强:在更长序列上表现良好
  • 无需位置嵌入:完全消除了位置嵌入的需要

位置编码的实际应用

不同模型的选择

模型 位置编码类型 最大序列长度 特点
BERT 可学习绝对位置 512 固定长度,性能稳定
GPT 可学习绝对位置 1024-8192 逐代增加序列长度
T5 相对位置偏置 不限 良好的外推性能
RoFormer RoPE 不限 中文优化,长序列

选择建议

  • 短序列任务:可学习绝对位置编码
  • 长序列任务:RoPE 或 ALiBi
  • 多语言任务:相对位置编码
  • 计算资源受限:正弦位置编码或ALiBi

🔧 位置编码可视化

调整参数观察不同位置编码的效果: