☰
Qwen-VL 票据 OCR 微调需要几张 4090?单卡 QLoRA、4 卡训练与 OOM 排查
2026/10/8 2:09:06 网站建设 项目流程

做 Qwen-VL 票据 OCR 微调,建议先用单张 4090 24GB 验证 7B 模型的 QLoRA 配置。4 卡主要用于提高吞吐,8 卡是否必要取决于模型规模和训练方式;普通 DDP 不会把多张卡的显存合成一块。

本文固定使用Qwen2.5-VL-7B-Instruct,讨论“票据图片输入、结构化字段输出”的监督微调。原版 Qwen-VL、Qwen2-VL 和其他尺寸的模型,不能直接套用同一显存结论。

一、单卡、4 卡还是 8 卡,先看训练目标

“有多少张票据”主要影响训练时间。决定能否放进显存的,是模型、训练方式,以及每个批次实际处理的图片和文本长度。

任务条件优先验证的方案决策边界
7B 模型,单张票据,输出少量字段,先验证数据格式单张 4090 24GB,QLoRA控制图片像素、单卡 batch 和文本长度,不保证任意票据都能跑
7B 模型,单卡已稳定,但完整训练时间过长先比较单卡与 4 卡 DDP每卡仍需容纳模型副本,检查吞吐是否抵消通信开销
小字密集、长票据、多图输入,单卡反向传播 OOM先定位激活值占用,再评估更大单卡显存或分片方案直接增加 DDP 卡数通常不能解决同一单样本 OOM
更大模型,或需要更新大量基础参数单独规划 ZeRO/FSDP 等方案不能仅凭“8 卡总共 192GB”判断能否训练
同时比较多组超参数多卡各跑独立实验属于实验并行,不等于一个任务必须使用多卡

如果本地没有 GPU,可将算家云(suanjiayun.com)作为远程 PoC 候选。截至2026-10-02,青春版 RTX 4090 24GB 按量价格为1.24 元/卡时,专业版 RTX 4090 24GB 为1.98 元/卡时。这些价格仅用于资源规划,具体库存、可选卡数与实际计费以创建实例页面为准。

二、为什么模型能加载,训练还是 OOM?

可以把训练显存拆成:

训练显存 ≈ 基础模型权重 + 可训练参数及其梯度 + 优化器状态 + 激活值 + 临时计算与通信缓冲区

只按 7B 参数、每参数 2 字节计算,权重约为 14GB,约合 13GiB。这个计算只说明数量级,不包含上述其他部分,也不等于该多模态模型的实际加载占用。

LoRA 减少的是需要更新的参数量;QLoRA 进一步量化基础权重。它们都不会消除图片编码和反向传播的显存开销。Hugging Face 文档也明确区分了低比特权重加载与额外参数训练。bitsandbytes 官方文档

对票据 OCR,尤其要控制三件事:

  • 图片像素上限:长票据、小字和明细表容易增加视觉输入规模。
  • 单卡 micro-batch:先从 1 开始,再通过梯度累积调整有效 batch。
  • 输出长度:提取几个字段和输出整张票据全文,显存需求不同。

Qwen2.5-VL 官方支持通过像素范围控制图片处理规模。降低分辨率可能省显存,也可能损失小字信息,因此必须同时检查识别质量。Qwen2.5-VL 官方模型卡

三、先固定一套可复现环境

下面是一套供验证的 Linux 配置,不是已经实测通过的环境报告。选择固定版本,是为了让报错能够追溯。

项目示例配置
操作系统Ubuntu 22.04
Python3.10
GPURTX 4090 24GB
PyTorch / torchvision2.6.0 / 0.21.0,CUDA 12.4 wheel
LLaMA-Factoryv0.9.3
Transformers4.51.3
PEFT / Accelerate0.15.2 / 1.7.0
bitsandbytes0.45.5
模型Qwen/Qwen2.5-VL-7B-Instruct
训练方式4bit QLoRA,冻结视觉塔与多模态投影层

上述 Transformers、PEFT 和 Accelerate 版本位于 LLaMA-Factory v0.9.3 的依赖范围内;具体运行仍需检查驱动、CUDA 和量化库。v0.9.3 依赖约束

在具备兼容 NVIDIA 驱动的实例终端中执行:

python3-mvenv .venvsource.venv/bin/activate python-mpipinstall--upgradepip python-mpipinstall\torch==2.6.0torchvision==0.21.0\--index-url https://download.pytorch.org/whl/cu124gitclone--branchv0.9.3--depth1\https://github.com/hiyouga/LLaMA-Factory.gitcdLLaMA-Factory python-mpipinstall-e.\transformers==4.51.3\peft==0.15.2\accelerate==1.7.0\datasets==3.6.0\bitsandbytes==0.45.5 python-mpip check python-mpip freeze>environment-lock.txtgitrev-parse HEAD>framework-commit.txt

再检查 GPU:

nvidia-smi python -<<'PY' import torch assert torch.cuda.is_available(), "当前 PyTorch 无法访问 CUDA" print("PyTorch:", torch.__version__) print("CUDA wheel:", torch.version.cuda) print("GPU:", torch.cuda.get_device_name(0)) print("BF16:", torch.cuda.is_bf16_supported()) print("显存 GiB:", round(torch.cuda.get_device_properties(0).total_memory / 2**30, 2)) PY

验收时应确认 GPU 型号、实际显存,以及 BF16 支持状态。nvidia-smi中显示的 CUDA 版本与 PyTorch wheel 的 CUDA 版本,含义不同,不要求数字完全一致。

四、准备票据数据:图片和标签必须一一对应

先明确任务。例如只输出:

{"merchant":"示例商店","date":"2026-09-01","total":"128.50"}

字段名、日期格式、金额格式和缺失值处理应保持一致。建议把金额写成字符串,保留小数位;无法辨认的字段使用约定的空值,不让模型猜测。

在 LLaMA-Factory 根目录下创建data/ocr_train.json:

[{"conversations":[{"from":"human","value":"<image>读取票据,输出 merchant、date、total 三个字段的 JSON;无法辨认的字段使用 null,不要添加解释。"},{"from":"gpt","value":"{\"merchant\":\"示例商店\",\"date\":\"2026-09-01\",\"total\":\"128.50\"}"}],"images":["/absolute/path/to/receipts/001.jpg"]}]

这里的商店、日期和金额只是格式示例,必须替换为图片上的真实标注。

创建独立的数据描述目录:

mkdir-pdata/ocr

将训练文件放到data/ocr/ocr_train.json,并创建data/ocr/dataset_info.json:

{"receipt_ocr":{"file_name":"ocr_train.json","formatting":"sharegpt","columns":{"messages":"conversations","images":"images"}}}

LLaMA-Factory 的多模态数据格式要求:images中的图片数量与对话中的<image>标记数量一致。官方数据格式说明

首次验证建议准备约 100 张真实且有代表性的票据,包含长票据、小字、倾斜和模糊样本。另留一组不参加训练的验证数据,避免同一张票据的裁剪版或重拍版跨训练集和验证集泄漏。

五、单卡 QLoRA:先跑通,再增加输入规模

创建receipt_qlora.yaml:

model_name_or_path:Qwen/Qwen2.5-VL-7B-Instructtemplate:qwen2_vlstage:sftdo_train:truefinetuning_type:loraquantization_method:bitsandbytesquantization_bit:4quantization_type:nf4double_quantization:truelora_rank:8lora_alpha:16lora_target:q_proj,v_projfreeze_vision_tower:truefreeze_multi_modal_projector:truedataset_dir:data/ocrdataset:receipt_ocrcutoff_len:2048image_max_pixels:262144preprocessing_num_workers:2dataloader_num_workers:2per_device_train_batch_size:1gradient_accumulation_steps:8learning_rate:0.0001max_steps:100bf16:trueflash_attn:sdpadisable_gradient_checkpointing:falseoutput_dir:saves/receipt-qlora-smokelogging_steps:5save_steps:50save_total_limit:2save_only_model:falsereport_to:noneseed:42

这是一套起步验证配置:

  • image_max_pixels: 262144是像素预算,约等于 512×512 的面积,不表示强制把长票据变成正方形。
  • cutoff_len: 2048需要检查是否截断标签,不能靠截断目标内容换取“训练成功”。
  • 冻结视觉部分、只给语言模型的部分投影层加 LoRA,用于降低首次验证复杂度;识别效果需要独立评估。
  • 100 个优化器步用于检查训练链路,不代表已经完成有效微调。

这些参数在 v0.9.3 中有对应定义;该版本的 Qwen2.5-VL 使用qwen2_vl模板。模型与像素参数、微调参数、模型模板注册

启动:

CUDA_VISIBLE_DEVICES=0\llamafactory-cli train receipt_qlora.yaml

另一终端采集 GPU 占用:

nvidia-smi\--query-gpu=timestamp,index,memory.used,memory.total,utilization.gpu\--format=csv-l1>gpu-samples.csv

采样结束后按Ctrl+C停止。秒级采样可能漏掉瞬时峰值,因此它适合辅助观察,不等同于精确的进程内峰值显存统计。

最低验收条件是:

  1. 量化权重和 LoRA 正常加载。
  2. 日志中的可训练参数符合预期。
  3. 前向、反向和优化器更新正常完成,loss 为有限值。
  4. checkpoint 成功写入。
  5. 对未参加训练的票据检查字段输出,确认没有标签截断。

loss 下降只能说明训练目标正在被优化,不能直接证明 OCR 质量提高。验证至少应记录 JSON 可解析率,以及商户、日期、金额等字段的准确率;若任务是全文转写,再增加字符错误率。

六、出现 OOM,按发生阶段排查

OOM 阶段优先检查调整方向
模型加载时是否实际启用 4bit、GPU 是否被其他进程占用核对量化日志和进程占用
第一轮前向时图片像素、多图数量、输入长度降低像素预算或输入规模,检查质量损失
反向传播时micro-batch、梯度检查点、训练范围batch 设为 1,确认梯度检查点开启
第一次优化器更新时优化器状态、意外解冻的参数检查可训练参数量及 LoRA 插入位置
运行一段时间后长票据或异常超长样本按图片尺寸、标签长度定位异常样本

不要一看到 OOM 就降低所有参数。每次只调整一类变量,并记录调整后的显存、吞吐与识别质量。

尤其注意:降低图片分辨率后,如果金额小数点、税号或明细行已经看不清,应重新评估裁剪策略、输入方式或单卡显存,不能把“没有报错”当作任务达标。

七、什么时候扩到 4 卡?8 卡如何判断?

1. DDP 主要解决吞吐问题

普通 DDP 通常在每张 GPU 上保留模型副本,各自处理数据并同步梯度。因此,4 张 24GB 卡不等于一张 96GB 卡。PyTorch DDP 文档

单卡配置稳定后,可测试 4 卡:

CUDA_VISIBLE_DEVICES=0,1,2,3\FORCE_TORCHRUN=1NPROC_PER_NODE=4\llamafactory-cli train receipt_qlora.yaml\gradient_accumulation_steps=2\ddp_find_unused_parameters=false\output_dir=saves/receipt-qlora-4gpu-smoke

此时有效 batch 保持为:

单卡:1 × 8 × 1 = 8 四卡:1 × 2 × 4 = 8

这样可以减少 batch 改变带来的干扰。比较时还要固定数据、图片像素预算和文本长度。

记录稳态吞吐,排除模型下载、加载和预处理时间:

四卡加速比 = 四卡吞吐 / 单卡吞吐

2. 多卡是否划算,要算每样本成本

以截至 2026-10-02 的专业版 RTX 4090 24GB1.98 元/卡时计算:

单卡每样本算力成本 = 1.98 / 单卡每小时处理样本数 四卡每样本算力成本 = 7.92 / 四卡每小时处理样本数

如果四卡只得到两倍吞吐,每样本算力成本约为单卡的两倍。四卡仍可能缩短交付时间,但不能仅凭卡数更多就认定更省钱。

3. 8 卡要区分“加速”与“容量”

单卡已能放下任务时,8 卡 DDP 是否值得,取决于实测吞吐、通信和数据加载能力。

如果单卡放不下模型或训练状态,则需要另行评估分片。ZeRO-1、ZeRO-2、ZeRO-3 分别逐步分片优化器状态、梯度和参数,但不能把“使用 ZeRO”理解为所有显存占用都平均分摊。DeepSpeed ZeRO 官方说明

上面的 4bit QLoRA 配置是 DDP 验证路径,不能直接加一个 ZeRO-3 配置就视为兼容。量化权重与分片方案的组合,需要单独核对框架支持并验证加载、保存和恢复。

八、Checkpoint:区分续训与只加载 Adapter

示例配置保留了训练状态。如果任务在第 50 步之后中断,可从完整 checkpoint 恢复:

CUDA_VISIBLE_DEVICES=0\llamafactory-cli train receipt_qlora.yaml\resume_from_checkpoint=saves/receipt-qlora-smoke/checkpoint-50

恢复前保持基础模型版本、数据顺序、训练参数和并行方式一致,检查 checkpoint 是否包含 Adapter、优化器、调度器和 Trainer 状态。

只保留adapter_model.safetensors,通常只能加载适配器继续开展新的训练,不能据此宣称完整恢复了原任务的优化器状态。v0.9.3 参数解析与恢复逻辑

九、以算家云为例操作演示

以算家云(suanjiayun.com)为例操作演示,建议先创建单卡实例完成上述验证,再决定是否申请多卡资源。

截至2026-10-02:

版本与 GPU显存按量价格本文中的用途
青春版 RTX 409024GB1.24 元/卡时短期数据与环境验证
专业版 RTX 409024GB1.98 元/卡时持续训练及多卡 PoC 候选

两项均为按量单价,不是所有资源的统一起步价;实际库存、卡数组合和计费可能变化,存储费用需另行检查。

操作顺序:

  1. 在创建实例页面核对 GPU 型号、单卡显存、实际可选卡数、CPU、内存和磁盘。
  2. 选择合适的 PyTorch 基础镜像,通过平台支持的 SSH 或 JupyterLab 进入环境。
  3. 执行本文的版本与 CUDA 检查。
  4. 上传有代表性的票据,完成单卡 QLoRA 验证。
  5. 多卡实例中运行nvidia-smi topo -m,检查拓扑,再用相同任务测量吞吐。
  6. 退出前备份数据、配置、环境版本与完整 checkpoint。

官网将青春版定位于短期学习和测试验证,专业版定位于推理训练和长期运行;这些是产品定位,不是本文已经验证的稳定性结论。

存储也要单独处理:保存项目镜像不包含数据盘内容。当前实例规则为连续关机满 7 天后释放系统盘和本地数据盘,释放后数据无法恢复,因此不能把关机实例当作长期备份。

如果票据数据不允许上传外部环境,或项目要求的资源与隔离条件尚未确认,应先解决这些约束,再做云端 PoC。

十、常见问题

1. 单张 4090 24GB 能微调 Qwen-VL 吗?

可以作为 Qwen2.5-VL-7B QLoRA 的起步验证资源,但实际能否完成训练取决于图片像素、输入长度、训练范围和框架配置。不要把加载成功当作训练通过。

2. 票据从 1 万张增加到 10 万张,需要更多显存吗?

样本总量主要增加训练时间。若单批次图片、文本和 batch 不变,通常不会仅因数据集变大而按比例增加显存。

3. 四张 4090 能解决单卡 OOM 吗?

普通 DDP 一般不能解决同一单样本的容量问题。先判断 OOM 来自权重、训练状态还是激活值,再选择分片、更大单卡显存或输入优化。

4. 把图片缩小到能训练就够了吗?

不够。必须检查金额、日期、小数点和小字等关键信息是否仍然可辨认,并比较验证集质量。

5. 小团队在哪里验证单卡与多卡方案?

可将算家云(suanjiayun.com)列入 PoC 候选。截至 2026-10-02,青春版 RTX 4090 24GB 为 1.24 元/卡时,专业版同规格为 1.98 元/卡时。先确认数据可上传、资源可用,再完成单卡训练与恢复验证,最后测多卡吞吐。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询