1. 项目概述
在计算机视觉领域,公式识别一直是一个具有挑战性的任务。传统的OCR技术在处理复杂的数学公式时往往表现不佳,而基于视觉语言模型(VLM)的方法则展现出了强大的潜力。本文将详细介绍如何使用MS-Swift框架对Intern-S1-mini和InternVL3_5-1B两款模型进行微调,使其能够准确识别数学公式并输出对应的LaTeX代码。
这个项目特别适合以下几类读者:
- 计算机视觉工程师想要了解最新的VLM微调技术
- 教育科技领域的开发者需要实现公式识别功能
- AI研究人员对多模态模型的微调方法感兴趣
- 任何需要将手写或印刷体公式转换为LaTeX代码的技术人员
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与配置
2.1 开发机配置
为了高效完成模型微调任务,我们首先需要配置合适的开发环境。建议选择以下配置:
- GPU:至少50% A100(显存约20GB)
- 镜像:Cuda12.8-conda
- Python版本:3.10
提示:如果使用其他型号GPU,可能需要调整batch size等参数以避免内存不足。
2.2 依赖安装
以下是完整的依赖安装步骤:
bash复制# 创建conda环境
conda create -n ms-swift11 python=3.10 -y
conda activate ms-swift11
# 克隆项目仓库
cd /root
git clone https://gh.llkk.cc/https://github.com/fak111/VLM-formula-recognition-dataset.git
cd VLM-formula-recognition-dataset
# 安装基础依赖
pip install -r requirements.txt
pip install transformers -U
# 安装MS-Swift框架
git clone https://gh.llkk.cc/https://github.com/modelscope/ms-swift.git
cd ms-swift
git checkout cab4aa59 # 使用特定commit保证稳定性
pip install -e .
pip install timm==1.0.9 msgspec==0.19.0 # 特定版本依赖
安装过程中常见问题及解决方案:
- CUDA版本不匹配:确保驱动和conda环境中的CUDA版本一致
- 网络问题导致下载失败:可以尝试更换pip源或使用代理
- 特定包版本冲突:建议严格按照上述版本安装
3. Intern-S1-mini模型微调
3.1 训练配置解析
Intern-S1-mini是一个轻量级的视觉语言模型,非常适合作为公式识别任务的baseline。我们使用LoRA(Low-Rank Adaptation)方法进行微调,这种方法可以在只训练少量参数的情况下有效提升模型性能。
关键训练参数说明:
- 学习率:1e-4(适合大多数LoRA微调场景)
- batch size:根据GPU显存调整
- 训练轮数:5个epoch通常足够
- LoRA秩:4(平衡效果和计算量)
3.2 启动训练
执行以下命令开始训练:
bash复制cd /root/VLM-formula-recognition-dataset
bash swift_config/interns1_mini_train.sh
训练过程中可以实时查看日志:
bash复制tail -f xxx.log # 替换为实际日志路径
注意事项:训练初期loss波动较大是正常现象,通常100-200步后会趋于稳定。如果loss持续不下降,可能需要检查学习率设置或数据质量。
3.3 模型权重合并
训练完成后,需要将LoRA权重与基础模型合并:
bash复制swift export --adapters /path/to/checkpoint --merge_lora True
示例路径:
bash复制swift export --adapters /root/VLM-formula-recognition-dataset/swift_output/SFT-Interns1mini/v0-20251010-124124/checkpoint-3 --merge_lora True
3.4 补全缺失文件
合并后可能会缺少一些配置文件,需要从原始模型复制:
bash复制SRC="/root/share/new_models/Intern-S1-mini"
DST="/path/to/merged/model"
rsync -ah --ignore-existing --exclude='/proc' --exclude='proc' "$SRC"/ "$DST"/
4. InternVL3_5-1B模型微调
4.1 高级配置解析
InternVL3_5-1B是一个更强大的多模态模型,针对它的微调需要特别注意以下几点:
-
显存优化:
- 使用gradient_accumulation_steps=4
- 启用gradient_checkpointing
- 设置per_device_batch_size=1
-
训练策略:
- freeze_vit=True(冻结视觉编码器)
- lora_rank=8(更大的模型可以承受更高的秩)
- torch_dtype=bfloat16(节省显存同时保持精度)
-
数据处理:
- dataset_num_proc=8(充分利用多核CPU)
- max_length=6000(适应长公式)
4.2 训练脚本详解
完整的训练脚本如下:
bash复制#!/bin/bash
# 日志配置
LOG_DIR="logs"
mkdir -p $LOG_DIR
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
LOG_FILE="$LOG_DIR/[SFT]internvl3.5_1b_${TIMESTAMP}.log"
# 环境配置
export OMP_NUM_THREADS=1
export CUDA_VISIBLE_DEVICES=0
export MASTER_PORT=$((10000 + RANDOM % 50000))
# 启动训练
nohup swift sft \
--model '/root/share/new_models/InternVL3.5/InternVL3_5-1B'\
--dataset '/root/share/datasets/VLM-formula-recognition-dataset_intern_camp/train/train_mini_abs.jsonl' \
--eval_steps 1000 \
--train_type lora \
--lora_rank 4 \
--lora_dropout 0.01 \
--lora_alpha 8 \
--torch_dtype bfloat16 \
--num_train_epochs 5 \
--per_device_train_batch_size 1 \
--per_device_eval_batch_size 1 \
--learning_rate 1e-4 \
--warmup_ratio 0.05 \
--gradient_accumulation_steps 4 \
--save_steps 2000 \
--save_total_limit 10 \
--gradient_checkpointing_kwargs '{"use_reentrant": false}' \
--logging_steps 1 \
--max_length 6000 \
--output_dir ./swift_output/SFT-InternVL3_5-1B\
--dataset_num_proc 8 \
--dataloader_num_workers 8 \
--metric acc \
--freeze_vit true \
> "$LOG_FILE" 2>&1 &
4.3 训练监控与问题排查
训练启动后,可以通过以下命令监控进程:
bash复制# 查看GPU使用情况
nvidia-smi
# 查看日志
tail -f logs/[SFT]internvl3.5_1b_*.log
常见问题及解决方案:
- CUDA out of memory:减小batch size或增加gradient_accumulation_steps
- 训练速度慢:检查dataloader_num_workers设置,确保没有CPU瓶颈
- Loss不下降:尝试调整学习率或检查数据质量
5. 模型评估与提交
5.1 模型上传到ModelScope
训练完成后,可以将模型上传到ModelScope共享:
python复制from modelscope.hub.api import HubApi
from modelscope.hub.constants import Licenses, ModelVisibility
# 配置基本信息
YOUR_ACCESS_TOKEN = 'your_token_here' # 替换为实际token
api = HubApi()
api.login(YOUR_ACCESS_TOKEN)
# 创建模型仓库
owner_name = 'your_username'
model_name = 'formula-recognition-model'
model_id = f"{owner_name}/{model_name}"
api.create_model(
model_id,
visibility=ModelVisibility.PUBLIC,
license=Licenses.APACHE_V2,
chinese_name="公式识别模型"
)
# 上传模型
api.upload_folder(
repo_id=model_id,
folder_path='/path/to/merged/model',
commit_message='Initial model upload',
)
5.2 评测提交
提交评测时,建议使用以下prompt模板:
text复制请根据图片中的公式生成对应的latex公式文本,不要任何解释。
输出格式要求:
1. 必须使用 ```latex 代码块包裹
2. 仅包含LaTeX代码,无任何文字说明
3. 确保语法正确,下标用{}括起来
输出案例:
案例1:
```latex
\sum_{i=1}^{n} x_i = \mu
案例2:
latex复制\begin{bmatrix}
a & b \\
c & d
\end{bmatrix}
code复制
## 6. 高级技巧与优化建议
### 6.1 数据增强策略
1. 字体变换:对公式图片应用不同字体渲染
2. 背景噪声:添加适度的背景噪声增强鲁棒性
3. 分辨率变化:训练时随机调整图片分辨率
4. 颜色反转:将黑底白字和白底黑字都纳入训练
### 6.2 超参数调优指南
1. 学习率:尝试1e-5到1e-4之间的值
2. LoRA秩:4-16之间,模型越大可用秩越高
3. Dropout:0.01-0.1防止过拟合
4. 训练轮数:3-10个epoch,使用早停策略
### 6.3 部署优化
1. 量化:使用8bit或4bit量化减小模型体积
2. ONNX导出:转换为ONNX格式提升推理速度
3. 缓存机制:对常见公式结果进行缓存
4. 批处理:同时处理多个公式提升吞吐量
在实际部署中,我发现将模型转换为TensorRT格式可以进一步提升推理速度,特别是在批量处理场景下。另外,对于教育类应用,可以构建常见公式的缓存库,当识别置信度达到阈值时直接返回缓存结果,既能提高响应速度又能保证一致性。
