万字干货分享!基于PaddleMIX实现InternVL2多模态模型推理

(六)关于InternVL2的单卡、多卡推理 以InternVL2作为基础,介绍多模态大模型的训练、推理以及其它相关知识 阅读详情

文主要介绍如何基于 PaddleMIX 实现 InternVL2 多模态模型推理,转载自飞桨PaddlePaddle公众号。

InternVL 开源链接:

https://github.com/OpenGVLab/InternVL

作者介绍: 

企鹅火烈鸟:北京邮电大学研二、书生大模型开源社区核心贡献者、飞桨核心框架贡献者俱乐部成员、百度飞桨(厦门)人工智能产业赋能中心核心开发者

散步:书生大模型开源社区核心贡献者、飞桨开发者技术专家、飞桨核心框架贡献者俱乐部成员、百度飞桨(厦门)人工智能产业赋能中心特聘专家

PaddleMIX 介绍

PaddleMIX 是基于飞桨框架的多模态大模型开发套件,包含常见的 SOTA 多模态模型训练、推理组件。随着多模态在实际场景理解与逻辑推理能力的逐渐提高,已逐渐具备产业实践落地的潜力。结合百度飞桨(厦门)人工智能产业赋能中心的实际落地需求,我们决定一起在 PaddleMIX 套件上支持 InternVL2 多模态模型的推理工作,将业内先进的多模态模型带给飞桨生态开发者,提升开发者在不同落地场景下对于视觉感知、图文检索、图生文和多模态对话的实际体验效果。

图片
PaddleMIX 首页

基于 PaddleMIX 套件实现 InternVL2 多模态模型推理

在进行 PaddleMIX 模型的新增工作时,可遵循以下三个关键步骤:

1. 权重转换:将其他框架的模型推理权重转换为飞桨框架的推理模型权重,这一步能确保模型在飞桨环境中能够被正常解析加载和使用,过程中需要注意到特定数据结构的规则对齐与正确转换。

2. 模型组网转换:利用飞桨框架提供的 Paconvert 工具进行模型组网的转换。除此步骤外,还需要对模型的非常见API以及相关实现进行检查,以保证模型结构完整可推理;在 InternVL2 的合入工作中,主要难点在于预处理以及 transformers 接口部分的完整迁移推理。

3. 训练与推理精度对齐:在成功进行训练或推理前,需要对 PaddleMIX 套件中的模型结果进行精度对齐,以确保模型的推理结果与预期相符;对于可训练模型,我们则需要将对齐模型训练时 loss 下降的精度,以保证模型结果一致性。

权重转换

要想支持任意其他框架模型在飞桨框架上的新增工作,都需要先进行基础权重的适配转换。首先在 huggingface 上获取 InternVL-8B 的 safetensors 基础权重,合并整合为bin的单一文件格式,最后进入到进行飞桨框架权重的正式转换流程。值得注意的是, huggingface 上的多数模型存储为 bfloat16 的数据格式,但由于权重转化需要经过 numpy 的中间过程,考虑到 numpy 对bfloat16 的支持有限,在权重数据转换时需要对 bfloat16 数据格式权重进行额外转换处理:


is_bf16 = False  
if value.dtype == torch.bfloat16:  
    is_bf16 = True  
if is_bf16 is True:  
    # paddle 权重转换回 bf16  
    print("is_bf16")  
    paddle_tensor = paddle.to_tensor(tensor.cpu().numpy())  
    paddle_tensor = paddle_tensor.astype(paddle.bfloat16) 

在权重转换至飞桨框架权重的过程中,由于不同深度学习框架在线性层权重矩阵的行列顺序上存在差异,因此在权重的转换过程中,我们仍需要对线性层权重矩阵进行额外的转置操作,以保证最后结果对齐:


if ('linear' in torch_key) or ('proj' in torch_key) or ('vocab' in torch_key and 'weight' in torch_key) or ("attn.qkv" in torch_key) \  
    or ("mlp.fc1" in torch_key) or ("mlp.fc2" in torch_key) or ("feed_forward.w1" in torch_key) or ("feed_forward.w2" in torch_key) or ("feed_forward.w3" in torch_key) \  
    or ("language_model.output.weight" in torch_key):  
    if tensor.ndim >= 2:  
        tensor = tensor.transpose(0, 1) 

对于卷积层,需要额外对卷积形状进行转置处理,已适配飞桨框架对应数据格式进行推理:


elif 'conv' in torch_key and 'weight' in torch_key:  
    # 对于卷积层,需要转置 weight 张量的形状  
    if tensor.ndim == 4:  # 2D 卷积  
        tensor = tensor.transpose(2, 3, 1, 0)  
    elif tensor.ndim == 5:  # 3D 卷积  
        tensor = tensor.transpose(2, 3, 4, 1, 0) 

完整处理代码如下所示,运行后可以得到初始推理所需的 model_state.pdparams  模型文件。


for torch_key, value in pytorch_state_dict.items():  
    is_bf16 = False  
    paddle_key = torch_key  
    tensor = value.clone().detach()  
    if value.dtype == torch.bfloat16:  
        is_bf16 = True  
        tensor = tensor.to(torch.float32)  
    if ('linear' in torch_key) or ('proj' in torch_key) or ('vocab' in torch_key and 'weight' in torch_key) or ("attn.qkv" in torch_key) \  
        or ("mlp.fc1" in torch_key) or ("mlp.fc2" in torch_key) or ("feed_forward.w1" in torch_key) or ("feed_forward.w2" in torch_key) or ("feed_forward.w3" in torch_key) \  
        or ("language_model.output.weight" in torch_key):  
        if tensor.ndim >= 2:  
            tensor = tensor.transpose(0, 1)  
    elif 'conv' in torch_key and 'weight' in torch_key:  
        # 对于卷积层,需要转置 weight 张量的形状  
        if tensor.ndim == 4:  # 2D 卷积  
            tensor = tensor.transpose(2, 3, 1, 0)  
        elif tensor.ndim == 5:  # 3D 卷积  
           tensor = tensor.transpose(2, 3, 4, 1, 0)  
    elif 'attention' in torch_key and 'weight' in torch_key:  
        if tensor.ndim >= 2:  
            tensor = tensor.transpose(0, 1)  
          
    if is_bf16 is True:  
        # 转换回 bf16  
        print("is_bf16")  
        paddle_tensor = paddle.to_tensor(tensor.cpu().numpy())  
        paddle_tensor = paddle_tensor.astype(paddle.bfloat16)  
    else:  
        paddle_tensor = paddle.to_tensor(tensor.cpu().numpy())  
      
    paddle_state_dict[paddle_key] = paddle_tensor  

  • 模型组网

在获取模型文件之后,可直接进入到正式的模型组网流程。我们推荐使用飞桨开发团队推出的一栈式组网转换工具—— Paconvert 进行模型组网的快速转换。Paconvert 能够自动将其深度学习框架训练或推理的代码,转换为飞桨框架的代码,方便快速自动地模型代码迁移。其中代码行数平均转换率约为90+%,Llama 等大语言模型推理转换率可达100%。利用官方转换工具,我们能够在飞桨框架中顺利进行模型迁移与组网工作。

图片
https://github.com/PaddlePaddle/PaConvert

Paconvert 转换时会尽量保持原代码的风格与结构,这就方便我们进行模型的组网工作,只需要一行 API,我们就可以很容易得到完整的文件:

python paconvert/main.py --in_dir torch_project [--out_dir paddle_project] [--exclude_dirs exclude_dirs] [--log_dir log_dir] [--log_level "INFO"] [--run_check 1]  

转换完成后,工具将会打印转换总结,包含总 API 数、成功转换 API 数、不支持转换 API 数、转换率。

对于成功转换的 API :代码风格会略有变化,会补全 API 全名、补全参数关键字、移除注释、移除多余空行。因为代码在扫描识别的过程中,注释、空行等无法识别,将被移除。

对于不支持转换的 API :将补全为 API 全名,同时在行前通过>>>>>>的形式加以标记,用户需要对该API进行人工手动转换,然后删除>>>>>>标记。

===========================================  
PyTorch to Paddle Convert Start ------>:  
===========================================  
Start convert file: /workspace/PaConvert1/test_code.py --> /workspace/PaConvert1/paddle_project/test_code.py  
[test_code.py:1] remove 'import torch'  
[test_code.py:2] remove 'import torch.nn as nn'  
[test_code.py:3] remove 'import torch.optim as optim'  
[test_code.py:4] remove 'import torch.nn.functional as F'  
[test_code.py:5] remove 'from torch.nn import Linear'  
[test_code.py:6] remove 'import mmcv'  
[test_code.py] add 'import paddle' in line 1  
[test_code.py:1] [Success] Convert torch.nn.Module to Paddle  
[test_code.py:13] [Not Support] convert mmcv.cnn.ConvModule to Paddle is not supported currently  
[test_code.py:14] [Success] Convert torch.nn.MaxPool2d to Paddle  
[test_code.py:16] [Success] Convert torch.nn.Linear to Paddle  
[test_code.py:17] [Success] Convert torch.nn.Linear to Paddle  
[test_code.py:18] [Success] Convert torch.nn.Linear to Paddle  
[test_code.py:24] [Success] Convert torch.flatten to Paddle  
[test_code.py:27] [Success] Convert torch.add to Paddle  
[test_code.py:31] [Success] Convert Class Method: torch.nn.Module.parameters to Paddle  
[test_code.py:31] [Success] Convert torch.optim.SGD to Paddle  
[test_code.py:32] [Success] Convert torch.optim.lr_scheduler.MultiStepLR to Paddle  
[test_code.py:35] [Success] Convert torch.rand to Paddle  
[test_code.py:36] [Success] Convert Class Method: torch.Tensor.sum to Paddle  
[test_code.py:38] [Success] Convert Class Method: torch.nn.Module.zero_grad to Paddle  
[test_code.py:39] [Success] Convert Class Method: torch.Tensor.backward to Paddle  
[test_code.py:40] [Success] Convert Class Method: torch.optim.Optimizer.step to Paddle, just remain the same  
Finish convert /workspace/PaConvert1/test_code.py --> /workspace/PaConvert1/paddle_project/test_code.py  
  
  
===========================================  
Convert Summary:  
===========================================  
There are 16 Pytorch APIs in this Project:  
 15  Pytorch APIs have been converted to Paddle successfully!  
 1  Pytorch APIs are not supported to convert to Paddle currently!  
 Convert Rate is: 93.750%  
  
For these 1 Pytorch APIs that currently do not support to convert, which have been marked by >>> before the line,  
please refer to [https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/model_convert/convert_from_pytorch/pytorch_api_mapping_cn.html]  
and convert it by yourself manually. In addition, these APIs will be supported in future.  
  
Thank you to use Paddle Code Convert Tool. You can make any suggestions  
to us by submitting issues to [https://github.com/PaddlePaddle/PaConvert].  
  
****************************************************************  
______      _____                          _  
| ___ \    / ____|                        | |  
| |_/ /_ _| |     ___  _ ____   _____ _ __| |_  
|  __/ _  | |    / _ \| \_ \ \ / / _ \ \__| __|  
| | | (_| | |___| (_) | | | \ V /  __/ |  | |_  
\_|  \__,_|\_____\___/|_| |_|\_/ \___|_|   \__|  
 
***************************************************************  

图片
internvl2组网整体展示

通过 Paconvert 在 API 层面快速转换映射,可以很容易得到模型视觉编码器 paddlemix/models/internvl2/internvl_chat/modeling_intern_vit.py、文本编码器 paddlemix/models/internvl2/internlm2/modeling_internlm2.pypaddlemix/models/internvl2/phi3/modeling_phi3.py 等模型的对应飞桨框架实现。其中核心组网模块例如 InternVisionModel InternLM2ForCausalLM Phi3ForCausalLM;


# Modified from transformers.model.llama.modeling_llama.LlamaForCausalLM  
class InternLM2ForCausalLM(InternLM2PretrainedModel):  
    _auto_class = 'AutoModelForCausalLM'  
  
    _tied_weights_keys = ['output.weight']  
  
    def __init__(self, config):  
        super().__init__(config)  
        self.model = InternLM2Model(config)  
        self.vocab_size = config.vocab_size  
        self.output = nn.Linear(config.hidden_size, config.vocab_size, bias_attr=False)  
# ...... 后续省略  

对于语言模块的子核心模块组网涉及到具体不同 DecoderLayer ,在组网过程中需要详细检查各子模块是否能够进行单元测试和正常推理,替换部分无法使用 Paconvert 转换的对应 API 至飞桨框架3.0最新 API 。

class InternLM2DecoderLayer(nn.Layer):  
    def __init__(self, config: InternLM2Config):  
        super().__init__()  
        self.hidden_size = config.hidden_size  
  
        self.attention = INTERNLM2_ATTENTION_CLASSES[config.attn_implementation](config=config)  
  
        self.feed_forward = InternLM2MLP(config)  
        self.attention_norm = InternLM2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)  
        self.ffn_norm = InternLM2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)  
  
    def forward(  
        self,  
        hidden_states: paddle.Tensor,  
        attention_mask: Optional[paddle.Tensor] = None,  
        position_ids: Optional[paddle.Tensor] = None,  
        past_key_value: Optional[Tuple[paddle.Tensor]] = None,  
        output_attentions: Optional[bool] = False,  
        use_cache: Optional[bool] = False,  
        **kwargs  
    ) -> Tuple[paddle.Tensor, Optional[Tuple[paddle.Tensor, paddle.Tensor]]]:  
        """  
        Args:  
            hidden_states (`paddle.Tensor`): input to the layer of shape `(batch, seq_len, embed_dim)`  
            attention_mask (`paddle.Tensor`, *optional*):  
                attention mask of size `(batch_size, sequence_length)` if flash attention is used or `(batch_size, 1,  
                query_sequence_length, key_sequence_length)` if default attention is used.  
            output_attentions (`bool`, *optional*):  
                Whether or not to return the attentions tensors of all attention layers. See `attentions` under  
                returned tensors for more detail.  
            use_cache (`bool`, *optional*):  
                If set to `True`, `past_key_values` key value states are returned and can be used to speed up decoding  
                (see `past_key_values`).  
            past_key_value (`Tuple(paddle.Tensor)`, *optional*): cached past key and value projection states  
        """  

除了飞桨框架集层面的组网对齐,还需要手动修改适配 PaddleNLP 相关的 paddlenlp.transformers 模块API,支持对应配置文件以及模型相关工具链、flash-attention实现的正常调用。PaddleNLP 3.0 升级总计涵盖了 80+ 业界主流的开源大语言模型,覆盖了大模型推理所需的大部分 transformers api 支持,只需要在前置加上 PaddleNLP 即可一键替换原 API ,即可获得完整支持。


from paddlenlp.transformers import LlamaForCausalLM  
from paddlenlp.transformers.model_outputs import CausalLMOutputWithPast  
from paddlenlp.transformers.model_utils import PretrainedModel

对于形状转换部分,需要注意飞桨框架的 Shape 默认使用list进行表达,而不是元组的形式,有关形状推导部分需要详细检查:

if attn_output.shape != [bsz, self.num_heads, q_len, self.head_dim]:  
    raise ValueError(  
        f'`attn_output` should be of size {(bsz, self.num_heads, q_len, self.head_dim)}, but is'  
        f' {attn_output.shape}'  

 

除了基础的飞桨框架所支持的 paddle.nn.functional.flash_attention 注意力实现替换,对于该模型组网还需额外 flash-attention 组件的支持 paddlemix/models/internvl2/bert_padding.py ,该文件主要实现了一种高效的序列填充 (padding) 和解填充 (unpadding) 方法,提高训练效率。

为了快速验证整体组网结果,可显式指定 attn_implementation='eager',该命令将使用最基础 Attention 模式进行推理,便于快速组网后跑通验证。

除了主要组网流程,为了支持 PaddleMIX 的 auto 模式推理,还需要在对应涉及注册表文件下注册新增InternVL2模型:

paddlemix/auto/modeling.py paddlemix/auto/processing.pypaddlemix/auto/tokenizer_mapping.yamlpaddlemix/trainer/trainer.py

以及在最后增加对应代码的单元测试覆盖,确保效果可复现与稳定性tests/models/test_internvl2.py。


def create_and_check_model(self, pixel_values):  
    model = InternVLChatModel(config=self.get_config())  
    model.eval()  
    generation_config = dict(max_new_tokens=1024, do_sample=False)  
    with paddle.no_grad():  
        result = model.chat(  
            tokenizer=self.tokenizer,  
            pixel_values=pixel_values,  
            question='Who are you?',  
            generation_config=generation_config,  
        )  
  
    self.parent.assertIsNotNone(result)  

最后,只需综合配置多种文本编码视觉编码器调用入口,即可快速切换不同配置情况下的 InternVL2 模型推理实现。

class InternVLChatModel(MixPretrainedModel):  
    config_class = InternVLChatConfig  
    main_input_name = 'pixel_values'  
    _no_split_modules = ['InternVisionModel', 'LlamaDecoderLayer', 'InternLM2DecoderLayer',  
                         'Phi3DecoderLayer', 'Qwen2DecoderLayer']  
    _supports_flash_attn_2 = True  
  
    def __init__(self, config: InternVLChatConfig, vision_model=None, language_model=None):  
        super().__init__(config)  
  
        image_size = config.force_image_size or config.vision_config.image_size  
        patch_size = config.vision_config.patch_sizepatch_size=config.vision.patch_size  
        self.patch_size = patch_size  
        self.select_layer = config.select_layer  
        self.template = config.template  
        self.num_image_token = int((image_size // patch_size) ** 2 * (config.downsample_ratio ** 2))  
        self.downsample_ratio = config.downsample_ratio  
        self.ps_version = config.ps_version  
  
        logger.info(f'num_image_token: {self.num_image_token}')  
        logger.info(f'ps_version: {self.ps_version}')  
        if vision_model is not None:  
            self.vision_model = vision_model  
        else:  
            self.vision_model = InternVisionModel(config.vision_config)  
        if language_model is not None:  
            self.language_model = language_model  
        else:  
            if config.llm_config.architectures[0] == 'LlamaForCausalLM':  
                self.language_model = LlamaForCausalLM(config.llm_config)  
            elif config.llm_config.architectures[0] == 'InternLM2ForCausalLM':  
                self.language_model = InternLM2ForCausalLM(config.llm_config) # [2048, 92553]  
            elif config.llm_config.architectures[0] == 'Phi3ForCausalLM':  
                self.language_model = Phi3ForCausalLM(config.llm_config)  
            elif config.llm_config.architectures[0] == 'Qwen2ForCausalLM':  
                self.language_model = Qwen2ForCausalLM(config.llm_config) # [151655, 896]  
            else:  
                raise NotImplementedError(f'{config.llm_config.architectures[0]} is not implemented.')  

在完成权重转换和初步组网工作后,通过简单的预处理即可测试 InternVL2 模型的效果。InternVL2 在动态分辨率支持方面表现更为出色,但预处理过程比其他 VLM 模型复杂,需要严格处理对齐推理结果,以确保之后推理精度对齐工作顺利进行。注意到 InternVL2 的预处理相关部分paddlemix/datasets/internvl_dataset.py, InternVL2 模型存在与其他VLM模型不同的预处理模块:dynamic_preprocess。该模块支持动态处理输入图片,并能均匀打散成 image_size*image_size 的子块进行处理。由于这个模块的特殊性,模型预处理的适配更加复杂。在常规的 PaddleMIX 预处理流程中并不涉及这个模块,我们需要手动加入这个模块到视觉预处理流程中,并保证前向反向不被此模块影响。

def dynamic_preprocess(self, image, min_num=1, max_num=6, image_size=448):  
        orig_width, orig_height = image.sizeorig_width,orig_eight=图像大小  
        aspect_ratio = orig_width / orig_height  
  
        # calculate the existing image aspect ratio  
        target_ratios = set(  
            (i, j)  
            for n in range(min_num, max_num + 1)  
            for i in range(1, n + 1)  
            for j in range(1, n + 1)  
            if i * j <= max_num and i * j >= min_num  
        )  
        target_ratios = sorted(target_ratios, key=lambda x: x[0] * x[1])  
  
        # find the closest aspect ratio to the target  
        target_aspect_ratio = self.find_closest_aspect_ratio(  
            aspect_ratio, target_ratios, orig_width, orig_height, image_size  
        )  
  
        # calculate the target width and height  
        target_width = image_size * target_aspect_ratio[0]  
        target_height = image_size * target_aspect_ratio[1]  
        blocks = target_aspect_ratio[0] * target_aspect_ratio[1]  
  
        # resize the image  
        resized_img = image.resize((target_width, target_height))  
        processed_images = []  
        for i in range(blocks):  
            box = (  
                (i % (target_width // image_size)) * image_size,  
                (i // (target_width // image_size)) * image_size,  
                ((i % (target_width // image_size)) + 1) * image_size,  
                ((i // (target_width // image_size)) + 1) * image_size,  
            )  
            # split the image  
            split_img = resized_img.crop(box)  
            processed_images.append(split_img)  
        assert len(processed_images) == blocks  
        if self.use_thumbnail and len(processed_images) != 1:  
            thumbnail_img = image.resize((image_size, image_size))  
            processed_images.append(thumbnail_img)  
        return processed_images  

至此,模型组网与运行测试基本完成,后续进入到模型预处理与模型精度对齐阶段。

精度对齐

精度对齐是飞桨框架模型适配中的最后一步,在进行更严格的对比前,我们可以用不同组件进行快速实例化精度对比测试,待组件测试通过后,最后再结合文本与视觉编码器,形成整体模型组网对齐推理与训练精度。

if __name__ == "__main__":  
    model = Phi3DecoderLayer(Phi3Config(),32)模型=Phi3DecoderLayer(Phi3Config(),32)  
    model = model.astype("float16")  
    dummy_tensor = paddle.randn([1, 1024, 3072]).cuda()  
    dummy_tensor = dummy_tensor.astype("float16")  
    out = model(dummy_tensor)  
  
if __name__ == "__main__":  
    model = InternLM2DecoderLayer(InternLM2Config())  
    model = model.astype("float16")  
    dummy_tensor = paddle.randn([1, 1024, 4096]).cuda()  
    dummy_tensor = dummy_tensor.astype("float16")  
    out = model(dummy_tensor)  
  
if __name__ == "__main__":  
    model = InternVisionEncoder(InternVisionConfig())  
    input = paddle.randn([1, 196, 3200])  
    out = model(input)  

这里飞桨官方还提供了一项便于使用的对照工具:Padiff,我们可以很容易通过 auto_diff 接口,自动对不同框架的组网后模型,进行推理精度的自动对齐,如果出现问题,将会提示精度diff第一次出现的位置:

from padiff import auto_diff  
import torch  
import paddle  
  
class SimpleModule(torch.nn.Module):  
  def __init__(self):  
      super(SimpleModule, self).__init__()  
      self.linear1 = torch.nn.Linear(100, 10)  
  def forward(self, x):  
      x = self.linear1(x)  
      return x  
  
class SimpleLayer(paddle.nn.Layer):  
  def __init__(self):  
      super(SimpleLayer, self).__init__()  
      self.linear1 = paddle.nn.Linear(100, 10)  
  def forward(self, x):  
      x = self.linear1(x)  
      return x  
  
module = SimpleModule()  
layer = SimpleLayer()  
  
inp = paddle.rand((100, 100)).numpy().astype("float32")  
inp = ({'x': torch.as_tensor(inp) },  
     {'x': paddle.to_tensor(inp)})  
  
auto_diff(module, layer, inp, atol=1e-4, auto_init=True)  

不仅限于推理精度对齐,Padiff 覆盖了模型在多种运行情况下的精度对齐,并支持自定义的 Loss 函数以及优化器参与精度对齐工作,大大减轻了模型精度对齐工作的难度:

1.权重拷贝阶段(当设置参数 auto_weights 为 True 时)

2.模型前反向对齐阶段

3.模型权重&梯度对齐阶段

如果运行过程中每一层网络的精度都正常对齐,最后的分析结果和对应报告将如下列结果所示:


[AutoDiff] Your options:  
{  
  atol: `0.0001`  
  auto_init: `True`  
  single_step: `False`  
  use_loss: `False`  
  use_opt: `False`  
  rtol: `1e-07`  
  compare_mode: `mean`  
}  
[AutoDiff] Assign weight success !!!  
[AutoDiff] check cfg {'atol': 0.0001, 'rtol': 1e-07, 'compare_mode': 'mean'}  
[AutoDiff] Checking report in /workspace/PaDiff/padiff_dump/SimpleModule(base_model)/auto_diff and /workspace/PaDiff/padiff_dump/SimpleLayer(raw_model)/auto_diff  
[AutoDiff] Check grads cfg: {'atol': 0.0001, 'rtol': 1e-07, 'compare_mode': 'mean'}  
[AutoDiff] Checking grads in /workspace/PaDiff/padiff_dump/SimpleModule(base_model)/auto_diff and /workspace/PaDiff/padiff_dump/SimpleLayer(raw_model)/auto_diff  
[AutoDiff] grads compared.  
[AutoDiff] SUCCESS !!!  

​​​​​​​此外,Padiff 还支持细粒度更小的精度对齐模式,对于一些较小的精度差别积累,可能会导致精度差别 diff 结果层与实际精度误差层不同。例如:auto_diff 接口发现了精度 diff ,但 log 信息中定位到的位置却是 Linear 等常见的 API ,检查后未发现 Linear 存在 diff 。此时可以在接口参数中打开 single_step 模式的开关,进行对齐检查的同时不断调整 atol 、 rtol 等参数,最后调整可定位到真正的模型层精度偏移位置。

图片

合理运用 Padiff ,可加快任意框架模型在飞桨框架3.0下的精确转换,在精度一致的模型下进行正常训练与推理工作。

结语

总的来说,进行 PaddleMIX 模型新增时,需遵循三步骤:首先,进行飞桨权重转换,确保模型能在飞桨中正常解析使用;其次,利用飞桨的 Paconvert 工具进行模型组网转换,针对非常见 API 以及相关实现进行定制修改,确保预处理正确,视觉模型与语言模型组网结构完整可推理;最后,进行精度对齐,确保推理和训练结果与预期目标相符。

「文智助手」全场景办公AI助理AI+OPC全流程实践方案(大赛作品) 阅读详情

相关推荐

船载 OpenHarmony AIS 航海工作台:告警与防碰撞预警系统

船载OpenHarmony AIS航海工作台的告警与防碰撞系统,集成十余类告警(超速、偏航、会遇、SOS等),通过网格空间索引实现高效邻近判定,保障实时性。告警管理器统一调度规则、去重、通知与日志,支持悬浮球、语音、跑马灯、弹窗多渠道触达,确保航行安全。SOS紧急通道独立运行,避免干扰。系统设计强调性能优化与多场景适配,为航海安全提供核心支撑。

专注于计算机研发知识和资讯分享 113

PaddleMIX 开源项目教程

PaddleMIX 开源项目教程 项目介绍 PaddleMIX 是基于飞桨的多模态大模型开发套件,聚合图像、文本、视频等多种模态,覆盖视觉语言预训练、文生图、文生视频等丰富的多模态任务。它提供开箱即用的开发体验,同时满足开发者灵活定制需求,探索通用人工智能。 项目快速启动 环境准备 首先,克隆 PaddleMIX 仓库并安装必要的依赖: # 克隆仓库 git clone https://githu...

gitblog_00482的博客 1222

从东南大学906被刷到调剂过程(内含个人感想)

介绍了自己在看到初试成绩,到后期复习以及调剂的全过程,当中也包含了自己的复试中的感想,希望大家理性看待。

Philo的博客 2856

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 225

头歌操作系统2.3系统调用命令ls执行的系统调用

设置版本0内核为分析对象。然后一直c直到虚拟机出现。然后一直c就是答案了。

m0_74128952的博客 1万+

5G(NR)物理层面试问答

1.什么是参数集(Numerologies)? 答:在5G中由于其频段很宽,设置了不同的子载波带宽,另根据频段、循环前缀、帧结构等组成了参数集。 2.5G中的循环前缀有几种? 答:5G网络支持5种子载波间隔,有两种循环前缀(正常和扩展)。其中:参数集2,即子载波间隔60kHz支持常规循环前缀和扩展循环前缀。 3.5G无线网络在下行(DL)和上行(UL)均使用OFDM波形? 答:5G网络下行链路(DL)和上行链路(UL)使用的波形及处理见下图: 4.5G物理层帧和子帧是多长时间? 答:5G.

starts1990的博客 2378

6 款电商 AI 图片生成软件实测|国内 + 跨境卖家工具清单

电商 AI 作图工具已经从 "能不能用" 进入了 "好不好用" 的阶段。对于绝大多数卖家而言,现在的 AI 工具已经可以覆盖 60%-80% 的基础商品图需求,显著降低拍摄和设计成本。选择工具的核心逻辑不是 "哪款最强",而是 "哪款最适配你的品类、平台规模和团队能力"。垂直电商工具胜在工作流效率,通用生图工具强在创意上限,模板类工具赢在上手速度。建议根据自身业务阶段,搭配 1-2 款主力工具 + 1 款辅助工具,形成适合自己的视觉生产流程。

Mardi_Ladin的博客 398

全志Longan和Tina系统T113-S3-(Tina Linux 系统介绍)

Tina Linux是全志科技基于Linux内核开发的针对智能硬件类产品的嵌入式软件系统。Tina Linux基于openwrt-14.07 版本的软件开发包,包含了 Linux 系统开发用到的内核源码、驱动、工具、系统中间件与应用程序包。Tina系统软件架构如图所示。从下至上分别为Kernel && Driver、Libraries、System Services、Applications 四层。

szembed的博客 6337

我用 GPUWorks 在 M1 Pro 上搭了个发票识别原型

公司里经常要看电子发票。我想先做个小原型:把 PDF 发给一个自己部署的图文模型,让它提取发票类型、日期、交易双方和金额,再把结果交给同事核对。这个原型不用先接财务系统,先看看从部署到调用要走多少步,模型返回的内容能不能帮上忙。

鸽芷咕的博客 2万+

域用户无法修改密码问题的解决方案

问题描述:加域的电脑无法更改密码,提示“无法更新密码,为新密码提供的值不符合字符域的长度、复杂度或历史要求”。 问题原因:域控制器中相关设置问题,主要如下图所示(如启用复杂性、最短期限和强制密码历史) 解决方案:在域控制器中更改对应的密码策略即可: ① 禁用复杂性要求 ② 最短使用期限改为0天 ③ 强制密码历史改为0 如果出现无法更改的情况,如下图箭头所指的图标所示 代表需要在域控制器的组策...

运维日记 3万+

(6)NUC980 SPI Nand 启动

方式一:下载到SPI-NAND-Flash中,这种方式可以将程序固化到SPIflash中,可以掉电保存。第二种方式下载到DDR中程序掉电丢失,但是DDR调试方便,时候调试的时候使用。之前的设置都是基于SD卡启动,今天测试一下是用SPI flash启动。方式二: 下载到DDR中,①设置为USB启动②下载到DDR中③运行。1:烧写BootLoader。

卤煮小鱼的博客 1754

您您这可以把问小白的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭

第三层是格式编译层。这个决策背后的判断很清晰:一个批量导出工具的价值,不在于“试三次”,而在于你真正用它处理了几十份技术文档、访谈记录或课程讲义之后,它是否值得留在你的工作流里。问小白的会话列表通过分页接口加载,AI导出鸭 在页面运行时建立旁路监听,捕获每一次分页请求返回的完整对话清单,包括会话 ID、标题、时间戳和隐藏的元数据字段。让AI导出回归优雅——这句话说的是:导出不该是体力活,而应该是一次完整的、可预期的文件交付。注意:这里的“批量”指的是左侧列表里的多个独立会话,不是一条会话内的多轮对话。

laoyunsi的博客 246

Android开发工程师面试问题与参考答案

这是一份Android开发工程师职位面试指南,主要针对自研OS开发岗位。岗位要求3年以上独立开发经验,熟悉Android平台UI设计、四大组件和Java基础。面试问题覆盖五大核心领域:基础知识、开发经验、技术深度、问题解决和性能优化。文章提供了典型面试问题及专业参考答案,帮助应聘者准备关键技术点,如多线程处理、HashMap与ConcurrentHashMap区别、Handler机制等。同时建议应聘者结合项目经验展示优化能力,并注意公司提供完善的薪酬福利和团队文化。

郑伟强dev的专栏 893

【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端

上一篇讲了 MCP 的概念:标准协议、三大角色、M+N 替代 M×N。

nice_lcj520的博客 501

AI自瞄原理剖析(一)屏幕内容循环截取及代码实现

尽管Yolo框架在推理时其实是可以输入不同大小的图片的,但这些作者大多不会去处理图像尺寸的改变,所以目前大部分开源源码主要是以输入320或者640尺寸的图像为主。只要截图的效率足够快,能够满足一秒采集60张图片,也就是稳定的截图速度达到60帧以上,那么就可以实现内存级别的AI锁死自瞄效果。这里强调了截图速度对于最终实现特定自瞄效果的重要性,只有达到这样的速度标准,才能让整个自瞄相关的功能在内存层面有效地运作起来。在实现自瞄功能的情境下,只需要以游戏准星为中心向外的正方形区域图像就够了,没必要进行全屏截取。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1097

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

河道漂浮物目标检测数据集

目标检测,yolo,河道漂浮物目标检测数据集

DL_data_set的博客 201

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

AI Agent之核心框架

A: 显式 Thought 有三类价值:可解释性(便于人类审计)、可调试性(定位哪一步选错工具)、学习信号(可做监督微调或评估中间步骤质量)。ReAct 把推理与 可执行行动 绑定,每一步行动后都有 真实 Observation 反馈,从而用工具结果约束生成,降低闭卷幻觉。做完不等于结束——还要 评估做得好不好,把 教训 记下来,下次 带着教训重试,反思作为 记忆,影响后续尝试的策略。工作流程:Action → Evaluation → Reflection → Retry。A: 普通 CoT 只在。

剑雨巍巍的博客 199

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

AI 应用开发工程师技术实践:大模型接入、通用组件封装与性能优化

本文提出AI应用从PoC到生产的核心挑战:模型调用的持续可用、可控与可优化。通过构建统一LLM网关实现多供应商路由与故障转移,封装对话、工具调用与RAG组件以解耦业务逻辑,结合前缀缓存、批处理与流式背压治理等性能优化手段,形成“接通→接稳→接快”的工程路径,最终以工程化能力决定AI应用的生产可用性。

2301_79189962的博客 558

AI前沿日报 · 2026-11-04 | 祛魅时刻:Astra“纯读权重“神话的崩塌

①Astra"裸权重通吃"被spaCy创始人Honnibal精准祛魅——仅1/3实验真裸读,数学能力提升依赖Python+50次迭代;②Simon Willison用Qwen 3.8-27B端侧复现权重空间编程;③Nvidia开源Auto-Ontology自动知识图谱;④$800开源全域抓取机器人Stringman;⑤OpenAI悄然重开Codex训练开关引信任危机;⑥DeepMind发布Gemini 4 Argon机器人基础模型;⑦美国科技巨头隐性AI债务达3.2万亿美元,6个月增90%。

johnsong2009的博客 574

大模型 Embedding 与向量相似度详解

Embedding 解决的问题:计算机不懂文字,但懂数字│▼文本 → 向量(1024维浮点数数组)│▼相似度解决的问题:怎么判断两个向量(文本)有多接近│▼余弦相似度:看向量方向的夹角,越接近0°越相似│▼最终效果:语义搜索——理解意思,而非字面匹配一句话总结:Embedding 把文字变成数字,余弦相似度比较数字的方向,两者结合实现了"理解语义"的搜索。

T3165919332的博客 90

GPT-1 架构和计算细节

下面配合框图,对 GPT-1 的每个组件做公式展开 + 数值实例(配置:12 层 × 768,12 头,FFN 3072,词表 40478,共 117M 参数)。GPT-1 把翻译模型的编码器-解码器砍掉一半,只留解码器,然后以"预测下一个词"为目标在 BooksCorpus 上预训练。与 2017 原版的四个架构差异(框图中标 ★):h0=E[token]+Epos[position],E∈R40478×768, Epos∈R512×768h^0 = E[\text{token}] + E_{pos}[\

eloudy的专栏 278

终端 AI 审计与 “龙虾” 类智能体风险治理:从可见性到闭环溯源

生成式 AI 办公普及之后,数据泄露风险逐步下沉到终端。员工将合同、源代码、客户资料粘贴至公有大模型,以及龙虾(OpenClaw)这类本地开源 AI 智能体的滥用,成为企业安全新挑战。传统网络边界防护存在审计盲区,本文从风险链路拆解、核心能力模型、分级治理策略、落地踩坑点以及技术局限性多角度,分享终端侧 AI 安全治理的实践思路。

2401_86491085的博客 640

2.53 基于极稀疏指纹的室内定位注意力图元学习

该论文发表于IEEE Transactions on Mobile Computing(TMC)2026年6月,面向极稀疏指纹条件下的WiFi室内定位,针对指纹采集人力成本高、标记指纹稀缺时定位精度大幅下降的痛点,提出注意力图元学习模型AGML(Attentional Graph Meta‑Learning),结合图神经网络、元学习、两种指纹数据增强与分布对齐技术,在标记指纹极少的场景实现高精度室内定位,同时公开了多套真实+仿真定位数据集用于基准测试。场景:二维室内空间,障碍物造成信号遮挡,

weixin_42963026的博客 338

语音识别与语音合成的技术原理及应用

语音识别 #语音合成 #人工智能 #大模型。语音识别与语音合成的技术原理及应用。一、语音识别的核心原理。二、语音合成的核心原理。三、工程落地的主要难点。五、需要关注的现实问题。

weixin_62919816的博客 210

设计师工作室 GEO 实操:如何提升 AI 实体推荐概率

设计工作室 GEO 的本质,是把创意服务转化为 AI 可理解的结构化信息。核心动作可归纳为:区分事实与审美、建立实体图谱、预判用户提问、输出脱敏内容、搭建多信源、持续测试验证。梳理工作室的 6 个实体属性:品类、城市、流程、边界、团队、渠道。在官网或作品集平台发布至少 3 篇结构化项目复盘,只陈述事实。输出 1 篇「设计报价影响因素」科普内容,覆盖甲方高频提问。争取 1 次行业媒体或本地媒体专访,形成第三方信源。每周用「XX 城市 + 品类 + 设计工作室推荐」指令测试,记录出现频率。

goujunwe的博客 337
上一篇: InternVid:用于多模态视频理解与生成的大规模视频-文本数据集 | ICLR Spotlight
下一篇: InternVideo2 视频理解大模型已开源,更强VideoChat来袭!
OpenGVLab
博客等级 码龄2年 418粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值