StephanMeijer's picture
v0.3.0: trained on unanimous Albert teacher labels
0dd7d99 verified
|
Raw History Blame Contribute Delete
8.97 kB
---
license: apache-2.0
library_name: onnx
pipeline_tag: image-classification
tags:
- multi-label
- image-attributes
- onnx
- mobilenetv4
---
# WhatDoWeSee-MobileNetV4
Tags **what is visible in an image** with any number of 20 attributes, such as
people, text, chart, diagram, table, map or aerial view. A small, fast MobileNetV4 model (34 MB ONNX, about 18 ms per image on one CPU thread)
for sorting and describing large image collections.
This is **v0.3.0** (2026-10-15): trained on 38,386 images where three Albert vision-language models agree (same data as WhatDoWeSee-EfficientNet-B0 v0.3.0).
Try it in your browser: [WhatDoWeSee Space](https://huggingface.co/spaces/StephanMeijer/WhatDoWeSee).
## Attributes
An image gets every attribute that is clearly recognisable, also when blurry or in the background;
tiny or unrecognisable details don't count. Depicted things count (a drawn dog is Animals).
- **People** (`people`): one or more humans, or clearly human faces, hands or bodies
- **Animals** (`animals`): animals, birds, fish or insects
- **Plants** (`nature`): living green things: trees, plants, flowers, crops; not grass or a lawn as ground, not sea, sky or rocks (those are Landscape)
- **Landscape** (`landscape`): an outdoor view of land, sea, sky, mountains, rocks, rivers or a city as a whole
- **Buildings / structures** (`buildings`): buildings, interiors where the room or its architecture is clearly visible, and other built structures: bridges, towers, dams, monuments, ruins
- **Vehicles** (`vehicles`): cars, bikes, trains, ships, planes or other vehicles
- **Food** (`food`): food or drinks
- **Text** (`text`): running text, sentences, lists or a page that make up a substantial part of the image; labels, captions, titles and signs don't count
- **Handwriting** (`handwriting`): handwritten text, notes or signatures
- **Chart** (`chart`): a data plot: values on axes or as proportions (bar, line, pie, scatter, area chart or similar)
- **Diagram** (`diagram`): structure or relationships without measured values: a flowchart, schematic, process or relationship diagram; also labelled drawings that show how something is built (anatomy, parts, cross-sections)
- **Table** (`table`): text or numbers laid out in rows and columns, with or without grid lines; not the furniture
- **Map** (`map`): a geographic map, floor plan or route map
- **Logo / icon** (`logo-icon`): a logo, icon, emblem, badge or pictogram
- **Formula** (`formula`): mathematical, chemical or other notation
- **Screen / UI** (`screen`): an app, website or device interface
- **Artwork** (`artwork`): made as art: a painting, illustration, cartoon or sculpture, as the image itself or shown in it; not drawings made to explain (those are Diagram)
- **Instruments** (`instruments`): musical instruments: guitar, piano, violin, drums, wind instruments and the like
- **Furniture** (`furniture`): chairs, tables, beds, sofas, desks, cabinets, shelves and other furniture (a data table is Table)
- **Aerial** (`aerial`): the ground seen from high above: aerial or satellite photos, drone shots, bird's-eye views, also through a plane window, straight down or at an angle; clouds without ground don't count; a drawn map is Map
## Usage
Download a fixed version (recommended), so a later release never changes your results:
```python
from huggingface_hub import hf_hub_download
model_path = hf_hub_download("StephanMeijer/WhatDoWeSee-MobileNetV4", "model.onnx", revision="v0.3.0")
config_path = hf_hub_download("StephanMeijer/WhatDoWeSee-MobileNetV4", "config.json", revision="v0.3.0")
```
Then:
```python
import json
import numpy as np
import onnxruntime as ort
from PIL import Image
config = json.load(open(config_path))
session = ort.InferenceSession(model_path)
size = config["input"]["shape"][-1]
mean = np.array(config["input"]["mean"], dtype=np.float32)
std = np.array(config["input"]["std"], dtype=np.float32)
image = Image.open("photo.jpg").convert("RGB").resize((size, size), Image.BILINEAR)
x = ((np.asarray(image, dtype=np.float32) / 255 - mean) / std).transpose(2, 0, 1)[None]
probabilities = 1 / (1 + np.exp(-session.run(None, {"pixel_values": x})[0][0]))
present = [label for label, p in zip(config["labels"], probabilities)
if p >= config["thresholds"][label]]
```
Preprocessing: RGB, resized to 256×256 (antialiased bilinear, no crop, aspect ratio not kept),
scaled to [0, 1], normalised with the ImageNet mean and standard deviation, NCHW float32. Each label has
its own threshold in `config.json`, tuned on a validation split.
## Evaluation
On 39 held-out hand-labelled images: mean average precision **0.90**,
macro F1 **0.83** at the tuned thresholds. The set is small: per-label scores
are indicative only.
| label | name | positives | AP | F1 |
|---|---|---:|---:|---:|
| `people` | People | 3 | 1.00 | 0.86 |
| `animals` | Animals | 4 | 1.00 | 1.00 |
| `nature` | Plants | 0 | - | 0.00 |
| `landscape` | Landscape | 1 | 1.00 | 0.67 |
| `buildings` | Buildings / structures | 0 | - | 0.00 |
| `vehicles` | Vehicles | 1 | 1.00 | 1.00 |
| `food` | Food | 1 | 1.00 | 1.00 |
| `text` | Text | 17 | 1.00 | 0.87 |
| `handwriting` | Handwriting | 5 | 0.94 | 0.83 |
| `chart` | Chart | 5 | 1.00 | 0.89 |
| `diagram` | Diagram | 3 | 1.00 | 0.80 |
| `table` | Table | 8 | 0.94 | 0.86 |
| `map` | Map | 2 | 1.00 | 1.00 |
| `logo-icon` | Logo / icon | 3 | 0.51 | 0.44 |
| `formula` | Formula | 0 | - | 0.00 |
| `screen` | Screen / UI | 2 | 0.83 | 0.67 |
| `artwork` | Artwork | 2 | 0.35 | 0.50 |
| `instruments` | Instruments | 0 | - | 0.00 |
| `furniture` | Furniture | 0 | - | 0.00 |
| `aerial` | Aerial | 1 | 1.00 | 1.00 |
### How it compares
Against v0.2 on the same 39 independent hand-labelled images: better yes/no decisions (macro
F1 0.83 against 0.73 at each version's thresholds) and better ranking (mean AP 0.91 against
0.79). Clearly better on People (AP 1.00 against 0.67), Handwriting (0.94 / 0.69), Table
(0.94 / 0.58), Diagram (1.00 / 0.71) and Landscape. Weaker on Logo / icon (0.51 against
0.92). Thresholds are now tuned on 8,104 validation images instead of 95. On an earlier set
of 95 hand-labelled images it was the best of all v0.3 candidates (mean AP 0.86). Plants,
Buildings, Formula, Instruments and Furniture have no test image in the 39; per-label scores
rest on 1 to 17 images: indicative only.
## Training
- Backbone: `mobilenetv4_conv_medium.e500_r256_in1k` (ImageNet-pretrained, via timm), with a new
20-way sigmoid head; 30 epochs, AdamW, binary cross-entropy per label.
- Data: Three vision-language models on the Albert API (Gemma 4 31B, Ministral 3 8B, Mistral Small 3.2 24B) answered the attribute question for about 81,000 images; an attribute counts only when all three picked it. Each image counts under its rarest attribute, at most 2,000 per attribute were kept for training (38,386 images); the 645 hand-labelled images are in the pool with their teacher labels like any other. Thresholds are tuned on the 8,104 teacher-labelled validation images. Test: 39 hand-labelled images that neither this version nor v0.2 trained on or tuned thresholds on. Same weights and thresholds as v0.3.0-rc.3.
- The images come from public collections: photo datasets, document and form scans, charts,
diagrams, screenshots, maps, artwork and icons.
## Limitations
- Small text-related details (a small table inside a document, a signature) are harder than
whole-image subjects.
- The training images come from many public collections, some under research-only or
non-commercial terms. Check whether that matters for your use.
## Licence
The model weights and `config.json` are released under the Apache License 2.0, like the
MobileNetV4 backbone they start from. The licence covers the model, not the images it was trained on.
## Versions
Each version on hand-labelled test images it never trained on (mean AP and macro F1). The test sets
differ between some versions, so compare versions through the notes of each version:
| version | date | test images | mean AP | macro F1 | |
|---|---|---:|---:|---:|---|
| **v0.3.0** | 2026-10-15 | 39 | 0.90 | 0.83 | trained on 38,386 images where three Albert vision-language models agree (same data as WhatDoWeSee-EfficientNet-B0 v0.3.0) |
| **v0.3.0-rc.3** | 2026-10-15 | 95 | 0.86 | 0.71 | release candidate, trained on 38,386 images where all three Albert vision-language models agree (same data as WhatDoWeSee-EfficientNet-B0 v0.3.0-rc.3) |
| **v0.3.0-rc.2** | 2026-10-15 | 38 | 0.81 | 0.74 | release candidate, v0.3.0-rc.1 with stable thresholds (same data as WhatDoWeSee-EfficientNet-B0 v0.3.0-rc.2) |
| **v0.3.0-rc.1** | 2026-10-15 | 38 | 0.81 | 0.76 | release candidate (same data as WhatDoWeSee-EfficientNet-B0 v0.3.0-rc.1), trained on 38,710 images labelled by three Albert vision-language models |
| **v0.2** | 2026-10-14 | 95 | 0.82 | 0.74 | trained on 20,551 images labelled by a SigLIP 2 probe plus the 444 hand labels |