用 LoRA 对 Qwen2.5-VL 模型进行SFT - LoRA微调流程
用 LoRA 对 Qwen2.5-VL 模型进行SFT - LoRA微调流程
flyfish
┌──────────────────────────────────────────────────────────────────────────┐
│ 环境准备与启动 │
├──────────────────────────────────────────────────────────────────────────┤
│ 1. 执行命令: FORCE_TORCHRUN=1 llamafactory-cli train ... │
│ 2. torchrun初始化分布式训练环境 │
│ ├─ 启动2个GPU任务(world size:2) │
│ ├─ 主节点地址: 127.0.0.1:随机端口 │
│ └─ 设备配置: cuda:0, cuda:1, BF16混合精度 │
└───────────────────────────────────┬─────────────────────────────────────┘↓
┌──────────────────────────────────────────────────────────────────────────┐
│ 模型加载与配置 │
├──────────────────────────────────────────────────────────────────────────┤
│ 1. 加载Qwen2.5-VL-7B-Instruct模型 │
│ ├─ 视觉模块(visual): 32层Transformer块, 处理图像输入 │
│ ├─ 语言模块(model): 36层Decoder, 使用RoPE位置编码 │
│ └─ 输出层(lm_head): 语言生成输出层 │
│ │
│ 2. 模型参数冻结策略 │
│ ├─ 冻结视觉模块: visual.patch_embed, visual.blocks, visual.merger │
│ ├─ 冻结非关键层: 词嵌入(embed_tokens), lm_head, 归一化层(RMSNorm) │
│ └─ 保留可训练层: 语言模型线性层 │
│ │
│ 3. LoRA微调配置 │
│ ├─ 自动发现目标模块: q_proj, k_proj, v_proj, o_proj, gate_proj, │
│ │ up_proj, down_proj(语言模型注意力和MLP线性层) │
│ ├─ LoRA参数: r=8, alpha=16, dropout=0.1 │
│ └─ 可训练参数: 2018万(占总参数0.24%) │
└───────────────────────────────────┬─────────────────────────────────────┘↓
┌──────────────────────────────────────────────────────────────────────────┐
│ 多模态数据处理 │
├──────────────────────────────────────────────────────────────────────────┤
│ 1. 加载数据集: mllm_demo + identity + alpaca_en_demo (1097条样本) │
│ │
│ 2. 数据预处理 │
│ ├─ 图像预处理: │
│ │ ├─ 使用Qwen2VLImageProcessor │
│ │ ├─ 标准化: 均值[0.481,0.458,0.408], 标准差[0.269,0.261,0.276] │
│ │ └─ 图像占位符: <|vision_start|><|image_pad|>...<|vision_end|> │
│ │
│ └─ 文本预处理: │
│ ├─ 使用Qwen2TokenizerFast │
│ ├─ 特殊token: <|im_start|>, <|im_end|>, <|vision_start|>等 │
│ └─ 截断长度: 2048 token │
│ │
│ 3. 样本格式示例: │
│ ├─ 输入: 系统提示 + 用户问题(含图像占位符) + 模型回答 │
│ └─ 输出: 标签ID(仅优化回答部分, -100表示忽略) │
└───────────────────────────────────┬─────────────────────────────────────┘↓
┌──────────────────────────────────────────────────────────────────────────┐
│ 训练配置与执行 │
├──────────────────────────────────────────────────────────────────────────┤
│ 1. 核心超参数 │
│ ├─ 批次配置: 单GPU批次1 + 梯度累积8 → 等效批次16 │
│ ├─ 学习率: 1e-4, 余弦衰减, 10%预热 │
│ ├─ 训练轮次: 3 epoch, 总优化步骤204 │
│ └─ 优化器: 自动选择(基于配置) │
│ │
│ 2. 性能优化策略 │
│ ├─ 梯度检查点: 减少显存占用 │
│ ├─ Torch SDPA: 加速注意力计算 │
│ ├─ 可训练参数转float32: 保证数值稳定性 │
│ └─ 分布式训练: 自动处理GPU通信(NCCL屏障) │
│ │
│ 3. 训练过程监控 │
│ ├─ 日志记录: 每10步记录训练状态 │
│ ├─ 检查点保存: 每500步保存模型 │
│ └─ 损失曲线绘制: 可视化训练过程 │
└───────────────────────────────────┬─────────────────────────────────────┘↓
┌──────────────────────────────────────────────────────────────────────────┐
│ 结果保存与验证 │
├──────────────────────────────────────────────────────────────────────────┤
│ 1. 模型保存 │
│ ├─ 输出目录: saves/qwen2_5vl-7b/lora/sft │
│ ├─ 保存内容: LoRA权重 + 优化器状态(可选择仅保存模型) │
│ └─ 覆盖策略: 自动覆盖现有输出目录 │
│ │
│ 2. 可选验证步骤 │
│ ├─ 视觉任务评估: OK-VQA, COCO Captioning │
│ └─ 语言任务评估: 指令遵循能力测试 │
└──────────────────────────────────────────────────────────────────────────┘
从另一个角度看
1. 环境准备与初始化├─ 执行命令│ └─ `FORCE_TORCHRUN=1 llamafactory-cli train examples/train_lora/qwen2_5vl_lora_sft.yaml`│ ├─ 强制使用 `torchrun` 分布式训练│ └─ 配置文件定义训练参数├─ 分布式环境初始化│ ├─ 任务数:2 GPU(world size=2)│ ├─ 主节点地址:`127.0.0.1:44553`(随机端口)│ └─ 自动设置环境变量:`CUDA_DEVICE_ORDER=PCI_BUS_ID`└─ 设备配置├─ 双GPU训练:`cuda:0` 和 `cuda:1`└─ 混合精度:`torch.bfloat16`2. 模型加载与配置├─ 加载基础模型│ ├─ 模型名称:`Qwen2.5-VL-7B-Instruct`│ ├─ 结构:│ │ ├─ 视觉模块:32层Transformer│ │ ├─ 语言模块:36层Decoder + RoPE│ │ └─ 输出层:词汇表大小 152,064├─ 参数冻结策略│ ├─ 冻结视觉模块:│ │ ├─ `visual.patch_embed`│ │ ├─ `visual.blocks`│ │ └─ `visual.merger`│ └─ 冻结语言模块组件:│ ├─ `embed_tokens`│ ├─ `lm_head`│ └─ 所有归一化层(RMSNorm)└─ LoRA 配置├─ 目标模块:│ ├─ 注意力层:`q_proj`, `k_proj`, `v_proj`, `o_proj`│ └─ MLP 层:`gate_proj`, `up_proj`, `down_proj`├─ 参数:│ ├─ 秩(r) = 8│ ├─ α = 16│ └─ Dropout = 0.1└─ 可训练参数量:20,185,088(占总参数的 0.24%)3. 数据处理与准备├─ 数据集加载│ ├─ 合并数据集:│ │ ├─ `mllm_demo.json`(多模态指令-响应)│ │ ├─ `identity.json`(身份识别)│ │ └─ `alpaca_en_demo.json`(英文指令)│ └─ 总样本数:1,097 条├─ 图像预处理│ ├─ 处理器:`Qwen2VLImageProcessor`│ ├─ 标准化参数:│ │ ├─ 均值:[0.481, 0.458, 0.408]│ │ └─ 标准差:[0.269, 0.261, 0.276]│ └─ 图像占位符:`<image>`└─ 文本预处理├─ 分词器:`Qwen2TokenizerFast`├─ 特殊token:│ ├─ `</s>`(对话结束)│ ├─ `<s>`(对话开始)│ ├─ `<image>`(视觉内容起始)│ └─ `</image>`(视觉内容结束)└─ 序列截断:最大长度 2048 tokens4. 训练配置与执行├─ 核心超参数│ ├─ 批次配置:│ │ ├─ 单GPU批次大小:1│ │ ├─ 梯度累积步数:8│ │ └─ 有效批次大小:16│ ├─ 学习率策略:│ │ ├─ 初始学习率:1e-4│ │ ├─ 调度器:余弦衰减│ │ └─ 预热比例:10%│ ├─ 训练轮次:3 epochs│ └─ 总优化步骤:204 steps├─ 性能优化│ ├─ 梯度检查点:启用(减少显存)│ ├─ Torch SDPA:加速注意力计算│ └─ 参数精度:│ ├─ 模型主体:bfloat16│ └─ 可训练参数:float32└─ 分布式训练细节├─ 通信后端:NCCL├─ 设备同步:自动屏障(barrier)└─ 日志记录:├─ 每10步记录损失└─ 每500步保存检查点5. 模型保存与验证├─ 模型保存│ ├─ 路径:`saves/qwen2_5vl-7b/lora/sft`│ ├─ 内容:│ │ ├─ LoRA权重:`adapter_config.json`, `adapter_model.bin`│ │ └─ 优化器状态(可选)│ └─ 覆盖策略:自动覆盖输出目录└─ 可选验证├─ 视觉任务:│ ├─ OK-VQA(视觉问答)│ └─ COCO Captioning(图像描述)└─ 语言任务:├─ 指令遵循测试└─ 多轮对话连贯性评估6. 关键技术细节├─ 多模态样本格式示例:│ ```text│ <s>system</s>│ You are a helpful assistant.<e>│ <s>user</s>│ <image>Who are they?<e>│ <s>assistant</s>│ They're Kane and Gretzka from Bayern Munich.<e>│ ```├─ 标签处理:│ ├─ 仅优化回答部分(标签ID ≠ -100)│ └─ 系统提示和问题部分标签设为 -100(忽略)└─ 显存优化:├─ 梯度检查点├─ BF16混合精度└─ 动态调整数据处理并行度(num_proc)