@qriton/hopfield-anomaly
v4.0.1
Published
Production-ready Binary and Continuous (Modern) Hopfield Neural Networks for anomaly detection and cross-domain discovery
Maintainers
Readme
@qriton/hopfield-anomaly
Qriton's Production-ready Binary and Continuous (Modern) Hopfield Neural Networks for real-time anomaly detection, adaptive thresholds, and cross-domain discovery.
🚀 Features
Binary Hopfield (v1-3)
✅ Hard Anomaly Detection — Binary threshold-based classification ✅ Z-Score Normalization — Statistically grounded anomaly scoring ✅ Configurable Weights — Tune detection for your domain ✅ Gradient-Based Attribution — Identify root cause features (O(N²) optimized) ✅ Adaptive Thresholds — Unsupervised auto-tuning (95th percentile) ✅ Correlation-Aware Capacity — Prevents spurious attractors ✅ Seeded RNG — Reproducible debugging ✅ Storkey Learning — Higher capacity networks
Continuous Hopfield (v4.0.0+)
✅ Modern Hopfield Networks — Real-valued states with exponential capacity ✅ Soft Anomaly Detection — Preserves continuous feature values ✅ Cross-Domain Discovery — Detect pattern mixing ("Eureka moments") ✅ Pattern Composition — "60% pattern A, 40% pattern B" ✅ Attention Mechanism — Transformer-style attention weights ✅ Arrow of Discovery — Gradient direction showing where data differs ✅ Two Energy Types — LogSumExp (Modern) and Quadratic
📦 Installation
npm install @qriton/hopfield-anomaly⚡ Quick Start
Binary Hopfield (Hard Anomaly Detection)
const { HopfieldAnomalyDetector } = require('@qriton/hopfield-anomaly');
// Initialize detector
const detector = new HopfieldAnomalyDetector({
featureCount: 3,
snapshotLength: 5,
anomalyThreshold: 0.3,
learningRule: 'storkey',
scoreWeights: { energy: 0.25, drop: 0.25, hamming: 0.25, margin: 0.25 },
seed: 12345
});
// Define thresholds
detector.setThresholds({
temperature: { mode: 'range', min: 60, max: 80 },
pressure: { mode: 'range', min: 95, max: 105 },
vibration: { mode: 'below', value: 50 }
});
// Train network
detector.train({ useDefaults: true });
// Process data points
for (let i = 0; i < 5; i++) {
detector.addDataPoint({ temperature: 70, pressure: 100, vibration: 20 });
}
// Detect anomalies
const result = detector.detect();
console.log(result.isAnomaly); // false
console.log(result.anomalyScore); // 0.245
console.log(result.confidence); // 0.055
console.log(result.featureImpact[0]); // { name: 'temperature', energyDelta: -0.123 }Continuous Hopfield (Soft Anomaly Detection) (New in v4.0.0)
const { ContinuousHopfieldAnomalyDetector } = require('@qriton/hopfield-anomaly');
// Initialize continuous detector
const detector = new ContinuousHopfieldAnomalyDetector({
featureCount: 3,
snapshotLength: 5,
energyType: 'logsumexp', // Modern Hopfield
beta: 1.0, // Temperature inverse
seed: 12345
});
// Set feature names and normalization ranges
detector.setFeatures(['temperature', 'pressure', 'vibration'], {
temperature: { min: 0, max: 100 },
pressure: { min: 0, max: 200 },
vibration: { min: 0, max: 50 }
});
// Train network
detector.trainWithDefaults();
// Process data points (continuous values)
for (let i = 0; i < 5; i++) {
detector.addDataPoint({ temperature: 70.5, pressure: 105.2, vibration: 12.3 });
}
// Detect anomalies with rich output
const result = detector.detect();
console.log(result.isAnomaly); // false
console.log(result.anomalyScore); // 0.182
console.log(result.composition[0]); // { patternIndex: 0, similarity: 0.95, percentage: 72 }
console.log(result.featureGradients[0]); // { name: 'pressure', gradientNorm: 0.234 }📊 Performance Characteristics
| Network Size (N) | Memory | Recall Latency | Training Time | |------------------|--------|----------------|---------------| | 100 neurons | ~80KB | ~0.5ms | ~10ms | | 500 neurons | ~2MB | ~15ms | ~200ms | | 1000 neurons | ~8MB | ~80ms | ~1.5s |
Tested on Node.js v18, Intel i7-9700K
Run your own benchmarks:
npm run benchmark🧠 API Reference
HopfieldAnomalyDetector
Constructor Options
{
featureCount: number, // Required: number of features to monitor
snapshotLength: 5, // Time window size
anomalyThreshold: 0.3, // Detection threshold
maxIterations: 10, // Recall convergence limit
learningRule: 'hebbian', // 'hebbian' or 'storkey'
adaptiveThreshold: true, // Enable auto-tuning
unsupervisedAdaptive: true, // Use percentile (true) or labeled feedback (false)
scoreWeights: { // Configurable scoring weights
energy: 0.25,
drop: 0.25,
hamming: 0.25,
margin: 0.25
},
strictCapacity: false, // Throw error if capacity exceeded
seed: null // RNG seed for reproducibility
}Methods
setThresholds(thresholds, featureNames?)
detector.setThresholds({
temp: { mode: 'range', min: 60, max: 80 },
status: { mode: 'equal', value: 1 },
cpu: { mode: 'below', value: 80 },
memory: { mode: 'above', value: 1000 }
});train(options?)
// Auto-generate patterns
detector.train({ useDefaults: true });
// Custom patterns
detector.train({
patterns: [
[-1, -1, 1, 1, -1],
[1, -1, -1, 1, 1]
]
});trainWithDefaults() (New in v3.2.0)
// Explicit method for default training
detector.trainWithDefaults();addDataPoint(features)
const ready = detector.addDataPoint({ temp: 70, status: 1, cpu: 45, memory: 2048 });
// Returns true when buffer is fulldetect()
const result = detector.detect();
// Returns null if buffer not full
// Otherwise returns detection resultgetStats()
const stats = detector.getStats();
console.log(stats.anomaliesDetected);
console.log(stats.anomalyRate);
console.log(stats.baseline); // Z-score baselines (v3.2.0+)
console.log(stats.thresholdStats); // Adaptive threshold statsstatic benchmark(config) (New in v3.3.0)
const perf = HopfieldAnomalyDetector.benchmark({
featureCount: 10,
snapshotLength: 5,
dataPoints: 1000
});
console.log(perf.averageDetectLatency); // ms
console.log(perf.throughput); // points/secexportConfig() / fromConfig(config)
const config = detector.exportConfig();
const restored = HopfieldAnomalyDetector.fromConfig(config);Detection Result Structure
{
isAnomaly: boolean,
anomalyScore: number, // Z-score based (v3.2.0+)
confidence: number,
timestamp: string,
snapshot: number[],
recalledPattern: number[],
contributingFeatures: [ // Legacy (activation-based)
{ name: string, index: number, activation: number, pattern: number[] }
],
featureImpact: [ // NEW in v3.2.0 (gradient-based)
{ name: string, index: number, energyDelta: number }
],
energy: number,
metrics: {
energyInput: number,
energyRecalled: number,
energyDrop: number,
hammingDistance: number,
relativeHamming: number,
margin: number,
zEnergy: number, // NEW in v3.2.0
zDrop: number, // NEW in v3.2.0
zHamming: number, // NEW in v3.2.0
zMargin: number // NEW in v3.2.0
},
convergence: {
iterations: number,
energyPath: number[],
converged: boolean
}
}ContinuousHopfieldAnomalyDetector (New in v4.0.0)
Constructor Options
{
featureCount: number, // Required: number of features to monitor
snapshotLength: 5, // Time window size
anomalyThreshold: 0.3, // Detection threshold
maxIterations: 100, // Gradient descent iterations
energyType: 'logsumexp', // 'logsumexp' (Modern) or 'quadratic'
beta: 1.0, // Temperature inverse (higher = sharper)
learningRate: 0.1, // Gradient descent step size
normalizeFeatures: true, // Auto-normalize to [-1, 1]
adaptiveThreshold: true, // Enable auto-tuning
seed: null // RNG seed for reproducibility
}Methods
setFeatures(names, ranges?)
detector.setFeatures(['temp', 'pressure', 'vibration'], {
temp: { min: 0, max: 100 },
pressure: { min: 0, max: 200 },
vibration: { min: 0, max: 50 }
});trainWithDefaults()
// Generate default patterns for continuous detector
detector.trainWithDefaults();train(patterns)
// Custom continuous patterns (values in [-1, 1])
detector.train([
[0.5, -0.3, 0.8, ...],
[-0.2, 0.7, -0.1, ...]
]);addDataPoint(features)
const ready = detector.addDataPoint({ temp: 70.5, pressure: 105.2, vibration: 12.3 });
// Returns true when buffer is fulldetect()
const result = detector.detect();
// Returns rich detection result with composition, gradientsgetAttention(state)
// Get attention weights over stored patterns
const attention = detector.getAttention(state);
console.log(attention); // [0.8, 0.15, 0.05, ...]Continuous Detection Result Structure
{
isAnomaly: boolean,
anomalyScore: number, // Z-score based
confidence: number,
timestamp: string,
snapshot: number[], // Continuous values in [-1, 1]
recalledPattern: number[], // Nearest attractor
composition: [ // Pattern mixing analysis
{ patternIndex: number, similarity: number, percentage: number }
],
gradient: number[], // "Arrow of discovery" - deviation direction
featureGradients: [ // Per-feature gradient impact
{ name: string, index: number, gradientNorm: number }
],
energy: number,
metrics: {
energyInput: number,
energyRecalled: number,
energyDrop: number,
compositionEntropy: number, // Pattern mixing measure
gradientNorm: number, // Overall gradient magnitude
zEnergy: number,
zGradient: number,
zComposition: number
},
convergence: {
iterations: number,
energyPath: number[],
converged: boolean
}
}⚙️ Advanced Usage
High-Level Monitor API (Binary)
const { AnomalyMonitor } = require('@qriton/hopfield-anomaly');
const monitor = new AnomalyMonitor({ featureCount: 3 })
.setThresholds({
temp: { mode: 'range', min: 60, max: 80 },
pressure: { mode: 'range', min: 95, max: 105 },
vibration: { mode: 'below', value: 50 }
})
.train({ useDefaults: true })
.on('onAnomaly', (result) => console.log('⚠️ Anomaly:', result.anomalyScore))
.on('onNormal', (result) => console.log('✅ Normal:', result.anomalyScore));
// Stream metrics
monitor.process({ temp: 70, pressure: 100, vibration: 20 });High-Level Monitor API (Continuous) (New in v4.0.0)
const { ContinuousAnomalyMonitor } = require('@qriton/hopfield-anomaly');
const monitor = new ContinuousAnomalyMonitor({ featureCount: 3 })
.setFeatures(['temp', 'pressure', 'vibration'], {
temp: { min: 0, max: 100 },
pressure: { min: 0, max: 200 },
vibration: { min: 0, max: 50 }
})
.trainWithDefaults()
.on('onAnomaly', (result) => console.log('Anomaly:', result.anomalyScore))
.on('onCrossDomain', ({ primaryPattern, secondaryPattern, mixing }) => {
console.log(`Cross-domain: ${mixing * 100}% mixing between patterns`);
});
// Stream continuous metrics
monitor.process({ temp: 70.5, pressure: 105.2, vibration: 12.3 });Custom Scoring Weights (New in v3.3.0)
const detector = new HopfieldAnomalyDetector({
featureCount: 3,
scoreWeights: {
energy: 0.4, // Emphasize energy deviation
drop: 0.2,
hamming: 0.3,
margin: 0.1
}
});Strict Capacity Mode (New in v3.3.0)
const detector = new HopfieldAnomalyDetector({
featureCount: 3,
learningRule: 'hebbian',
strictCapacity: true // Throws error if pattern count exceeds capacity
});
try {
detector.network.train(tooManyPatterns);
} catch (err) {
console.error('Capacity exceeded:', err.message);
}Custom Learning Rules
// Hebbian (default) - Capacity: ~0.138 * N
const detector1 = new HopfieldAnomalyDetector({ featureCount: 3, learningRule: 'hebbian' });
// Storkey (higher capacity) - Capacity: ~0.25 * N
const detector2 = new HopfieldAnomalyDetector({ featureCount: 3, learningRule: 'storkey' });Adaptive Threshold Tuning
// Unsupervised mode (default) - automatically sets to 95th percentile
const detector = new HopfieldAnomalyDetector({
featureCount: 3,
adaptiveThreshold: true,
unsupervisedAdaptive: true
});
// Supervised mode - manual feedback for labeled data
detector.adaptiveThreshold.update(
0.45, // anomaly score
true, // labeled data
true // actually an anomaly
);💻 Integration Examples
Example 1: Express.js API
const express = require('express');
const { HopfieldAnomalyDetector } = require('@qriton/hopfield-anomaly');
const app = express();
app.use(express.json());
const detector = new HopfieldAnomalyDetector({
featureCount: 4,
snapshotLength: 5,
learningRule: 'storkey',
adaptiveThreshold: true
});
detector.setThresholds({
cpu: { mode: 'above', value: 80 },
memory: { mode: 'above', value: 75 },
disk: { mode: 'above', value: 90 },
network: { mode: 'above', value: 1000 }
});
detector.train({ useDefaults: true });
app.post('/detect', (req, res) => {
const ready = detector.addDataPoint(req.body);
if (ready) {
const result = detector.detect();
res.json({
...result,
topFeature: result.featureImpact[0].name // Root cause
});
} else {
res.json({ status: 'buffering' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));Example 2: Real-Time Streaming (WebSockets)
const http = require('http');
const socketIo = require('socket.io');
const { AnomalyMonitor } = require('@qriton/hopfield-anomaly');
const server = http.createServer();
const io = socketIo(server);
const monitor = new AnomalyMonitor({ featureCount: 3, snapshotLength: 5, learningRule: 'hebbian', seed: 42 });
monitor.setThresholds({
temp: { mode: 'range', min: 60, max: 80 },
pressure: { mode: 'range', min: 95, max: 105 },
vibration: { mode: 'below', value: 50 }
});
monitor.train({ useDefaults: true });
io.on('connection', socket => {
socket.on('metrics', data => {
const result = monitor.process(data);
if (result) socket.emit('detection', result);
});
});
server.listen(3000, () => console.log('WebSocket server on port 3000'));🧩 Use Cases
Binary Hopfield
- ✅ IoT sensor monitoring
- ✅ Network security & intrusion detection
- ✅ Server & process health monitoring
- ✅ Financial time-series anomaly detection
- ✅ Manufacturing & quality control
- ✅ Application performance monitoring (APM)
- ✅ Threshold-based binary monitoring
Continuous Hopfield (New in v4.0.0)
- ✅ Cross-domain pattern discovery
- ✅ Soft anomaly detection with gradients
- ✅ Semantic similarity analysis
- ✅ Pattern interpolation ("60% A, 40% B")
- ✅ "Eureka moment" detection (novel combinations)
- ✅ Continuous sensor data without binarization
🧬 How It Works
Hopfield networks store patterns as energy minima in a recurrent neural network.
Normal data converges to stable, low-energy states, while anomalies result in unstable or high-energy configurations.
Detection Pipeline
- Binarization: Features → binary patterns via thresholds
- Snapshot: Sliding window builds temporal pattern
- Recall: Hopfield network stabilizes toward learned attractors
- Scoring: Z-scored energy, margin, and Hamming distance
- Attribution: Gradient-based feature impact (O(N²) optimized)
- Adaptation: Threshold adjusts to 95th percentile
Key Advantages
- 🧠 Interpretable: Energy landscape reveals "why" (not just "what")
- 🎯 Deterministic: Seeded RNG ensures reproducibility
- ⚡ Fast: O(N²) recall + O(N²+MN) attribution
- 📊 Statistical: Z-score normalization prevents scale issues
- 🔧 Configurable: Tune weights for your domain
📈 Changelog
v4.0.0 (2025-11-19)
Major Release: Continuous (Modern) Hopfield Networks
Added:
ContinuousHopfieldNetwork- Real-valued states in [-1, 1] with exponential capacityContinuousHopfieldAnomalyDetector- Soft anomaly detection without binarizationContinuousAnomalyMonitor- High-level API withonCrossDomainevent- Two energy functions:
logsumexp(Modern Hopfield) andquadratic - Pattern composition analysis ("60% pattern A, 40% pattern B")
- Attention mechanism via
getAttention()method - Gradient-based "arrow of discovery" showing deviation direction
Use Cases:
- Binary Hopfield: Hard anomaly detection, error classification, noise removal
- Continuous Hopfield: Cross-domain discovery, soft anomalies, "Eureka moments"
No breaking changes - all v3.x code works unchanged.
See CHANGELOG.md for full migration guide.
v3.4.0 (2025-10-20)
Added:
- Pattern correlation-aware capacity estimation (
estimateCapacity()) - Inline test templates in documentation
- Performance table in README
- Enhanced capacity warnings with correlation adjustment
Changed:
- Capacity checks now account for pattern correlation
- Improved error messages with suggested network sizes
v3.3.0 (2025-10-20)
Added:
- Configurable score weights (
scoreWeightsoption) - Full z-score normalization for all metrics (energy, drop, hamming, margin)
- Optimized gradient-based feature attribution (O(N²+MN) instead of O(M×N²))
- Static
benchmark()method for performance profiling strictCapacitymode for hard capacity enforcement- Baseline statistics tracking for all metrics
Changed:
- Anomaly score formula now uses z-scores across all components
- Default score weights changed to equal (0.25 each)
- Feature impact computation 100× faster via analytical gradients
Fixed:
- Scale sensitivity issues with different network sizes
- Energy normalization now dimensionally correct
v3.2.0 (2025-10-20)
Added:
- Unsupervised adaptive threshold (95th percentile mode)
- Baseline energy statistics with z-score integration
- Gradient-based feature attribution (
featureImpact) trainWithDefaults()explicit method- Z-score metrics in detection results
Changed:
- Adaptive threshold now works without labeled data
- Feature attribution shows causal contribution (not just activation)
Deprecated:
contributingFeatures(legacy, activation-based) - usefeatureImpactinstead
v3.1.0 (Initial Release)
Features:
- Hebbian and Storkey learning rules
- Seeded RNG for reproducibility
- Convergence tracking with energy paths
- Semi-supervised adaptive thresholds
- Event-driven monitoring (AnomalyMonitor)
- JSON export/import for model persistence
🔬 Capacity Guidelines
| Learning Rule | Capacity Formula | 100 Neurons | 500 Neurons | 1000 Neurons | |---------------|------------------|-------------|-------------|--------------| | Hebbian | ~0.138 × N | 13 patterns | 69 patterns | 138 patterns | | Storkey | ~0.25 × N | 25 patterns | 125 patterns| 250 patterns |
⚠️ Warning: Exceeding capacity causes spurious attractors and false positives.
💡 Tip: Use strictCapacity: true to enforce hard limits.
📊 Note: Real capacity is lower for correlated patterns (automatically adjusted in v3.4.0+).
⚠️ When NOT to Use
Consider alternatives for these use cases:
- ❌ Sub-millisecond latency requirements → Pre-compute or use simpler methods
- ❌ Online learning → Hopfield requires batch training
- ❌ > 1000 features → Memory footprint becomes prohibitive (O(N²))
- ❌ Image/video anomalies → Use CNNs or VAEs
- ❌ Very high-dimensional embeddings → Use specialized vector databases
Choose Binary vs Continuous:
- Binary Hopfield: Best for threshold-based monitoring (e.g., "is CPU > 80%?")
- Continuous Hopfield: Best for soft patterns and cross-domain discovery (e.g., "how similar to pattern A vs B?")
🧪 Testing
# Run full test suite
npm test
# Run with coverage
npm run test:coverage
# Run benchmarks
npm run benchmark📄 License
MIT © Qriton
🤝 Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
Issues: GitHub Issues
Discussions: GitHub Discussions
🔗 Links
- npm Package: https://www.npmjs.com/package/@qriton/hopfield-anomaly
- GitHub Repository: https://github.com/qriton/hopfield-anomaly
- Documentation: [See API Reference above]
- Report Issues: https://github.com/qriton/hopfield-anomaly/issues
🙏 Acknowledgments
Based on:
- Hopfield, J.J. (1982). "Neural networks and physical systems with emergent collective computational abilities"
- Amit, D.J., Gutfreund, H., Sompolinsky, H. (1985). "Storing infinite numbers of patterns in a spin-glass model"
- Storkey, A. (1998). "Increasing the capacity of a Hopfield network without sacrificing functionality"
Built with ❤️ by Qriton
