| name | event2vec-neuromorphic-representation |
| description | Event2Vec: Processing neuromorphic events directly via vector representations for efficient event camera data processing compatible with Transformer architectures. Activation triggers: event camera, neuromorphic vision, event2vec, DVS, asynchronous events, sparse events, event-based vision. |
Event2Vec: Processing Neuromorphic Events Directly by Representations in Vector Space
Novel representation enabling direct processing of asynchronous, sparse neuromorphic event data in vector space, fully compatible with Transformer architectures while maintaining event camera advantages of temporal resolution, power efficiency, and dynamic range.
Metadata
- Source: arXiv:2504.15371 [cs.CV]
- Authors: Wei Fang, Priyadarshini Panda
- Published: 2025-04-21 (v5: 2026-02-05)
- Categories: cs.CV (Computer Vision), cs.NE (Neural and Evolutionary Computing)
- Code: Available at https URL
Core Methodology
Key Innovation
Neuromorphic event cameras produce asynchronous, sparse event streams that are incompatible with standard deep learning pipelines. Event2Vec addresses this by:
- Word-to-Event Analogy: Drawing inspiration from word embeddings (Word2Vec)
- Vector Representation: Direct encoding of events in continuous vector space
- Transformer Compatibility: Seamless integration with standard Transformer architectures
- Preserved Sparsity: Maintains event advantages without conversion to dense frames
Technical Framework
1. Event Representation
Event cameras output asynchronous events:
$$e = (x, y, t, p)$$
Where:
- $(x, y)$: Pixel location
- $t$: Timestamp
- $p$: Polarity (+1 for ON event, -1 for OFF event)
2. Event2Vec Embedding
Inspired by Word2Vec, events are mapped to a vector space:
- Event Embeddings: Each event type encoded as vector
- Positional Embeddings: Spatial and temporal location information
- Contextual Embeddings: Event relationships via attention
3. Event Stream Encoding
Raw Events → Event2Vec Embedding → Transformer → Task Output
↓ ↓ ↓ ↓
Sparse Continuous Vectors Attention Classification/
Asynchronous Maintains Processing Regression
4. Key Advantages
- Parameter Efficiency: Dramatically fewer parameters than frame-based
- High Throughput: Parallel processing of sparse events
- Low Latency: Direct event processing, no accumulation window
- Scalability: Effective at ultra-low spatial resolutions
Implementation Guide
Prerequisites
- Python 3.8+
- PyTorch 2.0+
- Event data library (e.g., tonic, Tonic)
- NumPy, Matplotlib
- Optional: CUDA for GPU acceleration
Step-by-Step Implementation
import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import List, Tuple, Optional
import numpy as np
class Event2Vec(nn.Module):
"""
Event2Vec: Direct event representation in vector space
"""
def __init__(
self,
embedding_dim: int = 128,
num_polarities: int = 2,
spatial_bins: Tuple[int, int] = (128, 128),
temporal_resolution: float = 1e-3,
max_time_window: float = 0.1,
use_positional_encoding: bool = True,
num_heads: int = 8,
num_layers: int = 6,
dropout: float = 0.1
):
super().__init__()
self.embedding_dim = embedding_dim
self.num_polarities = num_polarities
self.spatial_bins = spatial_bins
self.temporal_resolution = temporal_resolution
.max_time_window = max_time_window
.polarity_embedding = nn.Embedding(num_polarities, embedding_dim)
.spatial_embedding = nn.Parameter(
torch.randn(spatial_bins[], spatial_bins[], embedding_dim // )
)
use_positional_encoding:
.temporal_embedding = SinusoidalPositionalEncoding(
embedding_dim // ,
max_len=(max_time_window / temporal_resolution)
)
:
.temporal_embedding = nn.Embedding(
(max_time_window / temporal_resolution),
embedding_dim //
)
.event_proj = nn.Linear(embedding_dim * , embedding_dim)
encoder_layer = nn.TransformerEncoderLayer(
d_model=embedding_dim,
nhead=num_heads,
dim_feedforward=embedding_dim * ,
dropout=dropout,
batch_first=
)
.transformer = nn.TransformerEncoder(encoder_layer, num_layers)
.output_head = nn.Identity()
() -> torch.Tensor:
spatial_size :
spatial_size = .spatial_bins
x, y, t, p = events[:, ], events[:, ], events[:, ], events[:, ]
x_idx = (x * .spatial_bins[] / spatial_size[]).long().clamp(, .spatial_bins[] - )
y_idx = (y * .spatial_bins[] / spatial_size[]).long().clamp(, .spatial_bins[] - )
p_idx = ((p + ) / ).long()
t_idx = (t / .temporal_resolution).long().clamp(
, (.max_time_window / .temporal_resolution) -
)
polarity_emb = .polarity_embedding(p_idx)
spatial_emb = .spatial_embedding[y_idx, x_idx]
(.temporal_embedding, ):
temporal_emb = .temporal_embedding(t_idx)
:
temporal_emb = .temporal_embedding(t_idx)
spatiotemporal_emb = torch.cat([spatial_emb, temporal_emb], dim=-)
combined = torch.cat([polarity_emb, spatiotemporal_emb], dim=-)
embeddings = .event_proj(combined)
embeddings
() -> torch.Tensor:
event_embeddings = .encode_events(events, spatial_size)
embeddings = event_embeddings.unsqueeze()
encoded = .transformer(embeddings)
output = .output_head(encoded)
output
(nn.Module):
():
().__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(, max_len, dtype=torch.).unsqueeze()
div_term = torch.exp(
torch.arange(, d_model, ).() *
(-np.log() / d_model)
)
pe[:, ::] = torch.sin(position * div_term)
pe[:, ::] = torch.cos(position * div_term)
.register_buffer(, pe)
() -> torch.Tensor:
.pe[positions]
(nn.Module):
():
().__init__()
.event2vec = Event2Vec(
embedding_dim=embedding_dim,
**event2vec_kwargs
)
.classifier = nn.Sequential(
nn.LayerNorm(embedding_dim),
nn.Linear(embedding_dim, embedding_dim // ),
nn.GELU(),
nn.Dropout(),
nn.Linear(embedding_dim // , num_classes)
)
() -> torch.Tensor:
encoded = .event2vec(events, spatial_size)
pooled = encoded.mean(dim=)
logits = .classifier(pooled.squeeze())
logits
Handling Event Streams Efficiently
def preprocess_event_stream(
events: np.ndarray,
time_window: float = 0.1,
spatial_crop: Optional[Tuple[int, int, int, int]] = None
) -> torch.Tensor:
"""
Preprocess raw event stream for Event2Vec
Args:
events: [N, 4] raw events (x, y, t, p)
time_window: Time window for processing
spatial_crop: (x_min, x_max, y_min, y_max) crop region
Returns:
processed: [M, 4] processed events
"""
t_start = events[:, 2].min()
mask = (events[:, 2] - t_start) < time_window
events = events[mask]
if spatial_crop:
x_min, x_max, y_min, y_max = spatial_crop
mask = (
(events[:, 0] >= x_min) & (events[:, 0] < x_max) &
(events[:, 1] >= y_min) & (events[:, 1] < y_max)
)
events = events[mask]
events[:, 0] -= x_min
events[:, 1] -= y_min
events[:, 2] -= events[:, 2].min()
return torch.from_numpy(events).float()
class EventBatcher:
"""
Batch sparse events for efficient processing
"""
def __init__(self, max_events_per_sample: int = ):
.max_events = max_events_per_sample
() -> [torch.Tensor, torch.Tensor]:
batched = []
batch_indices = []
batch_idx, events (event_list):
(events) > .max_events:
events = events[:.max_events]
batched.append(events)
batch_indices.extend([batch_idx] * (events))
batched_events = torch.cat(batched, dim=)
batch_indices = torch.tensor(batch_indices, dtype=torch.long)
batched_events, batch_indices
Training on Event Datasets
import tonic
import tonic.transforms as transforms
from torch.utils.data import DataLoader
def get_dvs_gesture_loader(
batch_size: int = 32,
data_path: str = './data'
):
"""
Create DataLoader for DVS Gesture dataset
"""
transform = transforms.Compose([
transforms.ToTensor(),
transforms.DropEvent(p=0.1),
])
train_dataset = tonic.datasets.DVSGesture(
save_to=data_path,
train=True,
transform=transform
)
test_dataset = tonic.datasets.DVSGesture(
save_to=data_path,
train=False,
transform=transforms.ToTensor()
)
def collate_fn(batch):
events_list = [item[0] for item in batch]
labels = torch.tensor([item[1] for item in batch])
batcher = EventBatcher()
batched_events, batch_indices = batcher.collate_events(events_list)
return batched_events, batch_indices, labels
train_loader = DataLoader(
train_dataset,
batch_size=batch_size,
shuffle=True,
collate_fn=collate_fn,
num_workers=4
)
return train_loader, test_dataset
def train_event2vec(
model: Event2VecClassifier,
train_loader: DataLoader,
num_epochs: int = ,
device: =
):
model = model.to(device)
optimizer = torch.optim.AdamW(model.parameters(), lr=)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, num_epochs)
criterion = nn.CrossEntropyLoss()
epoch (num_epochs):
model.train()
total_loss =
correct =
total =
batched_events, batch_indices, labels train_loader:
batched_events = batched_events.to(device)
labels = labels.to(device)
optimizer.zero_grad()
logits_list = []
i ((labels)):
mask = batch_indices == i
sample_events = batched_events[mask]
logits = model(sample_events)
logits_list.append(logits)
logits = torch.stack(logits_list)
loss = criterion(logits, labels)
loss.backward()
optimizer.step()
total_loss += loss.item()
correct += (logits.argmax(dim=) == labels).().item()
total += (labels)
scheduler.step()
acc = * correct / total
()
Applications
1. Gesture Recognition
- DVS Gesture: 11-class hand gesture dataset
- ASL-DVS: American Sign Language alphabet
- DVS Lip: Lip reading from events
- Advantages: Low latency, motion blur immunity
2. Autonomous Navigation
- Obstacle Detection: Fast response to motion
- High Dynamic Range: Works in extreme lighting
- Low Power: Suitable for drones, robots
- Event Cameras: DAVIS, ATIS, Prophesee
3. Surveillance
- Motion Detection: Event-triggered recording
- Privacy-Preserving: No full-frame capture
- 24/7 Operation: Low power always-on
- Anomaly Detection: Sparse event analysis
4. Robotics
- SLAM: Event-based simultaneous localization
- Visual Servoing: High-speed tracking
- Collision Avoidance: Sub-millisecond latency
- Industrial Inspection: High-speed quality control
Pitfalls
-
Spatial Quantization: Grid-based encoding loses sub-pixel precision
- Mitigation: Learned continuous spatial embeddings, attention mechanisms
-
Temporal Alignment: Events from different sources may need synchronization
- Mitigation: Temporal normalization, learned time warping
-
Variable Event Count: Different samples have different numbers of events
- Mitigation: Set-based processing, attention pooling, truncation
-
Static Scenes: No events in static regions
- Mitigation: Periodic frame integration, hybrid approaches
-
Dataset Specificity: Hyperparameters tuned per dataset
- Mitigation: Meta-learning, domain adaptation
Related Skills
- snn-event-processing: Spiking neural networks for events
- neuromorphic-vision: General neuromorphic vision methods
- event-camera-denoising: Noise removal from event streams
- sparse-transformer: Efficient attention for sparse data
References
@article{fang2025event2vec,
title={Event2Vec: Processing Neuromorphic Events Directly by Representations in Vector Space},
author={Fang, Wei and Panda, Priyadarshini},
journal={arXiv preprint arXiv:2504.15371},
year={2025}
}
Further Reading
- Event Cameras: Gallego et al., "Event-based Vision: A Survey"
- Word2Vec: Mikolov et al., "Efficient Estimation of Word Representations"
- Transformer: Vaswani et al., "Attention is All You Need"
- Neuromorphic Vision: Davies et al., "Advancing Neuromorphic Computing"