Instructions to use plaincompute/ppocr-mlx with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use plaincompute/ppocr-mlx with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir ppocr-mlx plaincompute/ppocr-mlx
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
PP-FormulaNet Model Summary
Overview
Model: PP-FormulaNet (PaddlePaddle Formula Recognition) Purpose: Mathematical formula recognition from images Type: Encoder-Decoder Vision-Language Model Model Size: 694 MB (PyTorch safetensors) Total Parameters: 181,896,960 (~182M) Total Weight Tensors: 398 Total Module Instances: 279 Unique Module Types: 20
Model Architecture
High-Level Structure
Input Image (3, 768, 768)
β
[Image Preprocessing] β Resize, Normalize, Pad
β
[Vision Encoder] β Patch Embedding + Transformer Layers
β
[Neck + Multi-Modal Projector] β Feature projection to text space
β
[Text Decoder] β Transformer decoder with cross-attention
β
[Language Modeling Head] β Token logits (vocab_size=50000)
β
Output: LaTeX formula tokens
Vision Encoder (Image Understanding)
Configuration
| Parameter | Value |
|---|---|
| Image Size | 768 x 768 |
| Patch Size | 16 x 16 |
| Number of Patches | (768/16)Β² = 2304 patches |
| Input Channels | 3 (RGB) |
| Hidden Size | 768 |
| Output Channels | 256 (post-conv) |
| Number of Layers | 12 |
| Attention Heads | 12 |
| MLP Dimension | 3072 |
| Global Attention Indexes | [2, 5, 8, 11] |
| Window Size | 14 |
| Position Encoding | Absolute + Relative |
| QKV Bias | True |
Components
Patch Embedding
model.encoder.patch_embed.projection.weight: (768, 3, 16, 16)- Conv2d layer converting patches to embeddings
Position Embedding
model.encoder.pos_embed: Learnable position embeddings
Neck (Post-Conv)
model.encoder.neck.conv1.weight: First conv layermodel.encoder.neck.conv2.weight: Second conv layermodel.encoder.neck.layer_norm1.*: First layer normmodel.encoder.neck.layer_norm2.*: Second layer norm- Output channels: 256 β 512 β 1024
Multi-Modal Projector
model.encoder.multi_modal_projector.linear_1.*: (1024, 1024)model.encoder.multi_modal_projector.linear_2.*: Projects to text dimension (512)model.encoder.multi_modal_projector.conv1.weight: Conv projectionmodel.encoder.multi_modal_projector.conv2.weight: Conv projection
Transformer Layers (12 layers) Each layer contains:
attn.qkv.weight/bias: Fused QKV projection (2304 = 3*768)attn.proj.weight/bias: Output projectionattn.rel_pos_h/w: Relative position encodingsmlp.lin1.weight/bias: First linear (3072)mlp.lin2.weight/bias: Second linear (768)layer_norm1.*: Pre-attention normlayer_norm2.*: Pre-MLP norm
Text Decoder (LaTeX Generation)
Configuration
| Parameter | Value |
|---|---|
| Model Type | Transformer Decoder |
| Hidden Size | 512 |
| Vocab Size | 50000 |
| Number of Layers | 8 |
| Attention Heads | 16 |
| FFN Dimension | 2048 |
| Max Position Embeddings | 2560 |
| Dropout | 0.1 |
| Activation | GELU |
| Scale Embedding | True |
| Tie Word Embeddings | False |
Special Tokens
| Token ID | Token | Description |
|---|---|---|
| 0 | <s> |
BOS (Begin of Sequence) |
| 1 | <pad> |
Padding |
| 2 | </s> |
EOS (End of Sequence) |
| 3 | <unk> |
Unknown |
| 4 | [START_REF] |
Start reference |
| 5 | [END_REF] |
End reference |
| 6 | [IMAGE] |
Image token |
| 7 | <fragments> |
Start fragments |
| 8 | </fragments> |
End fragments |
| 9 | <work> |
Start work |
| 10 | </work> |
End work |
| 11 | [START_SUP] |
Start superscript |
| 12 | [END_SUP] |
End superscript |
| ... | ... | More special tokens for LaTeX structure |
Components
Token Embedding
model.decoder.embed_tokens.weight: (50000, 512)
Position Embedding
model.decoder.embed_positions.weight: Positional encodings
Layer Norm Embedding
model.decoder.layernorm_embedding.*: Input embedding normalization
Decoder Layers (8 layers) Each layer contains:
self_attn.q_proj/k_proj/v_proj.*: Self-attention projectionsself_attn.out_proj.*: Self-attention outputself_attn_layer_norm.*: Pre-self-attention normencoder_attn.q_proj/k_proj/v_proj.*: Cross-attention (to encoder output)encoder_attn.out_proj.*: Cross-attention outputencoder_attn_layer_norm.*: Pre-cross-attention normfc1.*: First FFN linear (2048)fc2.*: Second FFN linear (512)final_layer_norm.*: Pre-FFN norm
Final Layer Norm
model.decoder.layer_norm.*: Output normalization
Language Modeling Head
lm_head.weight: (50000, 512) - Projects to vocabulary logits
Image Preprocessing
Configuration (from processor_config.json)
| Parameter | Value |
|---|---|
| Image Size | 768 x 768 |
| Resample Method | Bicubic (2) |
| Do Resize | True |
| Do Rescale | True |
| Do Normalize | True |
| Do Pad | True |
| Do Crop Margin | True |
| Do Align Long Axis | False |
| Do Thumbnail | True |
| Image Mean | [0.7931, 0.7931, 0.7931] |
| Image Std | [0.1738, 0.1738, 0.1738] |
Preprocessing Pipeline
- Thumbnail: Resize maintaining aspect ratio
- Crop Margin: Remove white margins around formula
- Resize: Resize to 768 x 768
- Rescale: Scale pixel values to [0, 1]
- Normalize: Apply mean/std normalization
- Pad: Pad to target size if needed
Key Tensor Shapes
| Component | Tensor | Shape |
|---|---|---|
| Patch Embedding | model.encoder.patch_embed.projection.weight |
(768, 3, 16, 16) |
| QKV Projection | model.encoder.layers.0.attn.qkv.weight |
(2304, 768) |
| Token Embedding | model.decoder.embed_tokens.weight |
(50000, 512) |
| Projector | model.encoder.multi_modal_projector.linear_1.weight |
(1024, 1024) |
| LM Head | lm_head.weight |
(50000, 512) |
Model Tree Structure
PPFormulaNetForConditionalGeneration
βββ model
β βββ encoder (Vision Encoder)
β β βββ patch_embed
β β β βββ projection (Conv2d)
β β βββ pos_embed (Learnable)
β β βββ neck
β β β βββ conv1
β β β βββ conv2
β β β βββ layer_norm1
β β β βββ layer_norm2
β β βββ multi_modal_projector
β β β βββ linear_1
β β β βββ linear_2
β β β βββ conv1
β β β βββ conv2
β β βββ layers (12 Transformer layers)
β β βββ [0-11]
β β βββ attn
β β β βββ qkv
β β β βββ proj
β β β βββ rel_pos_h
β β β βββ rel_pos_w
β β βββ mlp
β β β βββ lin1
β β β βββ lin2
β β βββ layer_norm1
β β βββ layer_norm2
β βββ decoder (Text Decoder)
β βββ embed_tokens
β βββ embed_positions
β βββ layernorm_embedding
β βββ layers (8 Transformer layers)
β β βββ [0-7]
β β βββ self_attn
β β β βββ q_proj
β β β βββ k_proj
β β β βββ v_proj
β β β βββ out_proj
β β βββ self_attn_layer_norm
β β βββ encoder_attn
β β β βββ q_proj
β β β βββ k_proj
β β β βββ v_proj
β β β βββ out_proj
β β βββ encoder_attn_layer_norm
β β βββ fc1
β β βββ fc2
β β βββ final_layer_norm
β βββ layer_norm
βββ lm_head (Linear)
Inference Usage
HuggingFace Transformers
from PIL import Image
from transformers import AutoProcessor, PPFormulaNetForConditionalGeneration
# Load model and processor
model_path = "model/formula"
model = PPFormulaNetForConditionalGeneration.from_pretrained(model_path)
processor = AutoProcessor.from_pretrained(model_path)
# Preprocess image
image = Image.open("formula.png").convert("RGB")
inputs = processor(images=image, return_tensors="pt")
# Generate LaTeX
outputs = model.generate(**inputs)
result = processor.post_process(outputs)
print(result) # LaTeX string
Key Points
- Use
model.generate()for autoregressive decoding (inference mode) - Use
model.forward()only for training (requires decoder input_ids) - The processor handles image preprocessing and text post-processing
Decoding Strategy
Default: Greedy Decoding (beam_size=1)
num_beams: 1 (default)do_sample: False (default)max_length: 1537 tokens
To enable beam search for better quality:
outputs = model.generate(**inputs, num_beams=5, early_stopping=True)
Common generation parameters:
num_beams: Number of beams for beam search (default=1)max_length: Maximum sequence length (default=1537)early_stopping: Stop when all beams reach EOS (default=False)length_penalty: Penalty for longer sequences (default=1.0)do_sample: Enable sampling (default=False)temperature: Sampling temperature (default=1.0)top_k: Top-k sampling (default=50)top_p: Nucleus sampling (default=1.0)
Porting Considerations for MLX
Key Challenges
Relative Position Encoding: The vision encoder uses both absolute and relative position encodings (
rel_pos_h,rel_pos_w). MLX's attention mechanism may need custom implementation.Global Attention: Layers at indexes [2, 5, 8, 11] use global attention. This may require special handling.
Window Attention: Window size of 14 suggests window-based attention (similar to Swin Transformer).
Cross-Attention: The decoder has cross-attention to encoder outputs, requiring careful memory management.
Autoregressive Generation: The decoder generates tokens one at a time, which may be slow on MLX without optimization.
Large Vocabulary: 50,000 vocab size means the LM head is large (50000 x 512).
MLX Module Structure
The MLX implementation would need:
PPFormulaNetVisionEncoder: Vision encoder with patch embedding and transformer layersPPFormulaNetNeck: Post-conv layers for feature refinementPPFormulaNetMultiModalProjector: Projects vision features to text spacePPFormulaNetDecoder: Transformer decoder with self and cross attentionPPFormulaNetLMHead: Linear layer for vocabulary projectionPPFormulaNetModel: Combined modelPPFormulaNetForConditionalGeneration: Root model with generation support
Module Types Breakdown
| Module Type | Count | Description |
|---|---|---|
| Linear | 131 | Linear projection layers |
| LayerNorm | 50 | Layer normalization layers |
| GELUActivation | 20 | GELU activation functions |
| PPFormulaNetAttention | 16 | Attention mechanisms (12 vision + 4 decoder cross-attention) |
| PPFormulaNetVisionLayer | 12 | Vision transformer encoder layers |
| PPFormulaNetVisionAttention | 12 | Vision-specific attention with relative position encoding |
| PPFormulaNetMLPBlock | 12 | MLP blocks in vision encoder |
| PPFormulaNetDecoderLayer | 8 | Text decoder layers |
| Conv2d | 5 | Convolutional layers (patch embed + neck + projector) |
| ModuleList | 2 | Module lists for repeated layers |
| PPFormulaNetLayerNorm | 2 | Custom layer norm implementations |
| PPFormulaNetForConditionalGeneration | 1 | Root model class |
| PPFormulaNetModel | 1 | Core model (encoder + decoder) |
| PPFormulaNetTextModel | 1 | Text decoder wrapper |
| PPFormulaNetScaledWordEmbedding | 1 | Scaled word embedding layer |
| PPFormulaNetLearnedPositionalEmbedding | 1 | Learnable position embeddings |
| PPFormulaNetVisionModel | 1 | Vision encoder wrapper |
| PPFormulaNetPatchEmbeddings | 1 | Patch embedding layer |
| PPFormulaNetVisionNeck | 1 | Vision neck (post-conv) |
| PPFormulaNetMultiModalProjector | 1 | Multi-modal projection layer |
Files in model/formula/
| File | Description |
|---|---|
model.safetensors |
PyTorch weights (694 MB, 398 tensors) |
config.json |
Model architecture configuration |
processor_config.json |
Image preprocessing configuration |
tokenizer_config.json |
Tokenizer special tokens and settings |
tokenizer.json |
Tokenizer vocabulary |
generation_config.json |
Generation parameters |
inference.yml |
Inference configuration |
README.md |
Model documentation (Apache 2.0 license) |
formula_model_tree.json |
Generated model tree structure |
References
- HuggingFace Model:
PaddlePaddle/PP-FormulaNet_plus-L_safetensors - Original Paper: PP-FormulaNet (PaddlePaddle)
- Transformers Class:
PPFormulaNetForConditionalGeneration - Processor Class:
PPFormulaNetProcessor