SNN 输入编码过程理解

SNN 输入编码解析

以Bindset中的examples/eth_mnist.py为例

SNN的输入是时间脉冲,如何把mnist图片数据转换为脉冲序列呢?

首先mnist数据中,每张图片的像素为28×28,实际表示为28×28的矩阵,矩阵中每个元素是0-255之间的整数。

SNN需要输入一个脉冲序列,大体的输入格式是 长度为采样次数,每个元素为0/1,代表激活与否。

其中一种常见的序列编码为泊松编码

泊松分布

描述具有固定频率的事件,在某段时间内发生的概率。

那每个像素的灰度值,代表了颜色的深浅程度。灰度值越大,该像素与背景色之间的差距越大。

换个角度理解,灰度值越大,我们眼睛越容易注意到这个像素,也就越容易激活神经元。

用灰度值/255来比作看到这个像素,然后被神经元注意到的概率。

这样的话我们就有了一个固定的频率,接下来根据泊松分布,即可得到在指定的时间段内,脉冲产生的概率分布,根据这个分布产生脉冲序列即可。

具体代码和注释如下:

def poisson(
    datum: torch.Tensor, time: int, dt: float = 1.0, device="cpu", **kwargs
) -> torch.Tensor:
    #datum 是输入的像素矩阵
    #time是观测时间
    #dt是采样频率
    assert (datum >= 0).all(), "Inputs must be non-negative"#SNN不能处理负值
    # Get shape and size of data.
    shape, size = datum.shape, datum.numel()
    datum = datum.flatten()
    time = int(time / dt)#time/dt也就是脉冲序列的长度

    # Compute firing rates in seconds as function of data intensity,
    # accounting for simulation time step.
    # 计算每个像素点产生脉冲的概率
    rate = torch.zeros(size, device=device)
    rate[datum != 0] = 1 / datum[datum != 0] * (1000 / dt)

    # Create Poisson distribution and sample inter-spike intervals
    # (incrementing by 1 to avoid zero intervals).
    #根据概率产生脉冲序列
    dist = torch.distributions.Poisson(rate=rate)
    intervals = dist.sample(sample_shape=torch.Size([time + 1]))
    # 像素不等于0的地方至少有一个脉冲
    intervals[:, datum != 0] += (intervals[:, datum != 0] == 0).float()

    # Calculate spike times by cumulatively summing over time dimension.
    times = torch.cumsum(intervals, dim=0).long()
    # 最多产生time次脉冲
    times[times >= time + 1] = 0

    # Create tensor of spikes.
    spikes = torch.zeros(time + 1, size, device=device).byte()
    spikes[times, torch.arange(size)] = 1
    spikes = spikes[1:]

    return spikes.view(time, *shape)

你可能感兴趣的:(神经网络)