Skip to content

rohanvinaik/negative-learning

Repository files navigation

Negative Learning

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.


The Problem

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.


Key Results

Sample Efficiency

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×

Behavior

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.


Quick Start

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

Automatic Generalization

# 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.47

The Three Censor Types

Perceptual: "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)

Architecture

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

Tests

export PYTHONPATH=$PYTHONPATH:src
python examples/demo_sample_efficiency.py  # 22× speedup demo
pytest tests/ -v

Foundation

  • Minsky's Censors and Suppressors (Society of Mind, 1986)
  • Winston's Near-Miss Learning (1970)

MIT License

About

Learning behavioral constraints from negative examples - Minsky's censors and suppressors for AI safety

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages