Skip to content

Commit de5a06d

Browse files
Merge branch 'master' into hananel
2 parents 5955475 + c1412e8 commit de5a06d

11 files changed

Lines changed: 507 additions & 67 deletions

File tree

.travis.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
language: python
2-
dist: xenial
2+
dist: bionic
33
python:
44
- 3.6
55
- 3.7
6+
- 3.8
67
install:
78
- pip install . --progress-bar off
89
script:

bindsnet/encoding/encoders.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,18 @@ def __init__(self, time: int, dt: float = 1.0, **kwargs):
8686

8787

8888
class PoissonEncoder(Encoder):
89-
def __init__(self, time: int, dt: float = 1.0, **kwargs):
89+
def __init__(self, time: int, dt: float = 1.0, approx: bool = False, **kwargs):
9090
# language=rst
9191
"""
9292
Creates a callable PoissonEncoder which encodes as defined in
9393
``bindsnet.encoding.poisson`
9494
9595
:param time: Length of Poisson spike train per input variable.
9696
:param dt: Simulation time step.
97+
:param approx: Bool: use alternate faster, less accurate computation.
98+
9799
"""
98-
super().__init__(time, dt=dt, **kwargs)
100+
super().__init__(time, dt=dt, approx=approx, **kwargs)
99101

100102
self.enc = encodings.poisson
101103

bindsnet/encoding/encodings.py

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ def bernoulli(
9898

9999

100100
def poisson(
101-
datum: torch.Tensor, time: int, dt: float = 1.0, device="cpu", **kwargs
101+
datum: torch.Tensor,
102+
time: int,
103+
dt: float = 1.0,
104+
device="cpu",
105+
approx=False,
106+
**kwargs
102107
) -> torch.Tensor:
103108
# language=rst
104109
"""
@@ -110,6 +115,8 @@ def poisson(
110115
:param datum: Tensor of shape ``[n_1, ..., n_k]``.
111116
:param time: Length of Poisson spike train per input variable.
112117
:param dt: Simulation time step.
118+
:param device: target destination of poisson spikes.
119+
:param approx: Bool: use alternate faster, less accurate computation.
113120
:return: Tensor of shape ``[time, n_1, ..., n_k]`` of Poisson-distributed spikes.
114121
"""
115122
assert (datum >= 0).all(), "Inputs must be non-negative"
@@ -119,28 +126,36 @@ def poisson(
119126
datum = datum.flatten()
120127
time = int(time / dt)
121128

122-
# Compute firing rates in seconds as function of data intensity,
123-
# accounting for simulation time step.
124-
rate = torch.zeros(size, device=device)
125-
rate[datum != 0] = 1 / datum[datum != 0] * (1000 / dt)
126-
127-
# Create Poisson distribution and sample inter-spike intervals
128-
# (incrementing by 1 to avoid zero intervals).
129-
dist = torch.distributions.Poisson(rate=rate)
130-
intervals = dist.sample(sample_shape=torch.Size([time + 1]))
131-
intervals[:, datum != 0] += (intervals[:, datum != 0] == 0).float()
132-
133-
# Calculate spike times by cumulatively summing over time dimension.
134-
times = torch.cumsum(intervals, dim=0).long()
135-
times[times >= time + 1] = 0
136-
137-
# Create tensor of spikes.
138-
spikes = torch.zeros([time + 1, size], device=device, dtype=torch.bool)
139-
spikes[times, torch.arange(size)] = 1
140-
spikes = spikes[1:]
141-
142-
return spikes.view(time, *shape)
129+
if approx:
130+
# random normal power awful approximation
131+
x = torch.randn((time, size), device=device).abs()
132+
x = torch.pow(x, (datum * 0.11 + 5) / 50)
133+
y = torch.tensor(x < 0.6, dtype=torch.bool, device=device)
143134

135+
return y.view(time, *shape).byte()
136+
else:
137+
# Compute firing rates in seconds as function of data intensity,
138+
# accounting for simulation time step.
139+
rate = torch.zeros(size, device=device)
140+
rate[datum != 0] = 1 / datum[datum != 0] * (1000 / dt)
141+
142+
# Create Poisson distribution and sample inter-spike intervals
143+
# (incrementing by 1 to avoid zero intervals).
144+
dist = torch.distributions.Poisson(rate=rate)
145+
intervals = dist.sample(sample_shape=torch.Size([time + 1]))
146+
intervals[:, datum != 0] += (intervals[:, datum != 0] == 0).float()
147+
148+
# Calculate spike times by cumulatively summing over time dimension.
149+
times = torch.cumsum(intervals, dim=0).long()
150+
times[times >= time + 1] = 0
151+
152+
# Create tensor of spikes.
153+
spikes = torch.zeros(time + 1, size, device=device).byte()
154+
spikes[times, torch.arange(size)] = 1
155+
spikes = spikes[1:]
156+
157+
return spikes.view(time, *shape)
158+
144159

145160
def rank_order(
146161
datum: torch.Tensor, time: int, dt: float = 1.0, **kwargs

bindsnet/learning/learning.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ def __init__(
5252
elif isinstance(nu, float) or isinstance(nu, int):
5353
nu = [nu, nu]
5454

55-
self.nu = nu
55+
self.nu = torch.zeros(2, dtype=torch.float)
56+
self.nu[0] = nu[0]
57+
self.nu[1] = nu[1]
5658

5759
# Parameter update reduction across minibatch dimension.
5860
if reduction is None:
@@ -64,7 +66,7 @@ def __init__(
6466
self.reduction = reduction
6567

6668
# Weight decay.
67-
self.weight_decay = weight_decay
69+
self.weight_decay = 1.0 - weight_decay if weight_decay else 1.0
6870

6971
def update(self) -> None:
7072
# language=rst
@@ -73,7 +75,7 @@ def update(self) -> None:
7375
"""
7476
# Implement weight decay.
7577
if self.weight_decay:
76-
self.connection.w -= self.weight_decay * self.connection.w
78+
self.connection.w *= self.weight_decay
7779

7880
# Bound weights.
7981
if (
@@ -177,20 +179,21 @@ def _connection_update(self, **kwargs) -> None:
177179
"""
178180
batch_size = self.source.batch_size
179181

180-
source_s = self.source.s.view(batch_size, -1).unsqueeze(2).float()
181-
source_x = self.source.x.view(batch_size, -1).unsqueeze(2)
182-
target_s = self.target.s.view(batch_size, -1).unsqueeze(1).float()
183-
target_x = self.target.x.view(batch_size, -1).unsqueeze(1)
184-
185182
# Pre-synaptic update.
186183
if self.nu[0]:
187-
update = self.reduction(torch.bmm(source_s, target_x), dim=0)
188-
self.connection.w -= self.nu[0] * update
184+
source_s = self.source.s.view(batch_size, -1).unsqueeze(2).float()
185+
target_x = self.target.x.view(batch_size, -1).unsqueeze(1) * self.nu[0]
186+
self.connection.w -= self.reduction(torch.bmm(source_s, target_x), dim=0)
187+
del source_s, target_x
189188

190189
# Post-synaptic update.
191190
if self.nu[1]:
192-
update = self.reduction(torch.bmm(source_x, target_s), dim=0)
193-
self.connection.w += self.nu[1] * update
191+
target_s = (
192+
self.target.s.view(batch_size, -1).unsqueeze(1).float() * self.nu[1]
193+
)
194+
source_x = self.source.x.view(batch_size, -1).unsqueeze(2)
195+
self.connection.w += self.reduction(torch.bmm(source_x, target_s), dim=0)
196+
del source_x, target_s
194197

195198
super().update()
196199

bindsnet/network/network.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import torch
55

66
from .monitors import AbstractMonitor
7-
from .nodes import Nodes
7+
from .nodes import Nodes, CSRMNodes
88
from .topology import AbstractConnection
99
from ..learning.reward import AbstractReward
1010

@@ -226,12 +226,23 @@ def _get_inputs(self, layers: Iterable = None) -> Dict[str, torch.Tensor]:
226226
target = self.connections[c].target
227227

228228
if not c[1] in inputs:
229-
inputs[c[1]] = torch.zeros(
230-
self.batch_size, *target.shape, device=target.s.device
231-
)
229+
if isinstance(target, CSRMNodes):
230+
inputs[c[1]] = torch.zeros(
231+
self.batch_size,
232+
target.res_window_size,
233+
*target.shape,
234+
device=target.s.device
235+
)
236+
else:
237+
inputs[c[1]] = torch.zeros(
238+
self.batch_size, *target.shape, device=target.s.device
239+
)
232240

233241
# Add to input: source's spikes multiplied by connection weights.
234-
inputs[c[1]] += self.connections[c].compute(source.s)
242+
if isinstance(target, CSRMNodes):
243+
inputs[c[1]] += self.connections[c].compute_window(source.s)
244+
else:
245+
inputs[c[1]] += self.connections[c].compute(source.s)
235246

236247
return inputs
237248

0 commit comments

Comments
 (0)