Heidelberg Digits

The Heidelberg Digits example lives in examples/heidelberg_digits/main.py. It uses the Spiking Heidelberg Digits dataset through Tonic and trains SNN, GRU, and S6 models on framed event data.

Setup:

cd examples/heidelberg_digits
pip install -r requirements.txt
python main.py

Dataset

The script converts event streams into frames:

frame_transform = transforms.Compose([
    transforms.ToFrame(sensor_size=sensor_size, time_window=10000)
])

train_dataset = tonic.datasets.SHD(save_to='../data', train=True, transform=frame_transform)

The dataloader uses PadTensors(batch_first=False) so the resulting batch is arranged as a time-major sequence. The training loop then calls the model one timestep at a time.

Model

The SNN model is intentionally direct:

class SHD_SNN(tt.Model):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Flatten(start_dim=1),
            nn.Linear(sensor_size[0], 256),
            tt.snn.LIB(256, beta=torch.rand(256), threshold=torch.rand(256)),
            nn.Linear(256, 256),
            tt.snn.LIB(256, beta=torch.rand(256), threshold=torch.rand(256)),
            nn.Linear(256, num_classes),
        )

    def forward(self, x):
        return self.net(x)

The GRU and S6 models use the same outer training pattern. This is the core traceTorch idea: the layer dynamics can change while the model and loop shape stay familiar.

Training loop

The sequence is processed explicitly:

model.zero_states()

for t in range(seq_len):
    output = model(events[t])

loss = loss_fn(output, label)
loss.backward()
optimizer.step()

Only the final output is used for the loss in this example. Other tasks may accumulate loss over all timesteps or average outputs, as the MNIST rate-coded example does.

Notes

The example is meant to demonstrate event-data integration and traceTorch state management. It is not tuned as an SHD benchmark recipe.