Apoha: Exclusion-Based Few-Shot Classification with Principled OOD Rejection
"A concept is not defined by what it includes, but by what it excludes." — Dignāga, Pramāṇasamuccaya (c. 480–540 CE)
Overview
Apoha is a classification model that defines concepts by exclusion — what they are NOT — rather than shared positive properties. This is a direct implementation of Buddhist Apoha theory (anyāpoha-vāda) from the pramāṇavāda (epistemology) tradition.
The key result: when an input fails to satisfy any concept's exclusion boundary, the model outputs UNCERTAIN instead of forcing a classification. OOD rejection is built into the classification mechanism, not added post-hoc.
On CLINC150 (30 intents, 5 seeds):
- Apoha: 95.6% accuracy, 84.6% OOD rejection
- Best contrastive baseline (InfoNCE): 97.7% accuracy, 15.1% OOD rejection
- Apoha rejects 5.6× more OOD inputs with only a 2.1pp accuracy trade-off
Quick Start
from apoha_inference import ApohaClassifier, ConceptDefinition, Example, ExclusionExample
# 1. Initialise the classifier
clf = ApohaClassifier() # loads fine-tuned encoder automatically
# 2. Define a concept with positives AND exclusions
cardiology = ConceptDefinition(
concept_id="cardiology",
concept_label="Cardiology",
positive_examples=[
Example(id="c1", input="chest pain radiating to left arm"),
Example(id="c2", input="irregular heartbeat and palpitations"),
Example(id="c3", input="elevated troponin levels suggest cardiac damage"),
],
exclusion_set=[
ExclusionExample(id="e1", input="chronic cough with phlegm", excludes_because="respiratory"),
ExclusionExample(id="e2", input="stomach acid reflux after meals", excludes_because="gastroenterology"),
ExclusionExample(id="e3", input="migraine headache with visual aura", excludes_because="neurology"),
],
)
clf.register_concept(cardiology)
# 3. Classify
result = clf.predict("patient presents with irregular heartbeat")
print(result.label) # "cardiology"
print(result.uncertain) # False
print(result.boundary_scores) # {"cardiology": 0.43}
# Out-of-distribution input
result = clf.predict("my stock portfolio crashed")
print(result.label) # "UNCERTAIN"
print(result.uncertain) # True
How It Works
Concept Definition
A concept C is defined by:
- Positive examples P = {p₁, ..., pₘ} — what C is
- Exclusion set N = {n₁, ..., nₖ} — what C is not, with optional reasons
- Margin γ (gamma) — the required separation between core and boundary
Boundary Score
At inference, for input x and concept C:
boundary_score(x, C) = min_{n ∈ N} d(x, n) - mean_{p ∈ P} d(x, p)
where d is cosine distance. The score measures how much further the nearest exclusion is than the average positive.
If the best score across all concepts exceeds γ → classified If no concept's score exceeds γ → UNCERTAIN
The min over exclusions is hard-negative mining: the closest counter-example defines the boundary, analogous to SVM support vectors. This is Dignāga's key insight: a concept boundary is challenged by the single nearest non-member.
Training (Apoha Boundary Loss)
L(x, C) = max(0, γ - [min_{n ∈ N} d(x, n) - mean_{p ∈ P} d(x, p)])
A hinge loss that pushes exclusions at least γ further from the query than the average positive. Fine-tunes the sentence encoder to create sharp exclusion boundaries in embedding space.
Benchmark Results
All results: 5 seeds (42–46), mean ± std Encoder: BAAI/bge-small-en-v1.5 (384d, 33M params) Hardware: NVIDIA L4 (24GB VRAM), CUDA 12.4
CLINC150-OOS (30 intents, 20 train/class)
| Method | Accuracy | Macro-F1 | AUROC | FPR@95 | OOD Rejection |
|---|---|---|---|---|---|
| Apoha | 0.956 ±0.011 | 0.970 ±0.009 | 0.980 ±0.004 | 0.070 ±0.029 | 0.846 ±0.032 |
| InfoNCE | 0.977 ±0.007 | 0.977 ±0.007 | 0.989 ±0.002 | 0.040 ±0.008 | 0.151 ±0.036 |
| ProtoNet | 0.979 ±0.006 | 0.979 ±0.006 | 0.985 ±0.003 | 0.072 ±0.018 | 0.005 ±0.003 |
| Mahalanobis | 0.660 ±0.027 | 0.769 ±0.026 | 0.991 ±0.001 | 0.040 ±0.014 | 0.999 ±0.001 |
| Energy | 0.977 ±0.007 | 0.977 ±0.007 | 0.383 ±0.062 | 0.969 ±0.020 | 0.000 ±0.000 |
Banking77-OOS (50 intents, near-OOD)
| Method | Accuracy | AUROC | OOD Rejection |
|---|---|---|---|
| Apoha | 0.822 ±0.021 | 0.829 ±0.021 | 0.291 ±0.036 |
| InfoNCE | 0.871 ±0.010 | 0.844 ±0.017 | 0.000 ±0.000 |
| ProtoNet | 0.899 ±0.012 | 0.851 ±0.019 | 0.000 ±0.000 |
| Energy | 0.871 ±0.010 | 0.406 ±0.059 | 0.000 ±0.000 |
HWU64-OOS (40 intents, near-OOD)
| Method | Accuracy | AUROC | OOD Rejection |
|---|---|---|---|
| Apoha | 0.813 ±0.019 | 0.816 ±0.053 | 0.249 ±0.077 |
| InfoNCE | 0.868 ±0.014 | 0.798 ±0.085 | 0.002 ±0.001 |
| ProtoNet | 0.895 ±0.015 | 0.801 ±0.031 | 0.000 ±0.000 |
| Energy | 0.868 ±0.014 | 0.401 ±0.117 | 0.000 ±0.000 |
Cybersecurity — MITRE ATT&CK (15 tactics)
| Method | Accuracy | OOD Rejection | vs InfoNCE |
|---|---|---|---|
| Apoha | 0.621 ±0.017 | 0.452 ±0.048 | 38× |
| InfoNCE | 0.688 ±0.015 | 0.012 ±0.013 | — |
Summary: Apoha vs Best Baseline
| Dataset | Accuracy Gap | Apoha OOD | InfoNCE OOD | OOD Ratio |
|---|---|---|---|---|
| CLINC150 | −2.1pp | 84.6% | 15.1% | 5.6× |
| Banking77 | −4.9pp | 29.1% | 0.0% | ∞ |
| HWU64 | −5.5pp | 24.9% | 0.2% | 166× |
| Cybersecurity | −6.7pp | 45.2% | 1.2% | 38× |
| Medical | −10.6pp | 97.0% | 86.0% | 1.1× |
Ablation Studies (CLINC150, 5 seeds)
| Ablation | Finding |
|---|---|
| Fine-tuned vs raw encoder | 10× accuracy gain (9.5% → 95.8%) — the loss reshapes embedding space |
| Min vs mean over exclusions | Min essential — mean destroys accuracy by 31pp |
| Gamma sweep (0.1–0.7) | Smooth accuracy/OOD trade-off — gamma is a tunable safety knob |
| Exclusion set size (5–50) | 20+ exclusions needed; accuracy stable, OOD rejection scales 47%→89% |
| Loss variants (V1 vs V2 LSE) | V1 (hard-min) best accuracy; V2 LSE trades 4.6pp for 7.3pp more OOD rejection |
When to Use Apoha
Use Apoha when:
- You need the model to abstain on out-of-distribution inputs
- You have 5–20 positive examples per concept (few-shot setting)
- You can articulate what each concept is NOT (exclusion examples)
- Silent misclassification has real costs (safety-critical domains)
Consider alternatives when:
- All inputs are guaranteed in-distribution (closed world)
- You need maximum accuracy and OOD rejection is not required
- You have thousands of training examples per class (contrastive methods may be better)
Known Limitations
- Accuracy trade-off: 2–7pp below contrastive baselines on in-distribution data
- Exclusion set quality: Performance depends on choosing informative exclusions
- Near-OOD: Banking77/HWU64 (semantically similar OOD) is harder (25–29% rejection vs 84% on CLINC150)
- Binary classification: ADE drug safety dataset (binary, overlapping domains) is not a good fit — both classes' exclusion sets overlap with each other's positives
- Scalability: Tested up to 50 concepts; behavior with hundreds is untested
Philosophical Grounding
Apoha is a direct implementation of anyāpoha-vāda — the exclusion theory of meaning developed by the Indian Buddhist logician Dignāga (c. 480–540 CE) and refined by Dharmakīrti (c. 600–660 CE) in the pramāṇavāda (valid cognition) tradition.
The core insight: concepts are not defined by shared positive properties ("cow" is not defined by what cows have in common) but by exclusion of non-members ("cow" is "not-non-cow" — everything that fails to be excluded by the concept's boundaries).
This maps directly onto machine learning:
- Exclusion sets → hard-negative mining
- Margin boundaries → SVM support vectors
- The closest counter-example defines the boundary (Dignāga's key insight, validated by ablation)
- UNCERTAIN output → Dignāga's epistemological principle that absence of sufficient evidence is itself informative
The philosophical tradition was developed by Dobdon Maksarov (Geshe Lharampa, SOAS PhD) and implemented in ML by Alexander Khundoev.
For a modern philosophical treatment, see:
- Siderits, M., Tillemans, T., & Chakrabarti, A. (2011). Apoha: Buddhist Nominalism and Human Cognition. Columbia University Press.
- Hattori, M. (1968). Dignāga, On Perception. Harvard University Press.
- Dunne, J. D. (2004). Foundations of Dharmakīrti's Philosophy. Wisdom Publications.
- Downloads last month
- 56