Image Feature Extraction
LiteRT
LiteRT
PerceptionEncoder
on-device
android
gpu
clip
image-encoder
vit
rope
Instructions to use mlboydaisuke/PE-Core-base-patch16-224-LiteRT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use mlboydaisuke/PE-Core-base-patch16-224-LiteRT with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- PerceptionEncoder
How to use mlboydaisuke/PE-Core-base-patch16-224-LiteRT with PerceptionEncoder:
# Use PE-Core models as CLIP models import core.vision_encoder.pe as pe model = pe.CLIP.from_config("mlboydaisuke/PE-Core-base-patch16-224-LiteRT", pretrained=True)# Use any PE model as a vision encoder import core.vision_encoder.pe as pe model = pe.VisionTransformer.from_config("mlboydaisuke/PE-Core-base-patch16-224-LiteRT", pretrained=True) - Notebooks
- Google Colab
- Kaggle
Upload README.md with huggingface_hub
Browse files
README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
+
library_name: litert
|
| 4 |
+
pipeline_tag: image-feature-extraction
|
| 5 |
+
base_model: timm/vit_pe_core_base_patch16_224.fb
|
| 6 |
+
tags:
|
| 7 |
+
- litert
|
| 8 |
+
- tflite
|
| 9 |
+
- on-device
|
| 10 |
+
- android
|
| 11 |
+
- gpu
|
| 12 |
+
- clip
|
| 13 |
+
- perception-encoder
|
| 14 |
+
- image-encoder
|
| 15 |
+
- vit
|
| 16 |
+
- rope
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
# Perception Encoder (PE-Core-B16-224) — LiteRT (TFLite) GPU
|
| 20 |
+
|
| 21 |
+
On-device [LiteRT](https://ai.google.dev/edge/litert) (`.tflite`) conversion of
|
| 22 |
+
**Perception Encoder Core** (PE-Core, Meta 2025), the SOTA CLIP-style image tower,
|
| 23 |
+
converted from [`timm/vit_pe_core_base_patch16_224.fb`](https://huggingface.co/timm/vit_pe_core_base_patch16_224.fb)
|
| 24 |
+
(ViT-B/16, 94M params; original [facebook/PE-Core-B16-224](https://huggingface.co/facebook/PE-Core-B16-224)).
|
| 25 |
+
|
| 26 |
+
A single forward pass turns one RGB image into a **1024-d L2-normalized image
|
| 27 |
+
embedding** for zero-shot classification, retrieval, and similarity — running
|
| 28 |
+
**fully on the LiteRT `CompiledModel` GPU accelerator** (ML Drift): **all 1028
|
| 29 |
+
ops are GPU-native (`Replacing 1028 out of 1028 node(s) ... LITERT_CL`), no CPU
|
| 30 |
+
fallback, no Flex ops.**
|
| 31 |
+
|
| 32 |
+
## Files
|
| 33 |
+
|
| 34 |
+
| File | Size | Description |
|
| 35 |
+
|------|------|-------------|
|
| 36 |
+
| `pe_core_base_224_fp16.tflite` | 187 MB | FP16 single-graph model, GPU full-residency |
|
| 37 |
+
| `convert_pecore.py` | — | Reproducible conversion script (timm → tflite) |
|
| 38 |
+
|
| 39 |
+
## I/O
|
| 40 |
+
|
| 41 |
+
- **Input**: `[1, 3, 224, 224]` float32, **NCHW**, RGB normalized to **`[-1, 1]`**
|
| 42 |
+
i.e. `(pixel/255 - 0.5) / 0.5` (timm mean/std = `(0.5, 0.5, 0.5)`). Normalization
|
| 43 |
+
is applied by the caller (not baked into the graph).
|
| 44 |
+
- **Output**: `[1, 1024]` float32, **L2-normalized** image embedding.
|
| 45 |
+
|
| 46 |
+
## Usage (Android, LiteRT CompiledModel)
|
| 47 |
+
|
| 48 |
+
```kotlin
|
| 49 |
+
val model = CompiledModel.create(
|
| 50 |
+
context.assets, "pe_core_base_224_fp16.tflite",
|
| 51 |
+
CompiledModel.Options(Accelerator.GPU), null
|
| 52 |
+
)
|
| 53 |
+
val inputs = model.createInputBuffers()
|
| 54 |
+
val outputs = model.createOutputBuffers()
|
| 55 |
+
inputs[0].writeFloat(nchwFloatArray) // [1,3,224,224], RGB scaled to [-1,1]
|
| 56 |
+
model.run(inputs, outputs)
|
| 57 |
+
val embedding = outputs[0].readFloat() // [1024], already L2-normalized
|
| 58 |
+
```
|
| 59 |
+
|
| 60 |
+
For zero-shot classification, precompute text-label embeddings with the PE-Core
|
| 61 |
+
text tower offline and take the dot product on device.
|
| 62 |
+
|
| 63 |
+
## Performance
|
| 64 |
+
|
| 65 |
+
- **~66 ms / image steady-state** on a Pixel 8a (Mali-G615) GPU (best 12.5 ms),
|
| 66 |
+
full GPU residency, FP16.
|
| 67 |
+
|
| 68 |
+
## Conversion notes
|
| 69 |
+
|
| 70 |
+
Converted with [litert-torch / ai-edge-torch](https://github.com/google-ai-edge/ai-edge-torch).
|
| 71 |
+
Making a RoPE ViT image tower **fully GPU-compatible** required three verbatim
|
| 72 |
+
(weights-exact, output corr ≈ 1.0) model-side rewrites:
|
| 73 |
+
|
| 74 |
+
1. **Fused-qkv → 4D manual attention** — the fused `qkv` reshape emits a 5D
|
| 75 |
+
head-split (`RESHAPE` rank 5) that the GPU delegate rejects; decompose into
|
| 76 |
+
separate q/k/v projections so attention stays 4D.
|
| 77 |
+
2. **Interleaved 2D-RoPE → rotate-half** — PE-Core's interleaved rotary uses a
|
| 78 |
+
strided `x[..., ::2]` that lowers to `GATHER_ND` (GPU-banned). Bake an
|
| 79 |
+
even→odd channel permutation into the q/k weights (preserves q·k exactly) and
|
| 80 |
+
apply the rotate-half form (slice + neg + concat) with constant cos/sin →
|
| 81 |
+
clean `MUL`/`ADD`/`SLICE`/`CONCAT`.
|
| 82 |
+
3. **Attention-pool with constant query → constant-RHS matmul** — the pooling
|
| 83 |
+
query is a constant latent, so the `q·kᵀ` batch-matmul is `const @ non-const`,
|
| 84 |
+
which the delegate rejects; reorder as `k @ q_constᵀ` (constant RHS → the
|
| 85 |
+
fully-connected path). Self-attention uses `scaled_dot_product_attention`,
|
| 86 |
+
whose lowering keeps the batch-matmul 3D with a materialized transpose
|
| 87 |
+
(both required for GPU residency).
|
| 88 |
+
|
| 89 |
+
Verified: zero banned ops, zero >4D tensors, TFLite-vs-PyTorch output
|
| 90 |
+
correlation = 1.000000 (FP32 and FP16).
|
| 91 |
+
|
| 92 |
+
## Training data & PII
|
| 93 |
+
|
| 94 |
+
PE-Core was pretrained by Meta on a large-scale **web-crawled image–text dataset**
|
| 95 |
+
(billions of image–caption pairs, CLIP-style contrastive objective). No new
|
| 96 |
+
training was performed for this conversion — it is a weights-exact format change
|
| 97 |
+
of the public `timm`/`facebook` checkpoint. Because the source data is
|
| 98 |
+
web-scraped, it may incidentally contain people, faces, text, and other PII;
|
| 99 |
+
no PII was deliberately collected, and this conversion adds none. Users deploying
|
| 100 |
+
the encoder should apply their own content/PII filtering as appropriate. See the
|
| 101 |
+
original [PE model card](https://huggingface.co/facebook/PE-Core-B16-224) and
|
| 102 |
+
[paper](https://arxiv.org/abs/2504.13181) for full dataset details.
|
| 103 |
+
|
| 104 |
+
## License & attribution
|
| 105 |
+
|
| 106 |
+
- **Apache-2.0** (original [PE-Core](https://huggingface.co/facebook/PE-Core-B16-224) /
|
| 107 |
+
[timm checkpoint](https://huggingface.co/timm/vit_pe_core_base_patch16_224.fb)).
|
| 108 |
+
- This is a format conversion; all credit to the original authors (Meta / FAIR).
|