Learn behavioral constraints from failures. 22× more sample-efficient than learning from positive examples alone.
The insight: the space of "bad actions in context" is smaller and more learnable than "all good actions." A few burns teach "don't touch hot stoves" faster than enumerating all safe kitchen behaviors.
Safe AI systems must know what NOT to do. Current approaches:
- Positive examples only: Requires exhaustive coverage of good behaviors
- Reward shaping: Catches problems after deployment
- Hard-coded rules: Brittle, doesn't adapt to novel contexts
This framework implements Minsky's "censors and suppressors" (Society of Mind): accumulate crystallized negative knowledge from failures.
| Constraint Type | Negative Examples | Positive Examples | Speedup |
|---|---|---|---|
| Sequential ("After A, don't do B") | 9 | ~200 | 22× |
| Perceptual ("If X, avoid Y") | 3-5 | 50-100 | 10-20× |
| Generalized ("For class C, avoid Y") | 10-15 | 200+ | 15× |
| Property | Value |
|---|---|
| Activation threshold | 3 failures |
| Max suppression | 95% (never complete block) |
| Decay on success | 10% per success |
| Generalization threshold | 5 contexts |
Censors weaken when suppressed actions unexpectedly succeed - bidirectional self-correction.
git clone https://github.com/rohan-vinaik/negative-learning
cd negative-learning
pip install -e .from negative_learning import CensorRegistry, CensorContext
registry = CensorRegistry()
context = CensorContext(perceptual={'object_type': 'fragile'})
# Learn from failures
for _ in range(5):
registry.learn(context, action='HARD_GRIP', success=False)
suppression = registry.query(context, 'HARD_GRIP')
print(f"Suppression: {suppression:.2f}") # 0.50# Failures across different symmetry types
for sym_type in ['horizontal', 'vertical', 'point', 'diagonal', 'rotational']:
ctx = CensorContext(perceptual={'symmetry_type': sym_type})
for _ in range(2):
registry.learn(ctx, action='FILL_ROW', success=False)
# Generalized censor applies to NEW symmetry types
new_ctx = CensorContext(perceptual={'symmetry_type': 'glide'})
print(registry.query(new_ctx, 'FILL_ROW')) # 0.47Perceptual: "If I see fragile objects, don't grip hard"
context = CensorContext(perceptual={'object_type': 'fragile'})
registry.learn(context, 'HARD_GRIP', success=False)Sequential: "After ROTATE, don't immediately SCALE"
context = CensorContext(sequential={'last_action': 'ROTATE'})
registry.learn(context, 'SCALE', success=False)Outcome: "For containment problems, avoid DELETE_BOUNDARY"
context = CensorContext(outcome={'archetype': 'containment'})
registry.learn(context, 'DELETE_BOUNDARY', success=False)Censor Registry
├── PERCEPTUAL: "If X, don't Y"
├── SEQUENTIAL: "After A, ¬B"
└── OUTCOME: "For type T, ¬P"
Query: O(1) dictionary lookup
Learn: Strengthen on failure (+0.1), weaken on success (×0.9)
Generalize: 5+ failures across contexts → abstract anti-pattern
export PYTHONPATH=$PYTHONPATH:src
python examples/demo_sample_efficiency.py # 22× speedup demo
pytest tests/ -v- Minsky's Censors and Suppressors (Society of Mind, 1986)
- Winston's Near-Miss Learning (1970)
MIT License