进阶岛--InternVL 微调实践

What

What is InternVL?

InternVL 是一种用于多模态任务的深度学习模型,旨在处理和理解多种类型的数据输入,如图像和文本。它结合了视觉和语言模型,能够执行复杂的跨模态任务,比如图文匹配、图像描述生成等。通过整合视觉特征和语言信息,InternVL 可以在多模态领域取得更好的表现。
如下图,对于InternVL这个模型来说,它vision模块就是一个微调过的ViT,llm模块是一个InternLM的模型。对于视觉模块来说,它的特殊之处在Dynamic High Resolution
在这里插入图片描述

  • Dynamic High Resolution
    InternVL独特的预处理模块:动态高分辨率,是为了让ViT模型能够尽可能获取到更细节的图像信息,提高视觉特征的表达能力。对于输入的图片,首先resize成448的倍数,然后按照预定义的尺寸比例从图片上crop对应的区域(参考上图左半区)
  • Pixel Shuffle
    Pixel Shuffle在超分任务中是一个常见的操作,PyTorch中有官方实现,即nn.PixelShuffle(upscale_factor) 该类的作用就是将一个tensor中的元素值进行重排列,假设tensor维度为[B, C, H, W], PixelShuffle操作不仅可以改变tensor的通道数,也会改变特征图的大小。

What is Xtuner?

本次微调使用书生浦语开源的Xtuner微调框架
XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。

高效

  • 支持大语言模型 LLM、多模态图文模型 VLM 的预训练及轻量级微调。XTuner 支持在 8GB 显存下微调 7B 模型,同时也支持多节点跨设备微调更大尺度模型(70B+)。
  • 自动分发高性能算子(如 FlashAttention、Triton kernels 等)以加速训练吞吐。
  • 兼容 DeepSpeed 🚀,轻松应用各种 ZeRO 训练优化策略。

灵活

  • 支持多种大语言模型,包括但不限于 InternLMMixtral-8x7BLlama 2ChatGLMQwenBaichuan
  • 支持多模态图文模型 LLaVA 的预训练与微调。利用 XTuner 训得模型 LLaVA-InternLM2-20B 表现优异。
  • 精心设计的数据管道,兼容任意数据格式,开源数据或自定义数据皆可快速上手。
  • 支持 QLoRALoRA、全量参数微调等多种微调算法,支撑用户根据具体需求作出最优选择。

全能

  • 支持增量预训练、指令微调与 Agent 微调。
  • 预定义众多开源对话模版,支持与开源或训练所得模型进行对话。
  • 训练所得模型可无缝接入部署工具库 LMDeploy、大规模评测工具库 OpenCompassVLMEvalKit

实操

系统环境(仅参考)

  • Intern Studio A100 50%算力(= 40g显存)
  • ubuntu 20.04
  • CUDA Version: 12.2

教程

跟着 https://github.com/InternLM/Tutorial/blob/camp3/docs/L2/InternVL/joke_readme.md 教程,写的相当详细,这里只概述下流程

  • 在Intern Studio开算力资源
    • A100 50%算力
    • ubuntu 20.04, cuda 12.2
  • 新建一个conda实验环境
  • 装各种依赖
  • 准备好InternVL2-2B模型
  • 准备好微调数据集: huggingface上的zhongshsh/CLoT-Oogiri-GO
  • 开始微调
    • 选择QLoRA or LoRA
    • 设置微调参数
  • 合并权重

由于我用的是Intern Studio预置的系统环境,因此整个过程中没有遇到任何坑~祝各位也一步到位

运行过程截图

QLoRA

启动微调

耗时≈5小时
在这里插入图片描述

微调效果

在这里插入图片描述

LoRA

参数设置
# Copyright (c) OpenMMLab. All rights reserved.
from mmengine.hooks import (CheckpointHook, DistSamplerSeedHook, IterTimerHook,
                            LoggerHook, ParamSchedulerHook)
from mmengine.optim import AmpOptimWrapper, CosineAnnealingLR, LinearLR
from peft import LoraConfig
from torch.optim import AdamW
from transformers import AutoTokenizer
 
from xtuner.dataset import InternVL_V1_5_Dataset
from xtuner.dataset.collate_fns import default_collate_fn
from xtuner.dataset.samplers import LengthGroupedSampler
from xtuner.engine.hooks import DatasetInfoHook
from xtuner.engine.runner import TrainLoop
from xtuner.model import InternVL_V1_5
from xtuner.utils import PROMPT_TEMPLATE
 
#######################################################################
#                          PART 1  Settings                           #
#######################################################################
# Model
path = '/root/model/InternVL2-2B'
 
# Data
data_root = '/root/InternLM/datasets/CLoT_cn_2000/'
data_path = data_root + 'ex_cn.json'
image_folder = data_root
prompt_template = PROMPT_TEMPLATE.internlm2_chat
max_length = 6656
 
# Scheduler & Optimizer
batch_size = 1  # per_device
accumulative_counts = 2
dataloader_num_workers = 4
max_epochs = 5
optim_type = AdamW
# official 1024 -> 4e-5
lr = 1e-6
betas = (0.9, 0.999)
weight_decay = 0.05
max_norm = 1  # grad clip
warmup_ratio = 0.03
 
# Save
save_steps = 1000
save_total_limit = 1  # Maximum checkpoints to keep (-1 means unlimited)
 
#######################################################################
#            PART 2  Model & Tokenizer & Image Processor              #
#######################################################################
model = dict(
    type=InternVL_V1_5,
    model_path=path,
    freeze_llm=True,
    freeze_visual_encoder=True,
    # comment the following lines if you don't want to use Lora in llm
    llm_lora=dict(
        type=LoraConfig,
        r=128,
        lora_alpha=256,
        lora_dropout=0.05,
        target_modules=None,
        task_type='CAUSAL_LM'),
    # uncomment the following lines if you don't want to use Lora in visual encoder # noqa
    # visual_encoder_lora=dict(
    #     type=LoraConfig, r=64, lora_alpha=16, lora_dropout=0.05,
    #     target_modules=['attn.qkv', 'attn.proj', 'mlp.fc1', 'mlp.fc2'])
)
 
#######################################################################
#                      PART 3  Dataset & Dataloader                   #
#######################################################################
llava_dataset = dict(
    type=InternVL_V1_5_Dataset,
    model_path=path,
    data_paths=data_path,
    image_folders=image_folder,
    template=prompt_template,
    max_length=max_length)
 
train_dataloader = dict(
    batch_size=batch_size,
    num_workers=dataloader_num_workers,
    dataset=llava_dataset,
    sampler=dict(
        type=LengthGroupedSampler,
        length_property='modality_length',
        per_device_batch_size=batch_size * accumulative_counts),
    collate_fn=dict(type=default_collate_fn))
 
#######################################################################
#                    PART 4  Scheduler & Optimizer                    #
#######################################################################
# optimizer
optim_wrapper = dict(
    type=AmpOptimWrapper,
    optimizer=dict(
        type=optim_type, lr=lr, betas=betas, weight_decay=weight_decay),
    clip_grad=dict(max_norm=max_norm, error_if_nonfinite=False),
    accumulative_counts=accumulative_counts,
    loss_scale='dynamic',
    dtype='float16')
 
# learning policy
# More information: https://github.com/open-mmlab/mmengine/blob/main/docs/en/tutorials/param_scheduler.md  # noqa: E501
param_scheduler = [
    dict(
        type=LinearLR,
        start_factor=1e-5,
        by_epoch=True,
        begin=0,
        end=warmup_ratio * max_epochs,
        convert_to_iter_based=True),
    dict(
        type=CosineAnnealingLR,
        eta_min=0.0,
        by_epoch=True,
        begin=warmup_ratio * max_epochs,
        end=max_epochs,
        convert_to_iter_based=True)
]
 
# train, val, test setting
train_cfg = dict(type=TrainLoop, max_epochs=max_epochs)
 
#######################################################################
#                           PART 5  Runtime                           #
#######################################################################
# Log the dialogue periodically during the training process, optional
tokenizer = dict(
    type=AutoTokenizer.from_pretrained,
    pretrained_model_name_or_path=path,
    trust_remote_code=True)
 
custom_hooks = [
    dict(type=DatasetInfoHook, tokenizer=tokenizer),
]
 
# configure default hooks
default_hooks = dict(
    # record the time of every iteration.
    timer=dict(type=IterTimerHook),
    # print log every 10 iterations.
    logger=dict(type=LoggerHook, log_metric_by_epoch=False, interval=10),
    # enable the parameter scheduler.
    param_scheduler=dict(type=ParamSchedulerHook),
    # save checkpoint per `save_steps`.
    checkpoint=dict(
        type=CheckpointHook,
        save_optimizer=False,
        by_epoch=False,
        interval=save_steps,
        max_keep_ckpts=save_total_limit),
    # set sampler seed in distributed evrionment.
    sampler_seed=dict(type=DistSamplerSeedHook),
)
 
# configure environment
env_cfg = dict(
    # whether to enable cudnn benchmark
    cudnn_benchmark=False,
    # set multi process parameters
    mp_cfg=dict(mp_start_method='fork', opencv_num_threads=0),
    # set distributed parameters
    dist_cfg=dict(backend='nccl'),
)
 
# set visualizer
visualizer = None
 
# set log level
log_level = 'INFO'
 
# load from which checkpoint
load_from = None
 
# whether to resume training from the loaded checkpoint
resume = False
 
# Defaults to use random seed and disable `deterministic`
randomness = dict(seed=None, deterministic=False)
 
# set log processor
log_processor = dict(by_epoch=False)
启动微调

在这里插入图片描述
在这里插入图片描述

微调效果

虽然这个梗不好笑,但是能看出模型在努力抛梗了😄
在这里插入图片描述

  • 27
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mpnet-base-v2是一种自然语言处理模型,它是PaddlePaddle的基础模型之一。微调指的是在已经预训练好的mpnet-base-v2模型上进行模型参数的调整和优化,以适应特定任务的需求。 进行mpnet-base-v2微调的主要目的是通过在特定任务上进行训练,使模型具有更好的性能和适应能力。微调可以通过在特定任务上进行更多的训练来提高模型的准确性和泛化能力。 在进行mpnet-base-v2微调之前,我们需要准备好特定任务的训练数据集。这个数据集需要与我们的任务目标相关,并且标注好相应的标签或答案。 微调的过程主要分为两个步骤:冻结层和微调训练。 首先,我们冻结mpnet-base-v2模型中的一些底层网络层,这些层经过预训练已经具备较好的特征提取能力,通常可以复用。冻结这些层可以减少我们需要调整的参数量,以提高训练效率和避免过拟合。 然后,我们对剩余的层进行微调训练。微调训练的过程就是在特定任务的数据集上对模型进行训练,通过调整模型参数来适应任务的需求。训练过程中,我们可以使用一些优化算法和技巧,如学习率衰减、正则化等,来进一步提高模型的性能。 为了得到一个较好的微调效果,我们还可以进行调参和验证,通过调整超参数来达到更好的模型性能。例如,我们可以调整微调训练的迭代次数、学习率等参数。同时,我们也需要使用验证数据集来评估模型在未见过的数据上的性能,以便进行调整和优化。 总的来说,mpnet-base-v2微调通过在特定任务上进行训练,使其更好地适应任务需求,从而达到提高模型性能的目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值