DeepSeek-OCR 2: Visual Causal Flow学习

传统的视觉-语言模型 (VLM) 在输入到 LLM 时,总是以刚性的光栅扫描顺序(从左上到右下)处理视觉 tokens,并采用固定的位置编码。然而,这与人类的视觉感知相悖,人类的视觉感知遵循灵活但语义连贯的扫描模式,这种模式由内在的逻辑结构驱动。特别是对于具有复杂布局的图像,人类视觉表现出因果相关的顺序处理。受这种认知机制的启发,DeepEncoder V2 的设计旨在赋予编码器因果推理能力,使其能够在基于 LLM 的内容解释之前智能地重新排序视觉 tokens。这项工作探索了一种新的范式:是否可以通过两个级联的 1D 因果推理结构有效地实现 2D 图像理解,从而提供一种新的架构方法,并有可能实现真正的 2D 推理。代码和模型权重可在 http://github.com/deepseek-ai/DeepSeek-OCR-2 公开访问

DeepSeek-OCR 2: Visual Causal Flow 论文大纲

I. 引言 (Introduction)

  • 背景:
    • 人类视觉系统遵循语义驱动的因果扫描模式,与传统VLM(Vision-Language Models)的固定栅格扫描顺序形成对比。
    • 传统VLM将2D图像扁平化为1D序列,引入了不必要的归纳偏差,忽略了语义关系。
  • 研究目标: 探索一种新型编码器------DeepEncoder V2,使其能够根据图像语义动态重排序视觉tokens,以实现更类人化的视觉编码。
  • 主要贡献:
    1. 提出DeepEncoder V2: 用紧凑型LLM架构替代CLIP组件,引入可学习的因果流查询(causal flow tokens)和定制注意力掩码,实现视觉因果流。
    2. 发布DeepSeek-OCR 2: 在保持DeepSeek-OCR图像压缩比和解码效率的同时,显著提升性能,并作为研究探索和高质量训练数据生成工具。
    3. 验证LLM架构作为VLM编码器的潜力: 为统一全模态编码(omni-modal encoding)提供可行路径。

II. 相关工作 (Related Works)

  • 解码器中的并行查询 (Parallelized Queries in Decoder):
    • 以DETR为代表,通过预设并行可学习查询处理token,打破了传统检测范式中串行解码的效率限制。
  • 投影器中的并行查询 (Parallelized Queries in Projector):
    • 以BLIP-2中的Q-former为例,利用可学习查询进行视觉token压缩,将视觉token与LLM嵌入空间对齐。
  • 基于LLM的多模态初始化 (LLM-based Multimodal Initialization):
    • LLM预训练权重在多模态模型初始化中的有效性,例如Fuyu和Chameleon。

III. 方法论 (Methodology)

  • 整体架构 (Architecture):
    • DeepSeek-OCR 2继承DeepSeek-OCR的编码器-解码器架构。
    • 核心区别: 编码器升级为DeepEncoder V2,引入因果推理能力。
  • DeepEncoder V2 详解:
    • 愿景: 解决传统编码器将2D图像转换为1D序列时引入的僵硬排序偏差,该偏差与非线性视觉阅读模式不符。
    • 视觉分词器 (Vision Tokenizer):
      • 采用80M参数的SAM-base结合两个卷积层,将图像压缩为视觉tokens(16倍压缩)。
      • 参数量与LLM中用于文本输入嵌入的参数量(~100M)相当。
    • 语言模型作为视觉编码器 (Language model as vision encoder):
      • DeepEncoder V2将DeepEncoder中的CLIP ViT替换为LLM风格架构 ,采用双流注意力机制
      • 视觉tokens: 使用双向注意力,保持CLIP的全局建模能力。
      • 因果流查询 (Causal flow query):
        • 新增可学习查询,附加在视觉tokens之后,采用因果注意力
        • 每个查询可关注所有视觉tokens和其之前的查询。
        • 通过维护查询与视觉tokens数量相等,实现语义排序和视觉特征提炼。
        • 只有因果查询的输出被送入LLM解码器。
      • 两阶段级联因果推理: 编码器通过可学习查询对视觉tokens进行语义重排序,LLM解码器对重排序后的序列执行自回归推理。
      • 实例化: 使用Qwen2-0.5B(500M参数)。
    • 注意力掩码 (Attention mask):
      • 由两个独立区域组成:左侧对原始视觉tokens应用双向注意力 (ViT风格),右侧对因果流tokens应用因果注意力(LLM解码器风格的下三角掩码)。
      • 数学表示:M = [ [1mxm, 0mxn], [1nxm, LowerTri(n)] ]
  • DeepSeek-MoE 解码器 (DeepSeek-MoE Decoder):
    • DeepSeek-OCR 2主要关注编码器改进,解码器沿用DeepSeek-OCR的3B参数MoE结构。
    • 前向传播公式:O = D(πo(T^L(Ɛ(I) ⊕ Q0; M)))

IV. 实验设置 (Experimental Settings)

  • 数据引擎 (Data Engine):
    • 沿用DeepSeek-OCR的数据源,OCR数据占80%。
    • 两项修改:OCR 1.0数据采样策略更平衡,布局检测标签优化。
  • 训练流程 (Training Pipelines):
    • 阶段1:编码器预训练 - 视觉分词器和LLM风格编码器学习特征提取、token压缩和token重排序。
    • 阶段2:查询增强 - 冻结视觉分词器,联合优化LLM编码器和解码器,增强查询表示和token重排序能力。
    • 阶段3:LLM继续训练 - 冻结DeepEncoder V2所有参数,仅更新DeepSeek-LLM参数,加速训练并提升LLM对重排序视觉tokens的理解。

V. 评估 (Evaluation)

  • 基准: OmniDocBench v1.5,包含1,355页文档,涵盖9大类别。
  • 主要结果 (Main Results):
    • DeepSeek-OCR 2在OmniDocBench v1.5上达到91.09%的先进性能,V-tokenmax最低(1120)。
    • 相比DeepSeek-OCR基线,性能提升3.73%。
    • 阅读顺序(R-order)的编辑距离(ED)显著下降(从0.085降至0.057),表明DeepEncoder V2能有效选择和排列视觉tokens。
    • 在相同视觉token预算下,相比Gemini-3 Pro,DeepSeek-OCR 2在文档解析方面ED更低(0.100 vs 0.115)。
  • 改进空间 (Improvement Headroom):
    • DeepSeek-OCR 2在大多数情况下优于DeepSeek-OCR,但在某些文档类型(如报纸)上仍有提升空间。
    • 主要原因:视觉token上限较低,报纸训练数据不足。
  • 实际应用就绪度 (Practical Readiness):
    • 重复率显著降低(在线用户日志图像从6.25%降至4.17%,PDF数据生产从3.69%降至2.88%),验证了其逻辑视觉理解能力。

VI. 讨论与未来工作 (Discussion and Future Works)

  • 迈向真正的2D推理 (Towards Genuine 2D Reasoning):
    • LLM风格编码器和LLM解码器的两阶段1D因果推理级联有望实现真正的2D推理。
    • 编码器执行阅读逻辑推理(通过查询tokens重排序视觉信息),解码器执行视觉任务推理。
    • 未来需要更长的因果流tokens以支持多次重检和多跳重排序。
  • 迈向原生多模态 (Towards Native Multimodality):
    • DeepEncoder V2架构有望发展为统一的全模态编码器,通过模态特定可学习查询处理多种模态(图像、音频、文本)。
    • DeepSeek-OCR 2的LLM风格编码器架构是迈向原生多模态的关键一步。

VII. 结论 (Conclusion)

  • DeepSeek-OCR 2是DeepSeek-OCR的重大升级,通过DeepEncoder V2引入双向和因果注意力机制,有效地建模了文档阅读中的因果视觉流,显著提升了视觉阅读逻辑。
  • 光学文本阅读是LLM时代最实用的视觉任务之一,但仍是更广泛视觉理解领域的一小部分。
  • 展望未来,将继续优化和调整该架构以适应更多样化的场景,旨在实现更全面的多模态智能。

细节学习

代码学习

1、deepseek_ocr2.py 文件核心介绍

(1)分割符

self.view_seperator = nn.Parameter(torch.randn(n_embed) * embed_std)

self.view_seperator = nn.Parameter(...)

  • nn.Parameter:将普通张量标记为模型可训练参数(会被 PyTorch 的优化器更新);
  • torch.randn(n_embed):生成 1280 维的标准正态分布随机数;
  • * embed_std:用之前计算的标准差缩放随机数,符合 Xavier 初始化规则。

该参数最终会在 _pixel_values_to_embedding 方法中被拼接进视觉特征序列(torch.cat([local_features, global_features, self.view_seperator[None, :]], dim=0)),是 "全局 + 局部" 多视图特征融合的关键标识。

(2)完整前向结构

DeepseekOCR2ForCausalLM,几个重要模块

self.sam_model = build_sam_vit_b()

self.qwen2_model = build_qwen2_decoder_as_encoder()

self.view_seperator = nn.Parameter(torch.randn(n_embed) * embed_std)

self.language_model = init_vllm_registered_model(

vllm_config=vllm_config,

hf_config=self.text_config,

prefix=maybe_prefix(prefix, "language"),

architectures=architectures,

)

对应的为大语言模型结构architectures = ["DeepseekForCausalLM"]可配置

self.projector = MlpProjector(Dict(projector_type="linear", input_dim=896, n_embed=n_embed)) #将qwen2_model 转为大语言模型的embedding

forward

复制代码
    def forward(self,
                input_ids: torch.Tensor,
                positions: torch.Tensor,
                intermediate_tensors: Optional[IntermediateTensors] = None,
                inputs_embeds: Optional[torch.Tensor] = None,
                **kwargs: object):

        if intermediate_tensors is not None:
            inputs_embeds = None

        # NOTE: In v1, inputs_embeds is always generated at model runner, this
        # condition is for v0 compatibility
        elif inputs_embeds is None:
            vision_embeddings = self.get_multimodal_embeddings(**kwargs)
            inputs_embeds = self.get_input_embeddings(input_ids,
                                                      vision_embeddings)
            input_ids = None

        hidden_states = self.language_model(input_ids,
                                            positions,
                                            intermediate_tensors,
                                            inputs_embeds=inputs_embeds)

        return hidden_states

(1)第一次推理使用inputs_emeds,否则使用input_ids(新生成的)和intermediate_tensors

(2)get_input_embeddings实现了文本和视觉embedding的合并,调用vllm的通用能力

get_multimodal_embeddings:重点调用了_pixel_values_to_embedding进行处理:

(1)大图需要分块,小图不需要。大图分块后需要融合全局特征和局部特征,sam_model和qwen2_model都执行了两次,最后进行拼接融合。小图直接使用全局特征

(2)拼接后使用project输出

复制代码
# 初始化存储批次内所有图像视觉嵌入的列表
images_in_this_batch = []

# 推理阶段禁用梯度计算,提升效率+降低显存占用
with torch.no_grad():
    # 遍历批次内的每张图像(jdx为图像索引)
    for jdx in range(images_spatial_crop.size(0)):
        # 提取当前图像的局部裁剪块(batch_size固定为1,取第0维),转bfloat16降低显存
        patches = images_crop[jdx][0].to(torch.bfloat16)
        # 提取当前图像的全局视图
        image_ori = pixel_values[jdx]
        # 提取当前图像的裁剪瓦片数量(宽/高方向)
        crop_shape = images_spatial_crop[jdx][0]

        # ========== 1. 有局部裁剪块(大图分块)的场景 ==========
        if torch.sum(patches).item() != 0:  # patches非空=存在局部裁剪
            # 步骤1:SAM模型提取局部裁剪块的细节特征
            local_features_1 = self.sam_model(patches)
            # 步骤2:Qwen2解码器改造的编码器,增强局部特征的语义表征
            local_features_2 = self.qwen2_model(local_features_1)  
            # 步骤3:投影层将视觉特征(896维)映射到语言模型维度(1280维)
            local_features = self.projector(local_features_2)

            # 同理处理全局视图:SAM→Qwen2→投影层,得到全局特征
            global_features_1 = self.sam_model(image_ori)
            global_features_2 = self.qwen2_model(global_features_1) 
            global_features = self.projector(global_features_2)

            # 调试:打印特征维度(若PRINT_NUM_VIS_TOKENS=True)
            if PRINT_NUM_VIS_TOKENS:
                print('=====================')
                print('BASE: ', global_features.shape)  # 全局特征维度
                print('PATCHES: ', local_features.shape) # 局部特征维度
                print('=====================')

            # 维度重塑:将二维特征展平为一维序列(适配语言模型输入格式)
            global_features = global_features.view(-1, self.projector.n_embed)
            local_features = local_features.view(-1, self.projector.n_embed)

            # 拼接:局部特征 → 全局特征 → 视图分隔符(可学习的特殊嵌入)
            global_local_features = torch.cat([
                local_features, 
                global_features, 
                self.view_seperator[None, :]  # 分隔符token,区分全局/局部视图
            ], dim=0)
        
        # ========== 2. 无局部裁剪块(小图,无需分块)的场景 ==========
        else:
            # 仅处理全局视图:SAM→Qwen2→投影层
            global_features_1 = self.sam_model(image_ori)
            global_features_2 = self.qwen2_model(global_features_1) 
            global_features = self.projector(global_features_2)

            if PRINT_NUM_VIS_TOKENS:
                print('=====================')
                print('BASE: ', global_features.shape)
                print('NO PATCHES')
                print('=====================')

            # 维度重塑+拼接:全局特征 → 视图分隔符
            global_features = global_features.view(-1, self.projector.n_embed)
            global_local_features = torch.cat([
                global_features, 
                self.view_seperator[None, :]
            ], dim=0)

        # 将当前图像的融合特征加入批次列表
        images_in_this_batch.append(global_local_features)

# 返回批次内所有图像的视觉嵌入列表
return images_in_this_batch

(3)sam_vary_sdpa.py# 文件整体介绍

  • SDPA 适配:使用 PyTorch 原生缩放点积注意力,兼顾效率与稳定性,适合批量 OCR 推理;
  • 动态位置编码:绝对 / 相对位置编码均支持插值缩放,适配不同分辨率的输入图像;
  • 分层特征处理:neck 层融合 + 逐步下采样,既保留字符细节,又提升特征维度适配语言模型;
  • 轻量化设计:窗口注意力将注意力计算复杂度从 O (N²) 降至 O (N²/W)(W 为窗口尺寸),降低显存占用。

通过改造 SAM 的 ViT 编码器,既保留了 SAM 对图像细节的捕捉能力

  • 核心目标:将 1024×1024 输入图像通过 ViT 提取特征,经卷积下采样和特征融合后输出 896 维视觉特征,兼顾字符细节(SAM 优势)和语义表征(适配语言模型);
  • 技术基底:基于 SAM 的 ViT-B 架构改造,优化了注意力机制、位置编码和特征维度,专门适配 OCR 任务对字符位置 / 细节的敏感性;
  • 输入输出
    • 输入:[B, 3, 1024, 1024] 维度的 3 通道图像张量;
    • 输出:[B, 896, 64, 64] 维度的视觉特征张量(经两次下采样后),展平后可直接输入 Qwen2 模型增强。

(4)qwen2_d2e.py# 文件整体介绍。因果和非因果是如何设计的,是否有自定义注意力?

该文件 qwen2_d2e.pyDeepSeek-OCR-2 项目 中核心的跨模态编码模块,核心目标是将 Qwen2 大语言模型的解码器改造为「适配 OCR 任务的编码器」------ 通过定制化注意力掩码逻辑,实现「视觉特征非因果注意力 + 文本 / 查询特征因果注意力」的混合机制,兼顾 OCR 中视觉特征的全局交互需求和语言特征的自回归生成约束。

文件整体围绕 "解码器转编码器" 展开,核心包含 3 个关键组件,层级关系为:build_qwen2_decoder_as_encoder(工程化构建)→ Qwen2Decoder2Encoder(编码器封装)→ CustomQwen2Decoder(核心改造的 Qwen2 解码器)。

一、核心类与功能拆解

类 / 函数 核心作用
CustomQwen2Decoder 核心改造类:封装 Qwen2 原生模型,重写注意力掩码逻辑,实现因果 / 非因果混合注意力
Qwen2Decoder2Encoder 编码器封装:新增视觉查询嵌入层,拼接视觉特征与查询特征,适配 OCR 输入格式
build_qwen2_decoder_as_encoder 工程化构建函数:支持加载预训练权重,对外提供统一的编码器构建接口

二、因果(Causal)与非因果(Non-Causal)注意力的设计逻辑

核心设计依托 token_type_ids 区分 token 类型(0=非因果视觉token1=因果文本/查询token),通过重写注意力掩码生成逻辑实现混合注意力,具体步骤如下:

1. 核心约定:token_type_ids 定义

token_type_ids 值 对应 token 类型 注意力规则
0 视觉特征 token 非因果:全局互相可见
1 文本 / 查询特征 token 因果:仅可见自身及之前的 token

2. 关键实现步骤(从输入到掩码生成)

步骤 1:传递 token_type_ids(暂存)

CustomQwen2ModelInner(自定义 Qwen2 模型子类)的 forward 方法中,将输入的 token_type_ids 暂存为实例变量 _current_token_type_ids,供后续掩码生成时调用:

python

运行

复制代码
self._current_token_type_ids = token_type_ids  # 暂存token类型标识
步骤 2:重写掩码更新入口

重写 Qwen2 原生的 _update_causal_mask 方法(原生仅生成纯因果掩码),替换为调用自定义的 _create_custom_4d_mask 生成混合掩码:

步骤 3:核心:自定义 4D 掩码生成(_create_custom_4d_mask)

这是因果 / 非因果的核心实现,逐 batch 构建掩码矩阵(seq_len × seq_len),核心逻辑:

复制代码
# 初始化全负无穷掩码(负无穷表示该位置注意力被屏蔽)
mask = torch.full((seq_len, seq_len), fill_value=min_dtype, dtype=dtype, device=device)
# 分离视觉/文本token位置
image_positions = (type_ids == 0).nonzero(as_tuple=True)[0]  # 非因果token位置
text_positions = (type_ids == 1).nonzero(as_tuple=True)[0]   # 因果token位置

# 1. 非因果:视觉token之间互相可见(全局注意力)
if len(image_positions) > 0:
    mask[image_positions[:, None], image_positions] = 0.0  # 0表示允许注意力

# 2. 因果:文本token的注意力约束
for i, text_pos in enumerate(text_positions):
    # 文本token可看到所有视觉token(跨模态关注)
    if len(image_positions) > 0:
        mask[text_pos, image_positions] = 0.0
    # 文本token仅能看到自身及之前的文本token(时序因果)
    mask[text_pos, text_positions[:i+1]] = 0.0
  • 非因果逻辑:视觉 token 所在的行和列全部置 0,意味着每个视觉 token 能关注到所有其他视觉 token(全局交互,适配图像特征的空间关联性);
  • 因果逻辑:文本 token 仅能关注「所有视觉 token + 自身及之前的文本 token」,符合语言模型自回归生成的时序约束;
  • 掩码维度 :最终拼接为 4D 掩码(batch_size × 1 × seq_len × seq_len),适配 Qwen2 多头注意力的输入格式。

3. 设计意图

OCR 任务中:

  • 视觉特征(图像 token)需要全局交互(非因果)才能完整捕捉字符的空间位置、笔画关联等信息;
  • 文本 / 查询特征(语言 token)需要因果约束,保证生成文本的时序合理性(符合自回归语言模型的特性)。

四、补充:编码器封装层(Qwen2Decoder2Encoder)的适配逻辑

为了让改造后的解码器适配 OCR 视觉特征输入,Qwen2Decoder2Encoder 新增了关键适配逻辑:

  1. 视觉查询嵌入 :定义 query_768/query_1024 两个嵌入层,适配 144/256 两种数量的视觉查询 token;
  2. 特征拼接 :将输入的视觉特征 x 与查询嵌入拼接,生成 x_combined(视觉 token + 查询 token);
  3. token_type_ids 自动生成:拼接后的序列前半部分为 0(视觉,非因果)、后半部分为 1(查询,因果);
  4. 输出裁剪 :仅保留查询 token 对应的输出(y[:, n_query:, :]),作为编码器的最终输出(因果流查询特征)。

(5)查询嵌入的概念和实现

介绍下这里面的因果和非因果注意力,这两部分的输入分别是什么,调用这个模型的时候需多次forward得到结果吗?

复制代码
# 非因果输入:图像特征展平(token_type_ids=0)
x = x.flatten(2).transpose(1, 2)  # [bs, hidden_dim, H, W] → [bs, n_query, 896]
# 因果输入:查询嵌入(token_type_ids=1)
batch_query_imgs = param_img.unsqueeze(0).expand(bs, -1, -1)
# 拼接为完整输入
x_combined = torch.cat([x, batch_query_imgs], dim=1)  # [bs, 2*n_query, 896]
# 对应token_type_ids:前半段0(非因果)、后半段1(因果)
token_type_ids = torch.cat([torch.zeros(bs, n_query), torch.ones(bs, n_query)], dim=1)

常规场景下无需多次调用 forward,单次 forward 即可完成推理,核心依据:

1. 代码设计层面
  • 模型是端到端一体化设计Qwen2Decoder2Encoder.forward 接收图像特征后,内部完成 "特征展平→查询嵌入拼接→token_type_ids 生成→注意力计算→结果输出" 的全流程;

划线位置,这个作用是什么,为什么把它叫做查询嵌入,有什么意义

复制代码
self.query_768 = nn.Embedding(144, hidden_dimension)
self.query_1024 = nn.Embedding(256, hidden_dimension)

先明确命名来源,再拆解作用和意义:

二、"查询嵌入(Query Embedding)" 的命名原因

  1. 注意力机制的底层逻辑:Transformer 的核心是「Query(查询)-Key(键)-Value(值)」注意力范式:

    • Query:"我要找什么"(主动查询的向量);
    • Key/Value:"我有什么"(被查询的向量)。这里的query_768/1024是为视觉特征生成 "主动查询向量",用于和视觉特征做注意力交互,因此命名为 "查询嵌入"。
  2. 后缀 768/1024 的含义 :后缀对应 OCR 场景中常见的图像输入分辨率(如 768×768、1024×1024);而nn.Embedding的第一个参数(144=12×12、256=16×16)是分辨率下视觉特征展平后的 token 数量(H×W)------ 本质是 "适配不同分辨率的查询向量",因此用分辨率作为后缀区分。

三、查询嵌入的核心作用(结合代码逻辑拆解)

先梳理Qwen2Decoder2Encoder的 forward 流程,再看查询嵌入的核心作用:

预览

查看代码

生成失败,请重试

复制代码
graph TD
A[输入视觉特征x: [batch, 896, 16, 16]] --> B[展平为: [batch, 256, 896]]
B --> C{判断n_query长度}
C -->|144| D[用query_768生成查询向量]
C -->|256| E[用query_1024生成查询向量]
D/E --> F[扩展为batch维度: [batch, 256, 896]]
F --> G[拼接视觉特征+查询向量: [batch, 512, 896]]
G --> H[token_type_ids标记: 视觉=0(非因果),查询=1(因果)]
H --> I[送入改造后的Qwen2解码器]
I --> J[提取查询部分输出作为最终编码结果]

具体作用分 4 点:

1. 视觉特征的 "空间锚点"

视觉特征是二维空间特征(如 16×16),展平后是无序的一维序列;查询嵌入为每个空间位置的视觉 token 提供可学习的固定查询向量,作为注意力交互的 "锚点",让模型能精准对齐图像的空间位置特征(比如区分 "第一行第一个字" 和 "第二行第二个字")。

2. 实现 "非因果 + 因果" 注意力的核心桥梁

DeepSeek-OCR2 改造 Qwen2 解码器的核心是「视觉非因果注意力 + 文本因果注意力」:

  • 视觉特征部分(token_type_ids=0):做非因果注意力 (全可见,对应代码中mask[image_positions[:, None], image_positions] = 0.0),让模型全局看图像;
  • 查询嵌入部分(token_type_ids=1):做因果注意力 (只能看前面的 token,对应mask[text_pos, text_positions[:i+1]] = 0.0),同时能关注所有视觉特征(mask[text_pos, image_positions] = 0.0)。查询嵌入是 "因果查询端",连接 "全局视觉特征" 和 "顺序文本理解",模拟人类 "先看全图、再按顺序读文字" 的视觉逻辑。
3. 适配不同分辨率的视觉输入

OCR 场景中图像分辨率多样(如 768×768、1024×1024),对应的视觉特征展平长度不同(12×12=144、16×16=256);query_768/1024分别适配这两种长度,保证不同分辨率输入下都有匹配的查询向量,提升模型的多分辨率鲁棒性。

4. 维度对齐与解码器兼容

查询嵌入的维度(hidden_dimension)和视觉特征、Qwen2 解码器的隐藏层维度完全一致,拼接后能无缝送入解码器做注意力计算,避免维度不匹配问题,是 "视觉特征→解码器" 的关键适配层。

四、查询嵌入的设计意义(结合 DeepSeek-OCR2 的核心理念)

1. 实现 "Decoder→Encoder" 的改造(适配 OCR 场景)

Qwen2 原生是解码器(Decoder) ,天然做因果注意力(文本生成);但 OCR 需要编码器(Encoder) 做视觉特征的全局建模。查询嵌入是核心改造点:通过 "视觉非因果 + 查询因果" 的组合,把 Decoder 改造成适配 OCR 的 Encoder,既保留 Qwen2 的文本建模能力,又具备视觉全局编码能力。

2. 落地 "视觉因果流(Visual Causal Flow)" 核心设计

DeepSeek-OCR2 的核心卖点是「类人视觉编码」------ 人类阅读时先全局看图像(非因果),再按顺序理解文本(因果);查询嵌入模拟 "按顺序查询图像特征" 的过程,贴合人类阅读的因果逻辑,大幅提升复杂排版(多行、倾斜、图文混排)的 OCR 识别准确率。

3. 可学习的位置编码(替代传统静态编码)

相比 RoPE、Sinusoidal 等静态位置编码 ,查询嵌入是可学习的,能自适应不同图像的特征分布(比如模糊、低对比度、异形字体),提升模型对复杂场景的适配能力。

4. 提升推理效率

查询嵌入是预定义的可学习参数(仅 144/256 个 token),而非动态生成,能减少推理时的计算量;同时结合 vLLM 的高性能推理框架,进一步提升 OCR 的处理速度(尤其是 PDF / 长文本场景)。

总结

"查询嵌入" 命名源于 Transformer 的 QKV 注意力范式,核心作用是为视觉特征提供 "因果查询锚点",实现 "非因果视觉编码 + 因果文本理解" 的融合,是 DeepSeek-OCR2 将 Qwen2 解码器改造成适配 OCR 的编码器、落地 "视觉因果流" 核心设计的关键组件;后缀 768/1024 则是为了适配不同分辨率的图像输入,保证多场景的鲁棒性。

相关推荐
lxl13073 小时前
学习C++(5)运算符重载+赋值运算符重载
学习
AutumnorLiuu4 小时前
C++并发编程学习(一)——线程基础
开发语言·c++·学习
CS创新实验室4 小时前
关于 Moltbot 的学习总结笔记
笔记·学习·clawdbot·molbot
峥嵘life4 小时前
Android EDLA CTS、GTS等各项测试命令汇总
android·学习·elasticsearch
千谦阙听4 小时前
数据结构入门:栈与队列
数据结构·学习·visual studio
.小墨迹4 小时前
C++学习——C++中`memcpy`和**赋值拷贝**的核心区别
java·linux·开发语言·c++·学习·算法·机器学习
望忆5 小时前
关于《Cold & Warm Net: Addressing Cold-Start Usersin Recommender Systems》
学习
笔画人生5 小时前
教培机构用蓝耘MaaS做“个性化学习计划”:从学情分析到方案生成的完整链路
python·学习
red_redemption5 小时前
自由学习记录(113)
学习
im_AMBER6 小时前
Leetcode 109 链表的中间结点 | 删除链表的中间节点
数据结构·学习·算法·leetcode·链表