File size: 8,263 Bytes
82d31f0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | ---
license: cc-by-4.0
base_model: laion/CLIP-ViT-B-32-laion2B-s34B-b79K
pipeline_tag: zero-shot-classification
library_name: pointcal-c
tags:
- 3d
- point-cloud
- modelnet40-c
- clip
- calibration
- selective-prediction
- uncertainty
- zero-shot
---
# PointCal-C — selective zero-shot 3D recognition under corruption
A post-hoc **calibration and abstention head** on top of a frozen OpenCLIP
ViT-B/32, for zero-shot 3D point-cloud recognition under corruption, plus the
complete evaluation artifacts backing it.
Code: <https://github.com/crimsonKn1ght/pointcal-c>
## What the model is
The backbone is **never trained**. `laion/CLIP-ViT-B-32-laion2B-s34B-b79K` is
loaded frozen, in eval mode, with `requires_grad_(False)`.
The fitted model is **four scalars**, in `runs/full/results/calibration.json`,
fit on clean calibration objects only — corrupted labels, corruption identity
and severity never touch a fitted parameter:
| parameter | value | role |
|---|---|---|
| `temperature` | 1.2309 | divides logits before softmax |
| `bias` | -1.5723 | combined-score intercept |
| `weight_confidence` | +1.7071 | on `logit(p_calibrated)` |
| `weight_disagreement` | +4.9158 | on cross-view disagreement `d` |
Combined score: `sigmoid(bias + w_conf * logit(p_cal) + w_dis * d)`, where `d`
is `1 -` mean pairwise Jensen-Shannon divergence across the six views.
Converged, unclamped, not degenerate. Fit in 0.94 s on CPU.
## How inference works
```
point cloud (N,1024,3)
-> centroid-center, unit-radius normalize
-> 6 orthographic cameras [front right back left top bottom]
-> 64x64 splat raster + nearest-depth z-buffer -> upsample to 224x224
-> frozen OpenCLIP ViT-B/32 image encoder
-> per-view logits vs a fixed 8-template prompt ensemble <-- cached here
-> mean over views -> the prediction
-> four confidence scores over that one prediction
```
All four confidence methods (`msp`, `temperature`, `disagreement`, `combined`)
rank the **same** predictions. A confidence method that changed a prediction
would be a different classifier, and `assert_predictions_unchanged` raises if
one ever does.
## Results
All 75 corrupted conditions pooled against clean, 1975 evaluation objects,
95% bootstrap intervals resampled over base object IDs:
| | accuracy | ECE (MSP) | ECE (combined) | AURC (MSP) | AURC (combined) |
|---|---|---|---|---|---|
| clean | 0.2896 | 0.1160 | 0.0245 | 0.4339 | 0.4147 |
| corrupted | 0.2354 | 0.1416 | 0.0229 | 0.5217 | 0.5008 |
Accuracy degrades under corruption and MSP calibration degrades with it. The
clean-fit combined score holds ECE near **0.023** under shift and lowers AURC
by 0.021.
The ECE improvement is large and consistent. **The AURC gain is small** and
should be read against the intervals in `results.csv`, not as a headline. This
is a reliability audit and a bounded abstention baseline, not a
state-of-the-art claim.
Accuracy by severity: 0.2896 (clean), 0.2593, 0.2515, 0.2388, 0.2252, 0.2023 —
monotonically non-increasing.
### Pre-registered hypotheses
Of the four pre-registered hypotheses, three are mechanically checked. H2 and H3
resolve True. **H1 does not hold strictly:** accuracy, NLL, Brier and AURC all
worsen monotonically with severity, but ECE dips at severities 3→4 and again
from clean→1. A paired object-grouped bootstrap places both reversals within
noise of zero, so H1 is supported in direction but not as strict monotonicity.
H4 is read off the family-scope rows rather than reduced to a verdict.
## Repository contents
The expensive artifact is `runs/*/logits/` — per-view logits for every
condition under both prompt modes. Every metric, ablation, bootstrap interval
and figure here was computed on CPU from those caches, so **any re-analysis is
free**: a different aggregation, disagreement statistic, coverage level or
bootstrap depth costs no GPU time, because CLIP never runs again.
```
runs/<tier>/
logits/<condition>.npz per-view logits, both prompt modes (~1.4 MB each)
results/calibration.json the fitted scalars above
results/results.csv|.json metrics table with intervals
results/ablations.csv view-count, prompt-mode, disagreement ablations
results/predictions.npz per-sample confidences and correctness
results/results_summary.md auto-generated tables + hypothesis checks
figures/fig1..fig4 accuracy, ECE, risk-coverage, cost
provenance/ data manifest, run manifest, split audit
ledger_inference.json measured GPU-hours, dollars, throughput, memory
artifacts/split.json the frozen calibration/evaluation object split
env/requirements.lock.txt exact resolved environment (171 packages)
```
Tiers: `xs` (5 conditions, 100 objects), `s` (13 conditions), `full` (all 76 =
clean + 15 corruptions x 5 severities).
## Training / evaluation data
Evaluated on **ModelNet40-C** (2468 objects, 40 classes, 15 corruption types,
5 severities). The calibration scalars are fit on the clean split of 493
calibration objects; 1975 evaluation objects are held out.
The split is over **base object IDs**, not samples, and every corruption array
is verified row-aligned with the clean array, so holding an object out of
calibration holds it out under all 76 conditions. Audited: `overlap: 0`,
0 row-misaligned conditions, all 40 classes present on both sides.
## Compute
| tier | conditions | GPU-hours | USD | views/s | peak VRAM |
|---|---|---|---|---|---|
| xs | 5 | 0.001 | 0.0003 | 1091 | 2.5 GB |
| s | 13 | 0.015 | 0.004 | 2816 | 12.1 GB |
| full | 76 | 0.089 | 0.025 | 2808 | 12.1 GB |
**0.105 GPU-hours and about $0.03** of inference in total, on a single Runpod
RTX 4000 Ada at $0.28/hr (2026-08-16).
## Known defects
See **[ERRATUM.md](ERRATUM.md)** for the full list. In short: the `ledger` block
embedded in `runs/full/provenance/run_manifest.json` is wrong — it records a
cache-hit re-invocation, not the real run. **Trust `ledger_inference.json`,**
which every figure and the compute table above are derived from. `git_dirty` in
that manifest is not meaningful either, because the dirtiness check counts
expected untracked artifacts.
## Limitations
- `full` uses **200** bootstrap replicates, not the preregistered 1000. The CPU
bootstrap dominated runtime (~2 h at 1000 vs ~5 min of GPU work). Deeper
intervals recompute from the cached logits at no GPU cost.
- NLL and Brier require a distribution over all 40 classes, so they are reported
for `msp` and `temperature` only. For the two ranking scores they are `null`,
not a lookalike substitute.
- `delta_*_vs_clean` rows in `results.csv` carry `NaN` intervals: degradation is
reported as point estimates without paired bootstrap intervals. Method
differences should likewise not be read from the marginal intervals alone.
- Cross-view disagreement is prior art, and calibration degrading under 3D
corruption is a confirmation rather than a discovery.
- Absolute accuracy is low (~0.29 clean). This is zero-shot transfer of a 2D
model to depth renders, with no 3D training whatsoever.
- Severity is reported **1-indexed**, matching the on-disk release.
## Provenance
- Frozen spec hash: `ca487597c978ab17217bd640ab8bf95c8a21db0eaacd51ae5ba4b00618dcc820`
- Backbone checkpoint SHA-256:
`1bd3c7172de5b207ceac554f5ab5266166f3b9baccc9af5989bc801016d080ad`
- Split fingerprint: `cc5ed4b3ce7108154039f497d474f3ac6bdbfe7eb7dbfe4d0f90785e1829bb31`
## Licence and attribution
Cached logits and metrics are **derived from ModelNet40-C** and redistributed
under **CC BY 4.0**, as the source record declares.
- ModelNet40-C — Zenodo [6017834](https://zenodo.org/records/6017834),
DOI `10.5281/zenodo.6017834`, CC BY 4.0
- Generation code — <https://github.com/jiachens/ModelNet40-C>, BSD-3-Clause
- Underlying ModelNet40 carries its own original terms
- OpenCLIP — MIT · PointCal-C code — MIT
The multi-view depth-projection approach follows the PointCLIP paper (CVPR
2022); the projector is an independent reimplementation from the paper text,
with no PointCLIP repository code used.
|