Image Classification
LiteRT
LiteRT
ONNX
English
vision
botany
western-australia
dinov3
mixture-of-experts
adaround
fp8
int8
android
biodiversity
flora
Instructions to use thenukegun10x/PLantDetect-WA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT
How to use thenukegun10x/PLantDetect-WA 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
- Notebooks
- Google Colab
- Kaggle
Add Dense Mobile & Edge Suite with ONNX and LiteRT models
Browse files
README.md
CHANGED
|
@@ -9,8 +9,12 @@ tags:
|
|
| 9 |
- western-australia
|
| 10 |
- dinov3
|
| 11 |
- mixture-of-experts
|
|
|
|
|
|
|
| 12 |
- adaround
|
| 13 |
- fp8
|
|
|
|
|
|
|
| 14 |
- biodiversity
|
| 15 |
- flora
|
| 16 |
datasets:
|
|
@@ -33,148 +37,61 @@ pipeline_tag: image-classification
|
|
| 33 |
|
| 34 |
---
|
| 35 |
|
| 36 |
-
##
|
| 37 |
|
| 38 |
-
|
| 39 |
-
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
| 40 |
-
| **`PlantDetect-FP8-AdaRound.safetensors`** | MoE++ (16 FFNs) | **Mixed AdaRound FP8 + BF16** | **`104.3 MB`** | **89.21%** | **96.19%** | **Standard 1-Photo Mode** (Fastest GPU inference, 3.95× smaller). |
|
| 41 |
-
| **`PlantDetect-BF16.safetensors`** | MoE++ (16 FFNs) | **Full `bfloat16`** | **`205.2 MB`** | **89.21%** | **96.19%** | **Standard 1-Photo Mode** (Full precision reference). |
|
| 42 |
-
| **`PlantDetect-4View-FP8-AdaRound.safetensors`** | MoE++ 4-View | **Mixed AdaRound FP8 + BF16** | **`104.3 MB`** | **99.20%** | **99.85%** | ⚠️ **Requires 2–4 complementary photos** of the same plant (Flower + Leaf + Habit + Bark). |
|
| 43 |
-
| **`PlantDetect-4View-BF16.safetensors`** | MoE++ 4-View | **Full `bfloat16`** | **`205.2 MB`** | **99.20%** | **99.85%** | ⚠️ **Requires 2–4 complementary photos** of the same plant (Flower + Leaf + Habit + Bark). |
|
| 44 |
-
| **`PlantDetect-FP32.pt`** | MoE++ (16 FFNs) | **Full `float32`** | `412.4 MB` | 89.21% | 96.19% | PyTorch training checkpoint. |
|
| 45 |
-
|
| 46 |
-
> [!IMPORTANT]
|
| 47 |
-
> **Single-Photo vs. Multi-Photo (4-View) Note:**
|
| 48 |
-
> * If you only have **1 single photograph**, use **`PlantDetect-FP8-AdaRound.safetensors`** (**89.2% Top-1 / 96.2% Top-5**).
|
| 49 |
-
> * The **`4View` models** are trained specifically for multi-photo sets. Feeding **2 to 4 angles** (e.g. flower close-up + leaf serration + whole shrub) resolves fine-grained sister-species ambiguity and boosts Top-1 accuracy to **99.2%**!
|
| 50 |
-
|
| 51 |
-
---
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
| 58 |
-
|
|
| 59 |
-
| **1 Photo ($K=1$)** | Single shot (e.g. whole plant) | 27,673 photos | **`89.04%`** | **`96.24%`** |
|
| 60 |
-
| **2 Photos ($K=2$)** | Flower close-up + Leaf margin | 13,593 pairs | **`97.37%`** | **`99.83%`** |
|
| 61 |
-
| **3 Photos ($K=3$)** | Flower + Leaf + Habit / Shrub | 8,903 triplets | **`98.92%`** | **`99.97%`** |
|
| 62 |
-
| **4 Photos ($K=4$)** | Flower + Leaf + Habit + Bark | 6,535 4-sets | **`99.33%`** | **`100.0%`** |
|
| 63 |
|
| 64 |
---
|
| 65 |
|
| 66 |
-
##
|
| 67 |
-
|
| 68 |
-
Standard Post-Training Quantization (PTQ) uses **Round-to-Nearest (`RTN`)**, which snaps each weight independently to the closest discrete value on the non-uniform FP8 (`E4M3`) grid. On sparse Mixture-of-Experts architectures, naive `RTN` causes quantization noise and routing jitter.
|
| 69 |
|
| 70 |
-
|
| 71 |
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
┌─────────────────────────────────────────────────────────┐
|
| 81 |
-
│ 2. Discrete Adaptive Rounding (AdaRound) │
|
| 82 |
-
│ - For each weight, bound between [Q_floor, Q_ceil] │
|
| 83 |
-
│ - Optimize continuous mask: min ||Wx - W_fp8 x||² │
|
| 84 |
-
│ - Discretize to pure native torch.float8_e4m3fn │
|
| 85 |
-
└────────────────────────────┬────────────────────────────┘
|
| 86 |
-
│
|
| 87 |
-
▼
|
| 88 |
-
┌─────────────────────────────────────────────────────────┐
|
| 89 |
-
│ 3. Output: 104.3 MB Single Safetensors File │
|
| 90 |
-
│ - 100% Native PyTorch (zero custom C++ wheels needed)│
|
| 91 |
-
│ - 97.0% exact FP32 agreement, 0.9998 cosine sim │
|
| 92 |
-
└─────────────────────────────────────────────────────────┘
|
| 93 |
-
```
|
| 94 |
-
|
| 95 |
-
1. **Layer Sensitivity Analysis:**
|
| 96 |
-
* Probing demonstrated that 71 sensitive layers (all LayerNorm scale/biases, MoE router gates, and final classification heads) accounted for 90% of naive quantization error.
|
| 97 |
-
* These 1.71M parameters are preserved in native `torch.bfloat16` (+3.4 MB).
|
| 98 |
-
2. **Adaptive Non-Uniform Discrete Optimization:**
|
| 99 |
-
* For the remaining 237 heavy Linear, Attention QKV, and SwiGLU expert layers, discrete rounding decisions were optimized via AdamW to minimize the quadratic feature reconstruction loss over field validation samples.
|
| 100 |
-
3. **Results:**
|
| 101 |
-
* **Exact FP32 Top-1 Match:** Retains identical **90.5%** validation Top-1 accuracy.
|
| 102 |
-
* **Cosine Similarity:** **`0.999840`** on output logits.
|
| 103 |
-
* **Size:** Compressed by **3.95×** from 412 MB down to **104.3 MB**.
|
| 104 |
|
| 105 |
---
|
| 106 |
|
| 107 |
-
##
|
| 108 |
|
| 109 |
-
###
|
| 110 |
```python
|
| 111 |
-
import
|
| 112 |
-
import
|
| 113 |
from PIL import Image
|
| 114 |
-
from huggingface_hub import hf_hub_download
|
| 115 |
-
from safetensors.torch import load_file
|
| 116 |
-
import json
|
| 117 |
-
|
| 118 |
-
# Download PlantDetect model and species index
|
| 119 |
-
repo_id = "thenukegun10x/wa-plant-identifier"
|
| 120 |
-
weights_file = hf_hub_download(repo_id=repo_id, filename="PlantDetect-FP8-AdaRound.safetensors")
|
| 121 |
-
species_file = hf_hub_download(repo_id=repo_id, filename="species_index.json")
|
| 122 |
-
|
| 123 |
-
with open(species_file, "r", encoding="utf-8") as f:
|
| 124 |
-
species_index = json.load(f)
|
| 125 |
-
|
| 126 |
-
transform = T.Compose([
|
| 127 |
-
T.Resize(int(336 * 1.14)),
|
| 128 |
-
T.CenterCrop(336),
|
| 129 |
-
T.ToTensor(),
|
| 130 |
-
T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
|
| 131 |
-
])
|
| 132 |
-
|
| 133 |
-
img = Image.open("sample_plant.jpg").convert("RGB")
|
| 134 |
-
x = transform(img).unsqueeze(0)
|
| 135 |
-
|
| 136 |
-
from src.models.plant_vit import PlantViT
|
| 137 |
-
model = PlantViT(stem_name="vit_base_patch16_dinov3", n_classes=999, use_moe=True, num_ffn=16)
|
| 138 |
-
|
| 139 |
-
raw_weights = load_file(weights_file)
|
| 140 |
-
sd = {k: v.float() if v.is_floating_point() else v for k, v in raw_weights.items()}
|
| 141 |
-
model.load_state_dict(sd, strict=False)
|
| 142 |
-
model.eval()
|
| 143 |
-
|
| 144 |
-
with torch.no_grad():
|
| 145 |
-
logits, embedding, aux = model(x)
|
| 146 |
-
probs = torch.softmax(logits, dim=-1)[0]
|
| 147 |
-
top5_probs, top5_indices = torch.topk(probs, 5)
|
| 148 |
-
|
| 149 |
-
for rank, (prob, idx) in enumerate(zip(top5_probs, top5_indices), 1):
|
| 150 |
-
spp_info = species_index[idx.item()]
|
| 151 |
-
print(f"#{rank}: {spp_info['scientific_name']} ({spp_info['genus']}) - {prob*100:.2f}%")
|
| 152 |
-
```
|
| 153 |
|
| 154 |
-
#
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
# Average logits across all 4 angles
|
| 168 |
-
mean_logits = logits_4view.mean(dim=0, keepdim=True)
|
| 169 |
-
probs = torch.softmax(mean_logits, dim=-1)[0]
|
| 170 |
-
top_pred = species_index[probs.argmax().item()]
|
| 171 |
-
print(f"4-View Identified Species: {top_pred['scientific_name']} ({probs.max()*100:.2f}% confidence)")
|
| 172 |
```
|
| 173 |
|
| 174 |
---
|
| 175 |
|
| 176 |
## Attribution & Licensing
|
| 177 |
|
| 178 |
-
* **Built with DINOv3:**
|
| 179 |
-
* **Dataset Attribution:** Observation data sourced
|
| 180 |
* **License:** Released under **Creative Commons Non-Commercial (CC BY-NC 4.0)** for scientific and non-commercial research.
|
|
|
|
| 9 |
- western-australia
|
| 10 |
- dinov3
|
| 11 |
- mixture-of-experts
|
| 12 |
+
- litert
|
| 13 |
+
- onnx
|
| 14 |
- adaround
|
| 15 |
- fp8
|
| 16 |
+
- int8
|
| 17 |
+
- android
|
| 18 |
- biodiversity
|
| 19 |
- flora
|
| 20 |
datasets:
|
|
|
|
| 37 |
|
| 38 |
---
|
| 39 |
|
| 40 |
+
## Model Suite Breakdown
|
| 41 |
|
| 42 |
+
### 1. Server / Desktop GPU Models (Mixture-of-Experts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
| Model Identifier | Architecture | Precision Format | File Size | Top-1 Accuracy | Top-5 Accuracy | Recommended Use Case |
|
| 45 |
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
| 46 |
+
| **`PlantDetect-FP8-AdaRound.safetensors`** | MoE++ (16 FFNs) | **Mixed AdaRound FP8 + BF16** | **`104.3 MB`** | **89.21%** | **96.19%** | **Fastest, ultra-compact GPU inference (3.95× smaller)** |
|
| 47 |
+
| **`PlantDetect-BF16.safetensors`** | MoE++ (16 FFNs) | **Full `bfloat16`** | **`205.2 MB`** | **89.21%** | **96.19%** | **Lossless baseline reference** |
|
| 48 |
+
| **`PlantDetect-4View-FP8-AdaRound.safetensors`** | MoE++ 4-View | **Mixed AdaRound FP8 + BF16** | **`104.3 MB`** | **99.20%** | **99.85%** | ⚠️ **Requires 2–4 complementary photos** (Flower + Leaf + Habit + Bark) |
|
| 49 |
+
| **`PlantDetect-4View-BF16.safetensors`** | MoE++ 4-View | **Full `bfloat16`** | **`205.2 MB`** | **99.20%** | **99.85%** | ⚠️ **Requires 2–4 complementary photos** (Lossless multi-photo baseline) |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
---
|
| 52 |
|
| 53 |
+
### 2. Mobile Edge & Embedded Models (Dense ViT-Base)
|
|
|
|
|
|
|
| 54 |
|
| 55 |
+
Optimized for **mobile NPUs (Samsung S24, Pixel, iOS) and edge devices (Raspberry Pi, Jetson)** using dense matrix layers without routing scatter-gather overhead.
|
| 56 |
|
| 57 |
+
| File Path in Repo | Runtime Target | Quantization / Format | Size | Top-1 Accuracy | Top-5 Accuracy | Target Hardware |
|
| 58 |
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
| 59 |
+
| **`onnx/PlantDetect-Dense-INT8-AdaRound.onnx`** | ONNX Runtime Mobile | **Mixed-Precision INT8** | **`106.3 MB`** | **83.08%** | **94.93%** | Android / iOS / Windows DirectML / CoreML |
|
| 60 |
+
| **`onnx/PlantDetect-Dense-FP32.onnx`** | ONNX Runtime Standard | **Full FP32** | `363.3 MB` | 83.08% | 94.93% | Reference ONNX graph |
|
| 61 |
+
| **`litert/PlantDetect-Dense-INT8.tflite`** | Google LiteRT (TFLite) | **Full Integer INT8** | **`387.0 MB`** | **83.08%** | **94.93%** | Samsung Galaxy S24 NPU (Exynos / Snapdragon) |
|
| 62 |
+
| **`litert/PlantDetect-Dense-FP16.tflite`** | Google LiteRT (TFLite) | **Float16** | **`196.2 MB`** | **83.08%** | **94.93%** | Mobile GPU / XNNPACK CPU acceleration |
|
| 63 |
+
| **`PlantDetect-Dense-FP8-AdaRound.safetensors`** | PyTorch / Python | **Mixed AdaRound FP8** | **`92.7 MB`** | **83.08%** | **94.93%** | Lightweight Python deployment |
|
| 64 |
+
| **`PlantDetect-Dense-BF16.safetensors`** | PyTorch / Python | **Full BF16** | **`181.5 MB`** | **83.08%** | **94.93%** | Dense PyTorch reference |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
---
|
| 67 |
|
| 68 |
+
## Android & ONNX Runtime Quickstart
|
| 69 |
|
| 70 |
+
### ONNX Runtime Inference in Python / C++ / C#
|
| 71 |
```python
|
| 72 |
+
import onnxruntime as ort
|
| 73 |
+
import numpy as np
|
| 74 |
from PIL import Image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
+
# Initialize ONNX Runtime session
|
| 77 |
+
session = ort.InferenceSession("onnx/PlantDetect-Dense-INT8-AdaRound.onnx", providers=["CPUExecutionProvider"])
|
| 78 |
+
|
| 79 |
+
# Preprocess image to [1, 3, 336, 336]
|
| 80 |
+
img = Image.open("wild_flower.jpg").convert("RGB").resize((383, 383))
|
| 81 |
+
crop = img.crop((23, 23, 359, 359))
|
| 82 |
+
arr = (np.array(crop, dtype=np.float32) / 255.0 - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225]
|
| 83 |
+
tensor = np.expand_dims(arr.transpose(2, 0, 1), axis=0)
|
| 84 |
+
|
| 85 |
+
# Run inference
|
| 86 |
+
logits = session.run(None, {"input": tensor})[0]
|
| 87 |
+
predicted_class = np.argmax(logits, axis=-1)[0]
|
| 88 |
+
print(f"Predicted Species Index: {predicted_class}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
```
|
| 90 |
|
| 91 |
---
|
| 92 |
|
| 93 |
## Attribution & Licensing
|
| 94 |
|
| 95 |
+
* **Built with DINOv3:** Uses the DINOv3 vision backbone (`vit_base_patch16_dinov3.lvd1689m`) developed by Meta AI.
|
| 96 |
+
* **Dataset Attribution:** Observation data sourced from the **Global Biodiversity Information Facility (GBIF)** and **Western Australian Herbarium (FloraBase / DBCA)**.
|
| 97 |
* **License:** Released under **Creative Commons Non-Commercial (CC BY-NC 4.0)** for scientific and non-commercial research.
|