SpikingJelly笔记之泊松编码

  • Published2025-11-23 17:40:22

文章目录

前言一、泊松编码的原理二、生成符合泊松分布的脉冲序列三、SpikingJelly中的泊松编码四、Lena图像的泊松编码与还原1.原始图像2.图像编码3.图像还原

总结

前言

记录SpikingJelly中泊松编码的使用方法,对图像数据进行编码与还原

一、泊松编码的原理

基于频率的编码方式,将输入编码为发放次数分布符合泊松过程的脉冲序列

P

(

X

=

k

)

=

λ

k

k

!

e

λ

P(X=k)=\frac{{\lambda}^{k}}{k!}{e}^{-\lambda}

P(X=k)=k!λk​e−λ 均值λ:时间T内发放的脉冲数目 根据输入决定每个时间步发放脉冲的概率[0,1],各时间步相互独立

二、生成符合泊松分布的脉冲序列

out_spike = torch.rand_like(x).le(x).to(x)

(1)生成与输入形状相同的标准正态分布随机值 (2)将生成值与输入[0,1]比较,<=为1,>为0 (3)将比较生成的布尔值转化为与输入相同的数据类型

三、SpikingJelly中的泊松编码

from spikingjelly.activation_based import encoding

pe = encoding.PoissonEncoder() # 泊松编码器

# 输出脉冲序列,T:时间步长,w:图像宽度,h:图像高度

out_spike = torch.zeros((T, w, h), dtype=torch.bool)

# 按时间步根据输入生成脉冲序列,相互独立

for t in range(T):

out_spike[t] = pe(x) # x需要归一化[0,1]

四、Lena图像的泊松编码与还原

1.原始图像

读取、展示原始图像

####################泊松编码####################

from PIL import Image

import numpy as np

import matplotlib.pyplot as plt

import torch

from spikingjelly.activation_based import encoding

from spikingjelly import visualizing

####################读取图像####################

img = np.array(Image.open('../dataset/lena.bmp')) / 255

x = torch.from_numpy(img)

w, h = x.shape

plt.figure()

plt.imshow(x, cmap='gray')

plt.axis('off')

2.图像编码

输出泊松编码后每个时间步的图像

####################泊松编码####################

T = 9 # 时间步长

pe = encoding.PoissonEncoder()

out_spike = torch.zeros((T, w, h), dtype=torch.bool)

for t in range(T):

out_spike[t] = pe(x)

# 每个时间步的编码图像

nrows, ncols, space = 3, 3, 30

figsize, dpi = (6, 4), 200

visualizing.plot_2d_feature_map(x3d=out_spike.float().numpy(),

nrows=nrows,

ncols=ncols,

space=space,

title='PoissonEncoder',

figsize=figsize,

dpi=dpi)

3.图像还原

按时间步累加可重构出原始图像,时间步T越长,累加结果越接近原始图像

####################编码结果累加####################

T = 100 # 时间步长

pe = encoding.PoissonEncoder()

out_spike = torch.zeros((w, h), dtype=torch.float)

out_spikes = torch.zeros((5, w, h), dtype=torch.float)

# 按时间步累加

show_step = 20

for t in range(T):

out_spike += pe(x)

if(t % show_step == 0):

out_spikes[t//show_step] = out_spike

# 归一化

for i in range(T//show_step):

out_spikes[i] = (out_spikes[i]-out_spikes[i].min()) / (out_spikes[i].max()-out_spikes[i].min())

# 按时间步累加的编码图像

nrows, ncols, space = 1, T//show_step, 30

figsize, dpi = (6, 4), 200

visualizing.plot_2d_feature_map(x3d=out_spikes.numpy(),

nrows=nrows,

ncols=ncols,

space=space,

title='PoissonEncoder',

figsize=figsize,

dpi=dpi)

plt.axis('off')

plt.show()

总结

泊松编码将输入转化为脉冲序列,是一种基于频率编码的方式 较大的输入对应于较高的脉冲频率 泊松编码的输入需要归一化[0,1] 使用spikingjelly.visualizing可以方便作图

参考: [1] 时间驱动:编码器 [2]【Spikingjelly】SNN框架教程的代码解读_3