编辑
2025-05-09
深度学习
00

目录

m-RoPE(多模态旋转位置编码)
1. 基本原理
2. 标准RoPE回顾
3. m-RoPE的创新点
3.1 三维位置ID
3.2 特征分块处理
3.3 数学公式表示
4. 代码实现分析
4.1 位置索引计算
4.2 位置编码生成
4.3 特征分块与多维度应用
5. 实际效果

m-RoPE(多模态旋转位置编码)

1. 基本原理

m-RoPE是传统RoPE(旋转位置编码)在多模态场景下的扩展。传统RoPE处理的是一维序列,而m-RoPE专门设计用来处理包含图像和视频等视觉内容的多模态输入。

如代码中注释所述:

多模态3D旋转位置编码是1D旋转位置编码的扩展。输入嵌入序列包含视觉(图像/视频)嵌入和文本嵌入,或者仅包含文本嵌入。对于视觉嵌入部分,我们分别在时间、高度和宽度维度上应用旋转位置编码。这里我们将通道维度分为3个块,用于时间、高度和宽度旋转位置编码。对于文本嵌入部分,我们只应用1D旋转位置编码。

2. 标准RoPE回顾

标准RoPE通过对每个token的嵌入进行旋转变换,将位置信息植入到token嵌入中。其核心公式:

qm(i)=[cos(mθi)sin(mθi)sin(mθi)cos(mθi)]q(i)q_m^{(i)} = \begin{bmatrix} \cos(m\theta_i) & -\sin(m\theta_i) \\ \sin(m\theta_i) & \cos(m\theta_i) \end{bmatrix} \cdot q^{(i)}

其中,q(i)q^{(i)}是查询向量的第i个特征维度,mm是token的绝对位置,θi\theta_i是频率系数,通常θi=100002(i1)/d\theta_i = 10000^{-2(i-1)/d}

在代码中,这种旋转通过rotate_half函数实现:

python
def rotate_half(x): """Rotates half the hidden dims of the input.""" x1 = x[..., : x.shape[-1] // 2] x2 = x[..., x.shape[-1] // 2 :] return torch.cat((-x2, x1), dim=-1)

以及旋转变换公式:

python
q_embed = (q * cos) + (rotate_half(q) * sin) k_embed = (k * cos) + (rotate_half(k) * sin)

3. m-RoPE的创新点

3.1 三维位置ID

对于视觉输入(图像/视频),Qwen2.5-VL使用三维位置ID:

  • 时间维度(t):处理视频中帧的顺序
  • 高度维度(h):图像/视频帧的垂直位置
  • 宽度维度(w):图像/视频帧的水平位置

这在Qwen2_5_VLRotaryEmbedding.forward中有体现:

python
# Core RoPE block. In contrast to other models, Qwen2_5_VL has different position ids for thw grids # So we expand the inv_freq to shape (3, ...) inv_freq_expanded = self.inv_freq[None, None, :, None].float().expand(3, position_ids.shape[1], -1, 1) position_ids_expanded = position_ids[:, :, None, :].float() # shape (3, bs, 1, positions)

3.2 特征分块处理

关键创新是将查询和键向量的特征维度分成三个部分,分别应用时间、高度和宽度的位置编码。这在apply_multimodal_rotary_pos_emb函数中实现:

python
mrope_section = mrope_section * 2 # mrope_section是每个维度分配的特征数 cos = torch.cat([m[i % 3] for i, m in enumerate(cos.split(mrope_section, dim=-1))], dim=-1) sin = torch.cat([m[i % 3] for i, m in enumerate(sin.split(mrope_section, dim=-1))], dim=-1)

这段代码的核心操作是:

  1. 将cos和sin按照mrope_section大小分块
  2. 对每个分块,根据索引i对3取模决定使用哪个维度的位置信息(时间、高度或宽度)
  3. 重新拼接为完整向量

3.3 数学公式表示

m-RoPE可以表示为:

qm(i)={R(mt,θi)q(i),如果 imod3=0(时间维度)R(mh,θi)q(i),如果 imod3=1(高度维度)R(mw,θi)q(i),如果 imod3=2(宽度维度)q_m^{(i)} = \begin{cases} R(m_t, \theta_i) \cdot q^{(i)}, & \text{如果 $i \bmod 3 = 0$(时间维度)} \\ R(m_h, \theta_i) \cdot q^{(i)}, & \text{如果 $i \bmod 3 = 1$(高度维度)} \\ R(m_w, \theta_i) \cdot q^{(i)}, & \text{如果 $i \bmod 3 = 2$(宽度维度)} \end{cases}

其中,R(m,θi)R(m, \theta_i)是标准RoPE的旋转矩阵,mtm_tmhm_hmwm_w分别是时间、高度和宽度维度的位置ID。

4. 代码实现分析

完整的m-RoPE实现涉及以下几个关键组件:

4.1 位置索引计算

get_rope_index方法负责为输入序列生成三维位置ID:

  • 对于纯文本序列,三个维度的位置ID相同(标准RoPE行为)
  • 对于视觉嵌入,根据grid_thw参数生成不同的时间、高度和宽度位置ID

4.2 位置编码生成

Qwen2_5_VLRotaryEmbedding类负责生成位置编码的sin和cos成分:

python
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(2, 3) emb = torch.cat((freqs, freqs), dim=-1) cos = emb.cos() sin = emb.sin()

4.3 特征分块与多维度应用

apply_multimodal_rotary_pos_emb函数将cos和sin分块,并根据特征维度应用相应的位置编码:

python
mrope_section = mrope_section * 2 cos = torch.cat([m[i % 3] for i, m in enumerate(cos.split(mrope_section, dim=-1))], dim=-1) sin = torch.cat([m[i % 3] for i, m in enumerate(sin.split(mrope_section, dim=-1))], dim=-1) q_embed = (q * cos) + (rotate_half(q) * sin) k_embed = (k * cos) + (rotate_half(k) * sin)

5. 实际效果

m-RoPE的设计使得模型能够:

  1. 正确理解视频中的时序信息(前后关系)
  2. 捕捉图像和视频帧中的空间布局(上下左右关系)
  3. 同时保持文本序列的正常处理能力

这种设计让Qwen2.5-VL能够更好地理解和处理多模态输入,特别是在处理需要空间和时间理解的视觉内容时,如视频动作识别、空间关系描述等任务。

总结来说,m-RoPE通过将标准RoPE扩展到三维空间(时间、高度、宽度),并通过特征分块技术将这三种位置信息分别编码到不同的特征维度中,从而实现了对多模态内容的更有效建模。

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!