Skip to content

Commit eeb7e27

Browse files
MachukaHananel-Hazan
authored andcommitted
Improve evaluation function with noise for assignments
Switched from '-1' sentinel value for silent neurons to randomly assigned labels. Also added noise for random tie-breaking in neuron assignments.
1 parent 8a5923b commit eeb7e27

1 file changed

Lines changed: 16 additions & 11 deletions

File tree

‎bindsnet/evaluation/evaluation.py‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,36 @@ def assign_labels(
3535

3636
# Sum over time dimension (spike ordering doesn't matter).
3737
spikes = spikes.sum(1)
38-
38+
3939
for i in range(n_labels):
40-
# Create mask (faster and allows future steps to stay on GPU).
41-
mask = (labels == i)
40+
# Create mask.
41+
mask = labels == i
4242
# Count the number of samples with this label.
4343
n_labeled = mask.sum().float()
4444

4545
if n_labeled > 0:
46-
# Get indices of samples with this label (masking is faster and stays on the GPU).
46+
# Get indices of samples with this label.
4747
label_sum = spikes[mask].sum(0)
4848
# Update rates.
4949
rates[:, i] = alpha * rates[:, i] + (label_sum / n_labeled)
5050

51-
# Compute proportions (and use 'torch.where' to avoid NaN bug).
51+
# Compute proportions of spike activity per class.
5252
total_activity = rates.sum(1, keepdim=True)
53-
proportions = torch.where(total_activity > 0, rates / total_activity, torch.zeros_like(rates))
53+
proportions = torch.where(
54+
total_activity > 0, rates / total_activity, torch.zeros_like(rates)
55+
)
56+
57+
# Noise for random tie breaking.
58+
eps = 1e-6 # Small enough not to distort real decisions
59+
noise = eps * torch.randn_like(proportions)
5460

5561
# Neuron assignments are the labels they fire most for.
56-
max_vals, assignments = torch.max(proportions, 1)
57-
58-
# Set unassigned (silent) neurons to -1 instead of defaulting to 0.
59-
assignments[max_vals == 0] = -1
62+
assignments = torch.argmax(proportions + noise, dim=1)
6063

6164
# Neurons that never fired have no class preference; mark them with -1 so
62-
# they don't contribute a (biased) vote for class 0 in downstream schemes.
65+
# they are masked out of downstream voting (issue #736: silent neurons must
66+
# not default to a vote for class 0). Downstream schemes only match
67+
# ``assignments == i`` for i >= 0, so -1 neurons are excluded.
6368
assignments[rates.sum(1) == 0] = -1
6469

6570
return assignments, proportions, rates

0 commit comments

Comments
 (0)