omr-monophonic / README.md
NathanZ721's picture
Upload checkpoint-9000 LoRA adapter for OMR
fe24a1e verified
|
Raw
History Blame Contribute Delete
5.21 kB
---
base_model: Qwen/Qwen2-VL-2B-Instruct
library_name: peft
pipeline_tag: image-text-to-text
license: apache-2.0
tags:
- optical-music-recognition
- omr
- primus
- sheet-music
- lora
- peft
- qwen2-vl
- vision-language-model
- base_model:adapter:Qwen/Qwen2-VL-2B-Instruct
---
# omr-monophonic
LoRA adapter for **monophonic optical music recognition (OMR)**. Given a sheet-music image, the model transcribes it into **PrIMuS semantic tokens** as a single space-separated string.
This is a task-specific adapter on top of [`Qwen/Qwen2-VL-2B-Instruct`](https://huggingface.co/Qwen/Qwen2-VL-2B-Instruct). Load the base model first, then apply this adapter with PEFT.
## Model details
| Field | Value |
| --- | --- |
| Base model | `Qwen/Qwen2-VL-2B-Instruct` |
| Method | LoRA (PEFT) |
| Checkpoint | `checkpoint-9000` (2.07 epochs) |
| LoRA rank | 32 |
| LoRA alpha | 64 |
| LoRA dropout | 0.05 |
| Precision | BF16 training |
| Output format | PrIMuS semantic tokens |
| PEFT version | 0.19.1 |
**Target modules:** `q_proj`, `k_proj`, `v_proj`, `o_proj`, `qkv`, `gate_proj`, `up_proj`, `down_proj`, `fc1`, `fc2`, `lm_head`
## Intended use
Use this adapter when you need to convert **monophonic** sheet-music images into PrIMuS semantic notation for:
- music-theory and ear-training workflows
- melodic dictation / composition exercises
- downstream symbolic music processing
This is **not** a general music understanding model and is **not** trained for polyphonic scores.
## Evaluation
Evaluated on a 100-image golden set using token-level edit distance. Equivalent major/minor key signatures and common/cut-time aliases (`4/4``C`, `2/2``C/`) are canonicalized before scoring. At most one trailing barline on either side is forgiven.
### Token accuracy (%)
| Dataset | Score |
| --- | ---: |
| handwritten_original | 98.49 |
| clean_original | 100.0 |
| camera_distorted_original | 98.5 |
| handwritten_corrupt | 98.81 |
| clean_corrupt | 100.0 |
| camera_distorted_corrupt | 99.57 |
| manual_handwritten | 93.16 |
| manual_digital | 98.69 |
| **Average** | **97.91** |
### Exact match (%)
Exact match is the share of samples with zero token edits after normalization.
| Dataset | Score |
| --- | ---: |
| handwritten_original | 80.0 |
| clean_original | 100.0 |
| camera_distorted_original | 90.0 |
| handwritten_corrupt | 80.0 |
| clean_corrupt | 100.0 |
| camera_distorted_corrupt | 90.0 |
| manual_handwritten | 15.0 |
| manual_digital | 65.0 |
| **Average** | **70.0** |
## Usage
Install dependencies:
```bash
pip install transformers accelerate peft qwen-vl-utils pillow torch
```
Load the adapter:
```python
from PIL import Image
from peft import PeftModel
from transformers import AutoProcessor, Qwen2VLForConditionalGeneration
BASE_MODEL_ID = "Qwen/Qwen2-VL-2B-Instruct"
ADAPTER_ID = "NathanZ721/omr-monophonic"
processor = AutoProcessor.from_pretrained(BASE_MODEL_ID)
model = Qwen2VLForConditionalGeneration.from_pretrained(
BASE_MODEL_ID,
torch_dtype="auto",
device_map="auto",
)
model = PeftModel.from_pretrained(model, ADAPTER_ID)
model.eval()
image = Image.open("score.png").convert("RGB")
messages = [
{
"role": "user",
"content": [
{"type": "image", "image": image},
{
"type": "text",
"text": (
"Transcribe this monophonic sheet-music image into PrIMuS semantic format. "
"Return only one space-separated token string with no explanation or markdown."
),
},
],
}
]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = processor(text=[text], images=[image], return_tensors="pt").to(model.device)
output_ids = model.generate(**inputs, max_new_tokens=512)
response = processor.batch_decode(output_ids, skip_special_tokens=True)[0]
print(response)
```
## Training
- **Dataset:** consolidated OMR corpus (~139k image / PrIMuS semantic pairs)
- **Sampling mix:** 50% handwritten, 25% clean digital, 25% camera-distorted; balanced original/corrupt within each style
- **Hardware:** NVIDIA A100 (40 GB or 80 GB)
- **Objective:** assistant-only loss on PrIMuS token strings (image and prompt tokens masked)
## Limitations
- Monophonic excerpts only; polyphonic or orchestral scores are out of scope.
- Weakest slice is manually captured handwritten examples (`manual_handwritten`: 93.16% token accuracy, 15% exact match).
- Output is PrIMuS semantic tokens, not MEI, MusicXML, or LilyPond.
- Performance depends on image quality, cropping, and similarity to training styles.
## License
This adapter is released under **Apache 2.0**. The base model [`Qwen/Qwen2-VL-2B-Instruct`](https://huggingface.co/Qwen/Qwen2-VL-2B-Instruct) has its own license; follow the base model terms when using this adapter.
## Citation
If you use PrIMuS or this evaluation framing, cite the PrIMuS OMR work:
```bibtex
@article{calvo2018end,
title={End-to-End Neural Optical Music Recognition of Monophonic Scores},
author={Calvo-Zaragoza, Jorge and Rizo, David},
journal={Applied Sciences},
volume={8},
number={4},
pages={606},
year={2018}
}
```