What I Learned... about data to spike encoding: Rate Encoding Part 1

What I learned from reading through the SNN Torch Tutorial 1: Spike Encoding is summarized in the Notes Infographic Flipbook above.

In Spiking Neural Networks (SNNs), input data is not represented as real number values—as is typically the case with digital sensors and classical Artificial Neural Networks (ANNs)—but rather in a form that resembles biological spike trains (i.e., sequences of neural activation events). The advantage of encoding and transmitting information as spike trains is that it mimics Biological Neural Networks (BNNs), which enable real-time, event-driven processing that is both energy- and computation-efficient. These are essential properties for high-functioning agentic AI systems running on battery-powered personal devices without relying on cloud-based processing.

Real-time event-driven processing means exactly what it sounds like: SNNs can adapt to new information as it occurs. This is one major reason I’m interested in SNNs and Neuromorphic Computing.

The SNN Torch Tutorial 1 covers how to convert static input data (such as an image) into a spike train sequence suitable for feeding into an SNN. I will break this tutorial into three parts, each focusing on one of the most common data-to-spike encoding methods:

Part 1 — Data to spike frequency encoding by Rate-Based (Poisson) Encoding
Part 2 — Data to spike temporal encoding by Time-to-First Spike Encoding
Part 3 — Data to spike population encoding by Delta Modulation

We begin with static data in the form of black-and-white images [math]\mathbb{X} [/math] of handwritten digits from the MNIST dataset, which contains a total of 70,000 images. Each image is represented as a 2D matrix (a rank-2 tensor) of pixel intensity values. 

During preprocessing, image properties are normalized (e.g., pixel values mapped to the range [0, 1]), image dimensions are standardized, and the images are converted from Python Imaging Library (PIL) image objects to PyTorch Tensor objects, where a Tensor is generally a multidimensional array of values represented in multi-dimensional matrices (covered on slide 4 in the notes). For this tutorial, only a small subset of the full dataset is used, and it is further divided into batches [math]\mathbf{B}[/math] of batch size [math]b[/math] (ref slide 2).

Once the data is properly formatted and compatible with the neuron model (to be discussed in later tutorials), it is encoded into a Spike Train Sequence Tensor, [math]S [/math].

Rate-Based (Poisson) Encoding

One approach to convert static image data into spike trains is Rate-Based Encoding. In this method, the normalized input sample values [math]\mathbb{X}{i,j}[/math] (i.e., pixel intensities) are interpreted as rate-coded values [math]R{i,j}[/math], which define a spike firing rate [math]\mathcal{R}_{i,j}[/math] for each pixel.

These rate-coded values are then used to generate a spike sequence [math]\sum_{\eta, i, j}[/math] via a Poisson process, which models the timing distribution of biological spike trains. However, because it is computationally more efficient to sample from a discrete distribution rather than a continuous one, the Poisson process is approximated by a Bernoulli process.

In the Bernoulli approximation, we perform [math]\eta[/math] iterations (i.e., time steps) of Bernoulli trials, denoted [math]\mathcal{B}(1, p)[/math], where [math]p = R_{i,j}[/math] is the spike probability. In each trial, a random value [math]U_{i,j} \sim \mathcal{U}(0, 1)[/math] is drawn from a uniform distribution. A spike is generated at time step [math]t[/math] if [math]U_{i,j} > R_{i,j}[/math]. This trial is conducted independently and simultaneously for every [math]R_{i,j}[/math] in the rate-coded sample [math]\mathbf{R}[/math] (ref slide 6).

After [math]\eta[/math] iterations, the original image tensor [math]\mathbb{X}[/math] of shape [math](H, W)[/math] becomes a spike sequence tensor [math]S[/math] of shape [math](\eta, H, W)[/math] (slide 7)

At this point, each spike sequence [math]S=\{ S_{t,i,j} \}_{t=1}^{\eta}[/math] encodes the original input values [math]\mathbf{X}_{i,j}[/math] (i.e., pixel intensities) as the average spike rate over [math]\eta[/math] time steps, known as the firing rate [math]\mathcal{R}_{i,j}[/math]. As the number of time steps [math](t)[/math] increases, the observed spike rate converges to the true input value ([math]\eta[/math] on order of 100-1000) (ref slide 6). As such rate-encoding can potentially off-setting some of the energy and computation advantages of using SNN. 

The details of the algorithmic steps for the Bernoulli approximation of the Poisson processes are explained in slide 7 and 8). Fortunately, with snnTorch API the entire process of converting a PyTorch image tensor into a spike sequence is handled by a single function calledspikegen.rate(),part of the snnTorch.spikegen module. This function takes a static data tensor as input and outputs a rate-based spike sequence tensor. It is useful to visualize the tensor objects, two example methods are shown:

  1. Raster Plots
        raster plots show a static representation of all neuron activity at each time step, individually in groups or          all at once.
  2. Animation 
        animations are generated by looping through each time step and rendering the neural activity  

 

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *