thenukegun10x commited on
Commit
00ec82c
·
verified ·
1 Parent(s): bc19de5

Add Dense Mobile & Edge Suite with ONNX and LiteRT models

Browse files
Files changed (1) hide show
  1. README.md +41 -124
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
- ## Available Model Weights
37
 
38
- | Model Identifier | Architecture | Precision Format | File Size | Top-1 Accuracy | Top-5 Accuracy | Usage Requirements & Mode |
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
- ## Multi-Photo (4-View) Accuracy Scaling
54
-
55
- When surveying wild plants in Western Australia, taking multiple complementary photos dramatically increases confidence:
56
-
57
- | Number of Photos Provided | Angles Captured | Validation Groups | Top-1 Accuracy | Top-5 Accuracy |
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
- ## How AdaRound-FP8 Was Created
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
- To eliminate quantization loss while maintaining **zero external dependencies**, **AdaRound-FP8** was developed using a two-stage process:
71
 
72
- ```
73
- ┌─────────────────────────────────────────────────────────┐
74
- 1. Layer-by-Layer Sensitivity Analysis │
75
- - LayerNorms & Routers: 1.71M params (Kept in BF16) │
76
- - Attention & MoE Experts: 100.85M params (FP8 E4M3)
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
- ## Quickstart / Inference Examples
108
 
109
- ### 1. Single-Photo Inference
110
  ```python
111
- import torch
112
- import torchvision.transforms as T
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
- ### 2. Multi-Photo (4-View) Inference (99.2% Accuracy)
155
- ```python
156
- # Pass 4 complementary photos (e.g. flower, leaf, habit, bark)
157
- image_paths = ["flower.jpg", "leaf.jpg", "habit.jpg", "bark.jpg"]
158
- batch_tensors = torch.cat([transform(Image.open(p).convert("RGB")).unsqueeze(0) for p in image_paths], dim=0)
159
-
160
- weights_4view = hf_hub_download(repo_id=repo_id, filename="PlantDetect-4View-FP8-AdaRound.safetensors")
161
- raw_4view = load_file(weights_4view)
162
- model.load_state_dict({k: v.float() if v.is_floating_point() else v for k, v in raw_4view.items()}, strict=False)
163
- model.eval()
164
-
165
- with torch.no_grad():
166
- logits_4view, _, _ = model(batch_tensors)
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:** This project uses the DINOv3 vision backbone (`vit_base_patch16_dinov3.lvd1689m`) developed by Meta AI.
179
- * **Dataset Attribution:** Observation data sourced under open licenses (CC BY, CC BY-NC, CC0) from the **Global Biodiversity Information Facility (GBIF)** and **Western Australian Herbarium (FloraBase / DBCA)**.
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.