-
Notifications
You must be signed in to change notification settings - Fork 88
Expand file tree
/
Copy path33_ocr_document_finetuning.py
More file actions
169 lines (141 loc) · 5.66 KB
/
Copy path33_ocr_document_finetuning.py
File metadata and controls
169 lines (141 loc) · 5.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""
OCR Document Fine-Tuning with a Dedicated OCR Model
Fine-tunes GLM-OCR (0.9B, ranked #1 on OmniDocBench) on LaTeX equation images
using the FastOCRModel API. This demonstrates the "dedicated OCR model" track:
take a model pre-trained for OCR and adapt it to your specific domain.
GLM-OCR has a pre-optimized vision encoder, so we freeze vision layers and
only fine-tune the language decoder (the default for FastOCRModel).
Usage:
python examples/33_ocr_document_finetuning.py
"""
# ===========================================================================
# MLX-Tune OCR imports
# ===========================================================================
from mlx_tune import (
FastOCRModel,
OCRSFTTrainer,
OCRSFTConfig,
UnslothVisionDataCollator,
compute_ocr_metrics,
)
# ===========================================================================
# Step 1: Load the dedicated OCR model
# ===========================================================================
print("=" * 70)
print("Step 1: Loading GLM-OCR-4bit (Dedicated OCR Model)")
print("=" * 70)
model, processor = FastOCRModel.from_pretrained(
"mlx-community/GLM-OCR-4bit", # 0.9B, #1 on OmniDocBench
# Other dedicated OCR models you can try:
# "mlx-community/DeepSeek-OCR-8bit" # 0.9B, 32x vision compression
# "mlx-community/DeepSeek-OCR-2-8bit" # 1B, improved accuracy
# "mlx-community/GLM-OCR-bf16" # 0.9B, full precision
# "mlx-community/dots.ocr-4bit" # DOTS OCR specialized
# "mlx-community/olmOCR-2-7B-1025-5bit" # 7B, trained on 270K PDF pages
# "mlx-community/LightOnOCR-1B-1025-bf16" # 1B, multilingual
)
# ===========================================================================
# Step 2: Add LoRA adapters (vision frozen by default for OCR models)
# ===========================================================================
print("\n" + "=" * 70)
print("Step 2: Adding LoRA Adapters (vision layers frozen)")
print("=" * 70)
model = FastOCRModel.get_peft_model(
model,
# finetune_vision_layers=False, # Default! OCR models have pre-optimized encoders
# finetune_language_layers=True, # Default! Adapt language decoder to domain
r=16,
lora_alpha=16,
lora_dropout=0,
bias="none",
random_state=3407,
)
# ===========================================================================
# Step 3: Prepare the dataset
# ===========================================================================
print("\n" + "=" * 70)
print("Step 3: Loading LaTeX OCR Dataset")
print("=" * 70)
from datasets import load_dataset
dataset = load_dataset("unsloth/LaTeX_OCR", split="train[:50]")
print(f"Dataset loaded: {len(dataset)} samples")
print(f"Columns: {dataset.column_names}")
print(f"Sample text: {dataset[0]['text'][:80]}...")
# Convert to OCR conversation format
from mlx_tune import convert_ocr_pairs_to_messages
instruction = "Write the LaTeX representation for this image."
converted_dataset = [
convert_ocr_pairs_to_messages(
image=sample["image"],
text=sample["text"],
instruction=instruction,
)
for sample in dataset
]
print(f"Converted {len(converted_dataset)} samples to OCR format")
# ===========================================================================
# Step 4: Pre-training inference test
# ===========================================================================
print("\n" + "=" * 70)
print("Step 4: Pre-Training Inference")
print("=" * 70)
FastOCRModel.for_inference(model)
image = dataset[0]["image"]
print("Testing transcribe()...")
try:
response = model.transcribe(image, prompt=instruction, max_tokens=128)
print(f"Transcription: {response[:100]}...")
except Exception as e:
print(f"Pre-training inference error (expected): {e}")
# ===========================================================================
# Step 5: Train the model
# ===========================================================================
print("\n" + "=" * 70)
print("Step 5: Training")
print("=" * 70)
FastOCRModel.for_training(model)
trainer = OCRSFTTrainer(
model=model,
processor=processor,
train_dataset=converted_dataset,
args=OCRSFTConfig(
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
warmup_steps=5,
max_steps=30,
learning_rate=5e-5,
logging_steps=1,
output_dir="ocr_glm_outputs",
max_length=2048,
),
)
trainer_stats = trainer.train()
# ===========================================================================
# Step 6: Post-training inference + evaluation
# ===========================================================================
print("\n" + "=" * 70)
print("Step 6: Post-Training Evaluation")
print("=" * 70)
FastOCRModel.for_inference(model)
# Transcribe a few test samples
test_images = [dataset[i]["image"] for i in range(min(5, len(dataset)))]
test_refs = [dataset[i]["text"] for i in range(min(5, len(dataset)))]
print("Transcribing test samples...")
predictions = model.batch_transcribe(test_images, prompt=instruction, max_tokens=256)
# Compute metrics
metrics = compute_ocr_metrics(predictions, test_refs)
print(f"\nOCR Metrics:")
print(f" CER: {metrics['cer']:.4f}")
print(f" WER: {metrics['wer']:.4f}")
print(f" Exact Match: {metrics['exact_match']:.4f}")
# ===========================================================================
# Step 7: Save the model
# ===========================================================================
print("\n" + "=" * 70)
print("Step 7: Saving Model")
print("=" * 70)
model.save_pretrained("ocr_glm_lora")
print("LoRA adapters saved to ocr_glm_lora/")
print("\n" + "=" * 70)
print("Done! OCR document fine-tuning complete.")
print("=" * 70)