spikingjelly.timing_based.encoding 源代码

import torch

__all__ = ["GaussianTuning"]


[文档] class GaussianTuning: def __init__( self, n: int, m: int, x_min: torch.Tensor, x_max: torch.Tensor, ) -> None: r""" **API Language** - :ref:`中文 <GaussianTuning.__init__-cn>` | :ref:`English <GaussianTuning.__init__-en>` ---- .. _GaussianTuning.__init__-cn: * **中文** 使用高斯感受野将连续值编码为脉冲时间。每个输入维度由 ``m`` 个神经元 编码,公开属性 ``mu`` 和 ``sigma2`` 分别保存感受野中心和方差。 :param n: 输入特征维度数量 :type n: int :param m: 每个特征使用的神经元数量,必须大于 2 :type m: int :param x_min: 各输入特征的最小值,形状为 ``[n]`` :type x_min: torch.Tensor :param x_max: 各输入特征的最大值,形状为 ``[n]`` :type x_max: torch.Tensor :raises ValueError: ``n`` 或 ``m`` 非法、输入范围形状不匹配,或任一 ``x_min`` 不小于对应的 ``x_max`` ---- .. _GaussianTuning.__init__-en: * **English** Encode continuous values as spike times with Gaussian receptive fields. Each input dimension uses ``m`` neurons. Public attributes ``mu`` and ``sigma2`` contain the receptive-field centers and variances. :param n: Number of input feature dimensions :type n: int :param m: Number of neurons per feature; must be greater than 2 :type m: int :param x_min: Per-feature minimum values with shape ``[n]`` :type x_min: torch.Tensor :param x_max: Per-feature maximum values with shape ``[n]`` :type x_max: torch.Tensor :raises ValueError: If ``n`` or ``m`` is invalid, the range tensors have incompatible shapes, or any minimum is not smaller than its maximum """ if n <= 0: raise ValueError("n must be a positive integer.") if m <= 2: raise ValueError("m must be greater than 2.") if x_min.shape != (n,) or x_max.shape != (n,): raise ValueError( f"x_min and x_max must both have shape ({n},), " f"but got {x_min.shape} and {x_max.shape}." ) if not torch.all(x_min < x_max): raise ValueError("All elements of x_min must be less than x_max.") self.n = n self.m = m indices = torch.arange( 1, m + 1, device=x_min.device, dtype=torch.float32 ).unsqueeze(0) input_range = (x_max - x_min).unsqueeze(-1) self.mu = x_min.unsqueeze(-1) + (2 * indices - 3) * input_range / (2 * (m - 2)) self.sigma2 = (input_range / (1.5 * (m - 2))).square().repeat(1, m)
[文档] def encode( self, x: torch.Tensor, max_spike_time: int = 50, ) -> torch.Tensor: r""" **API Language** - :ref:`中文 <GaussianTuning.encode-cn>` | :ref:`English <GaussianTuning.encode-en>` ---- .. _GaussianTuning.encode-cn: * **中文** :param x: 输入张量,形状为 ``[batch_size, n, samples_count]`` :type x: torch.Tensor :param max_spike_time: 非负编码时间窗长度;达到该值的神经元以 ``-1`` 表示不发放。 当其为 ``0`` 时,所有神经元均不发放 :type max_spike_time: int :return: 形状为 ``[batch_size, n, samples_count, m]`` 的脉冲时间 :rtype: torch.Tensor :raises AssertionError: 输入不是三维张量或特征维不等于 ``n`` :raises ValueError: ``max_spike_time`` 为负数 ---- .. _GaussianTuning.encode-en: * **English** :param x: Input tensor with shape ``[batch_size, n, samples_count]`` :type x: torch.Tensor :param max_spike_time: Non-negative encoding-window length; neurons reaching it are marked inactive with ``-1``. When it is ``0``, all neurons are inactive :type max_spike_time: int :return: Spike times with shape ``[batch_size, n, samples_count, m]`` :rtype: torch.Tensor :raises AssertionError: If the input is not three-dimensional or its feature dimension differs from ``n`` :raises ValueError: If ``max_spike_time`` is negative """ if max_spike_time < 0: raise ValueError("max_spike_time must be non-negative.") if x.dim() != 3 or x.shape[1] != self.n: raise AssertionError( f"x must have shape [batch_size, {self.n}, samples_count], " f"but got {tuple(x.shape)}." ) batch_size, _, samples_count = x.shape values = x.permute(0, 2, 1).reshape(-1, self.n, 1).expand(-1, -1, self.m) responses = torch.exp(-(values - self.mu).square() / (2 * self.sigma2)) spike_times = (max_spike_time * (1 - responses)).round() spike_times[spike_times >= max_spike_time] = -1 return spike_times.view(batch_size, samples_count, self.n, self.m).permute( 0, 2, 1, 3 )