DeepSeek OCR 微调指南
在本指南中,我们将逐步讲解如何为定制DeepSeek OCR模型,仅需60 个训练步骤即可实现显著的性能提升。
在人工智能的世界中,DeepSeek OCR 快速确立了自己作为光学字符识别最创新模型之一的地位。2025 年初推出时,这个模型因其几个使其真正独特的原因而引起轰动。
为什么 DeepSeek OCR 受到如此推崇?
- 先进的视觉-语言架构: DeepSeek OCR 基于尖端的视觉-语言架构,结合了视觉理解和自然语言处理。这不仅使它能够识别文本,还能在上下文中理解其含义。
- 出色的多语言支持: 与许多主要关注西方语言的 OCR 模型不同,DeepSeek OCR 对复杂语言(如波斯语、阿拉伯语、汉语等)提供了与英语相当的出色准确性。
- 灵活的图像处理: 该模型实现了动态裁剪系统,智能处理各种尺寸和布局的文档,将大图像分割成可管理的部分而不丢失上下文信息。
- 开源且易于访问: DeepSeek 已将模型免费提供,使高端 OCR 技术民主化,使开发人员和研究人员能够根据特定用例自定义它。
- 计算效率: 尽管其先进功能,该模型经过优化,可在消费级硬件上运行,3B 参数版本可以在标准 GPU 上运行。
然而,DeepSeek OCR 的真正力量在于你为特定领域进行微调。
在本指南中,我们将逐步讲解如何为定制DeepSeek OCR模型,仅需60 个训练步骤即可实现显著的性能提升。
这里是官方 Unsloth 笔记本,包含完整代码。
开始之前,请确保您拥有:
- 一个 Google Colab 账户(免费版即可)
- Tesla T4 GPU 或更高配置(Colab 上可用)
- 稳定的互联网连接
1、下载预训练模型
从 Hugging Face 仓库下载完整的 DeepSeek OCR 模型到名为 deepseek_ocr 的本地目录中。
这包括:模型权重、配置文件和分词器
from huggingface_hub import snapshot_download
snapshot_download("unsloth/DeepSeek-OCR", local_dir = "deepseek_ocr")
⚠️ 注意:根据您的网络速度,下载可能需要几分钟(模型大约 3GB)。
2、加载并配置模型
使用优化的设置将模型加载到内存中以进行训练:
load_in_4bit = False: 使用 16 位精度进行更准确的训练(如果内存有限则设为True)trust_remote_code=True: 允许执行 DeepSeek OCR 所需的自定义代码unsloth_force_compile=True: 启用编译时优化以加快训练use_gradient_checkpointing = "unsloth": 使用 Unsloth 的优化梯度检查点以减少内存使用
from unsloth import FastVisionModel
import torch
from transformers import AutoModel
import os
os.environ["UNSLOTH_WARN_UNINITIALIZED"] = '0'
model, tokenizer = FastVisionModel.from_pretrained(
"./deepseek_ocr",
load_in_4bit = False,
auto_model = AutoModel,
trust_remote_code=True,
unsloth_force_compile=True,
use_gradient_checkpointing = "unsloth",
)
输出将显示 GPU 规格和分配的内存。
3、测试基线模型
加载您的训练数据集。这里我们使用 Parsynth OCR,这是一个包含 200,000 个合成波斯语文本图像的数据集。
我们将只加载前 2,000 个示例以加快速度,但您应该使用完整数据集进行完整训练。
from datasets import load_dataset
dataset = load_dataset("hezarai/parsynth-ocr-200k", split = "train[:2000]")
数据集包括:
image_path: 文本图像text: 正确的转录文本
dataset[1523]['image_path'].save("your_image.jpg")
现在保存一个样本图像以测试模型在微调前后的性能。
prompt = "<image>\nFree OCR. "
image_file = 'your_image.jpg'
output_path = 'your/output/dir'
res = model.infer(tokenizer, prompt=prompt, image_file=image_file,
output_path=output_path, base_size=1024, image_size=640,
crop_mode=True, save_results=True, test_compress=False)
这在您的样本图像上测试了微调前的模型:
<image>作为图像占位符base_size和image_size定义处理尺寸crop_mode=True启用智能裁剪
基线结果:
模型生成了一个具有 字符错误率 (CER) 为 23% 的转录文本,显然有改进空间!
4、添加 LoRA 适配器
使用 参数高效微调 (PEFT) 配置 LoRA (低秩适应)。
而不是更新所有 30 亿个参数,LoRA 添加了小的“适配器”层,修改行为的同时只更新 1-2% 的参数。
关键参数:
target_modules: 插入适配器的层(查询、键、值投影和 MLP 层)r = 16: 适配器等级(越高 = 更多容量,更多内存)lora_alpha = 16: 缩放因子(通常等于r)lora_dropout = 0: 禁用 dropout 用于短期训练
model = FastVisionModel.get_peft_model(
model,
target_modules=[
"q_proj",
"k_proj",
"v_proj",
"o_proj",
"gate_proj",
"up_proj",
"down_proj",
],
r = 16,
lora_alpha = 16,
lora_dropout = 0,
bias = "none",
random_state = 3407,
use_rslora = False,
loftq_config = None,
# target_modules = "all-linear", # 可选!如需指定列表
)
这种方法大大减少了:内存使用(可在消费级 GPU 上训练),训练时间,过拟合风险。
5、准备数据集
将数据集转换为 DeepSeek OCR 所需的对话格式。
每个示例变成一个对话:
- 用户回合 -> 包含图像和指令(“Free OCR”)
- 助手回合 -> 包含正确的转录文本
instruction = "<image>\nFree OCR. "
def convert_to_conversation(sample):
conversation = [
{
"role": "<|User|>",
"content": instruction,
"images": [sample['image']]
},
{
"role": "<|Assistant|>",
"content": sample["text"]
},
]
return {"messages": conversation}
dataset = load_dataset("hezarai/parsynth-ocr-200k", split = "train[:1000]")
dataset = dataset.rename_column("image_path", "image")
converted_dataset = [convert_to_conversation(sample) for sample in dataset]
这种格式使模型能够像对话一样学习任务,使训练更加自然和有效。模型学会“回应”OCR请求,就像一个助手那样。
6、创建数据整理器
@dataclass
class DeepSeekOCRDataCollator:
tokenizer: Any
model: Any
image_size: int = 640
base_size: int = 1024
crop_mode: bool = True
train_on_responses_only: bool = True
DeepSeekOCRDataCollator 为训练准备数据。它的主要作用包括:
图像预处理
- 调整图像大小和归一化
- 应用动态裁剪
- 创建全局和局部图像裁剪
智能分词
- 将文本转换为标记
- 插入图像占位符
- 构建注意力掩码
掩码
- 当
train_on_responses_only=True时,仅训练助手的响应 - 用户提示被屏蔽(设为 -100)
高效的批处理
- 将样本组合成带有填充的批次
- 优雅地处理不同的图像尺寸
7、训练配置
from transformers import Trainer, TrainingArguments
from unsloth import is_bf16_supported
FastVisionModel.for_training(model)
data_collator = DeepSeekOCRDataCollator(
tokenizer=tokenizer,
model=model,
image_size=640,
base_size=1024,
crop_mode=True,
train_on_responses_only=True,
)
trainer = Trainer(
model=model,
tokenizer=tokenizer,
data_collator=data_collator,
train_dataset=converted_dataset,
args=TrainingArguments(
per_device_train_batch_size=2,
gradient_accumulation_steps=4,
warmup_steps=5,
max_steps=60,
learning_rate=2e-4,
logging_steps=1,
optim="adamw_8bit",
weight_decay=0.001,
lr_scheduler_type="linear",
seed=3407,
fp16=not is_bf16_supported(),
bf16=is_bf16_supported(),
output_dir="outputs",
report_to="none",
dataloader_num_workers=2,
remove_unused_columns=False,
),
)
批量参数:
per_device_train_batch_size=2: 每个批次 2 个示例(如果内存更多可以增加)gradient_accumulation_steps=4: 在更新权重前累积 4 步的梯度- 有效批量 = 2 × 4 = 8 个示例
- 这模拟了更大的批量而不增加内存使用
优化参数:
learning_rate=2e-4: 学习率(0.0002)——相当高以快速收敛warmup_steps=5: 在前 5 步中逐渐增加学习率以提高稳定性optim="adamw_8bit": 量化为 8 位的 AdamW 优化器以节省内存weight_decay=0.001: 正则化以帮助防止过拟合
训练控制:
max_steps=60: 在 60 步后停止(快速测试——使用num_train_epochs=1进行完整运行)logging_steps=1: 每步记录损失以监控进度
数值精度:
- 自动使用
bf16如果支持,否则使用fp16 - 这减少了内存使用并加快了训练
8、运行训练
开始实际的训练过程!在执行过程中,您会看到:
- 显示当前步骤的进度条
- 每一步的训练损失(应随时间减少)
- 已用时间和训练速度
trainer_stats = trainer.train()
内部发生什么:
对于每个图像批次:
- 图像被处理并转换为嵌入
- 模型生成转录预测
- 通过比较预测与正确转录来计算损失
- 计算并累积梯度
每 gradient_accumulation_steps:
- 使用 LoRA 适配器更新模型权重
- 为下一轮零化梯度
学习率根据线性调度逐渐减少
监控:
- 逐渐下降的损失表明模型正在学习
- 如果损失停止下降,您可能已经达到了收敛
- 波动是正常的,尤其是对于小批量
在 Tesla T4 上,这些 60 步大约需要 12-15 分钟。
9、训练后评估
在微调后对同一基准样本图像进行测试。
prompt = "<image>\nFree OCR. "
image_file = 'your_image.jpg'
output_path = 'your/output/dir'
res = model.infer(tokenizer, prompt=prompt, image_file=image_file,
output_path=output_path,
image_size=640,
base_size=1024,
crop_mode=True,
save_results=True,
test_compress=False)
令人印象深刻的结果:
仅经过 60 步,我们显著提高了转录质量。此单个样本的字符错误率 (CER) 从 23% 降至 6%,相对减少了 74%!
10、保存模型
model.save_pretrained("lora_model")
tokenizer.save_pretrained("lora_model")
将训练好的 LoRA 适配器保存在 lora_model 目录中。重要:这仅保存适配器,不保存完整的基础模型。保存的文件包括:
adapter_config.json: 适配器配置adapter_model.safetensors: 适配器权重(非常小,约 100-200MB)- 分词器文件
要以后使用模型,您需要加载基础模型和适配器:
model, tokenizer = FastVisionModel.from_pretrained(
model_name="lora_model",
load_in_4bit=False,
auto_model=AutoModel,
trust_remote_code=True,
)
原文链接:How to Fine-Tune the new DeepSeek OCR model with Unsloth
汇智网翻译整理,转载请标明出处