docker-neural-memory / src /memory /consolidation.py
macayaven's picture
Upload folder using huggingface_hub
dd41762 verified
Raw
History Blame Contribute Delete
3.95 kB
"""
Memory consolidation - compressing recent learning into stable patterns.
Like sleep for neural memory: strengthens important patterns,
prunes noise, and prevents catastrophic forgetting.
"""
from typing import Dict, List, Union
import torch
import torch.nn as nn
from torch import Tensor
class MemoryConsolidator:
"""
Consolidates memory by compressing recent learning into stable patterns.
Uses Elastic Weight Consolidation (EWC) to protect important weights.
"""
def __init__(self, ewc_lambda: float = 0.1):
"""
Initialize consolidator.
Args:
ewc_lambda: Weight for EWC penalty term
"""
self.ewc_lambda = ewc_lambda
self.fisher: Dict[str, Tensor] = {}
self.optimal: Dict[str, Tensor] = {}
def compute_fisher(self, model: nn.Module, data_loader: List[Tensor]) -> None:
"""
Compute Fisher information matrix for EWC.
The Fisher matrix measures how important each weight is
for the current task.
"""
self.fisher = {}
self.optimal = {}
# Store current optimal weights
for name, param in model.named_parameters():
self.optimal[name] = param.clone().detach()
self.fisher[name] = torch.zeros_like(param)
model.eval()
for x in data_loader:
model.zero_grad()
output = model(x)
# Use reconstruction loss as proxy for importance
loss = output.sum()
loss.backward()
for name, param in model.named_parameters():
if param.grad is not None:
self.fisher[name] += param.grad.data.pow(2)
# Normalize Fisher values
for name in self.fisher:
self.fisher[name] /= len(data_loader)
def ewc_loss(self, model: nn.Module, current_loss: Tensor) -> Tensor:
"""
Add EWC penalty to protect important weights from past tasks.
Args:
model: The neural memory model
current_loss: Current task loss
Returns:
Loss with EWC penalty added
"""
if not self.fisher:
return current_loss
ewc_penalty = torch.tensor(0.0, device=current_loss.device)
for name, param in model.named_parameters():
if name in self.fisher:
ewc_penalty += (self.fisher[name] * (param - self.optimal[name]).pow(2)).sum()
return current_loss + self.ewc_lambda * ewc_penalty
def consolidate(
self, model: nn.Module, recent_observations: List[Tensor]
) -> Dict[str, Union[int, float]]:
"""
Perform consolidation pass.
Args:
model: Neural memory model
recent_observations: Recent data to identify important patterns
Returns:
Consolidation metrics
"""
# Create simple data loader from observations
data_loader = recent_observations
# Compute new Fisher information
old_fisher = self.fisher.copy() if self.fisher else {}
self.compute_fisher(model, data_loader)
# Merge with existing Fisher (weighted average)
patterns_merged = 0
if old_fisher:
for name in self.fisher:
if name in old_fisher:
self.fisher[name] = 0.5 * (self.fisher[name] + old_fisher[name])
patterns_merged += 1
# Compute compression metric (how much the Fisher changed)
compression = 0.0
if old_fisher:
for name in self.fisher:
if name in old_fisher:
diff = (self.fisher[name] - old_fisher[name]).abs().mean()
compression += diff.item()
return {
"patterns_merged": patterns_merged,
"memory_compressed_by": compression,
"stability_score": 1.0 / (1.0 + compression),
}