Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,32 @@ To reproduce the data and plots for figure 7 (i.e., the weight scatter plots com
#### Figure 8

A minimal working example for the deep learning experiment is provided by `scripts/symm_net/main_salnet.py` and the corresponding parameter file `exp_setting.yaml`.
As forward training of the convolutional neural networks is implemented in pytorch, we highly recommend to use a GPU.

Usage: `python main_salnet.py -f exp_setting.yaml -s <type_of_experiment> --dataset <dataset> --tags <tag1,tag2>`

- `type_of_experiment`: choose the learning algorithm (equivalent to the section names in `exp_setting.yaml`)
- `dataset`: choose one the following datasets: `cifar10`, `svhn`, `mnist`, `fmnist`
- optionally, you can pass a list of descriptive tags to keep tack of your runs.

The typical execution time of `main_salnet.py` amounts to ca. 15 minutes for the training modes that do not involve a spiking neural network, in SAL-mode ca 30-45 minutes and in RDD-mode ca. 2 hours.

For conveniently reproducing any of the data shown in figure 8, we provide two workflows:
- `sweep.py`: suitable for small scale parameter sweeps. It directly launcher the required sub-processes. Example usage: `python sweep.py --datasets cifar10 --algos bp fa sal`.
See `python sweep.py --help` for all available settings.
- For large scale parameter sweeps (for instance to reproduce the 105 runs for all datasets, algorithms and seeds) on an HPC cluster (with SLURM), we provided the following workflow that needs only minimal adaptation to the available system.
1. Run `sweep_creator.py`: It creates `jobs.sh` which contains all `main_salnet.py`-calls with the relevant settings.
See `python sweep_creator.py --help` for all available settings.
2. Modify `slurm.sh` to specify the relevant settings for your HPC cluster.
3. Run `bash slurm_submit.sh`. It will call `slurm.sh` internally and start a slurm array job.
4. The data can be plotted with `scripts/symm_net/plots.ipynb`
#### Figure 9

A minimal working example for the Time evolution of SAL in the SALNet is provided by `scripts/symm_net/salnet_symm.py`.
A minimal working example for the time evolution of SAL in the SALNet is provided by `scripts/symm_net/salnet_symm.py`.

Example Usage: `python salnet_symm.py --lr 0.01 --n_epochs 200 --len_epoch 500`.

For conveniently reproducing the data shown in figure 9, we provide the same workflows as explained above with the files `sweep_symm.py` for quick small scale scans and `sweep_creator_symm.py` to launch all 20 runs as a slurm array job.

#### Figure 10

Expand Down
1 change: 1 addition & 0 deletions mystyle.mpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# use Latex: (uncomment the following two commands if latex is installed on system)
# text.usetex: true
# font.family: serif
# text.latex.preamble: \usepackage{amssymb}

# text and font and labets etc. settings
# axes.labelsize: 8
Expand Down
2 changes: 2 additions & 0 deletions scripts/symm_net/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
jobs.sh
jobs_[0-9]*_[0-9]*.sh
94 changes: 94 additions & 0 deletions scripts/symm_net/fast_exp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
bp:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: True
use_kp: False
use_fa_conv_layers: False
use_scfa: False

fa:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: False
use_kp: False
use_fa_conv_layers: False
use_scfa: False

bp_w_fa:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: True
use_kp: False
use_fa_conv_layers: True
use_scfa: False

akrout:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.001
use_backprop: False
use_kp: True
use_fa_conv_layers: False
use_scfa: False

scfa:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: False
use_kp: False
use_fa_conv_layers: False
use_scfa: True

sal:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: False
use_kp: False
use_fa_conv_layers: False
use_scfa: False
sal_params:
n_iterations: 5
use_sal: True
t_ref: 10
len_epoch: 200
sal_lr: 0.04
batch_size: 32

rdd:
params:
n_epochs: 1
batch_size: 128
lr: 0.01
momentum: 0.9
weight_decay: 0.0
use_backprop: False
use_kp: False
use_fa_conv_layers: False
use_scfa: False
rdd_params:
rdd_time: 90
use_rdd: True
every_epoch: True
42 changes: 37 additions & 5 deletions scripts/symm_net/load_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import argparse
from typing import Any, Callable

import yaml

Expand Down Expand Up @@ -34,14 +35,22 @@
},
"dataset": "cifar10",
}
ALLOWED_DATASETS = {"cifar10": cifar10, "mnist": mnist, "fmnist": fmnist, "svhn": svhn}
ALLOWED_DATASETS: dict[str, Callable] = {
"cifar10": cifar10,
"mnist": mnist,
"fmnist": fmnist,
"svhn": svhn,
}


def parse_tags(s):
def parse_tags(s: str | None) -> list[str]:
return [tag.strip() for tag in s.split(",")] if s else []


def load_params(param_file, section=None):
def load_params(
param_file: str,
section: str | None = None,
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any], str]:
with open(param_file, "r") as f:
content = yaml.safe_load(f)
if section:
Expand All @@ -61,13 +70,25 @@ def load_params(param_file, section=None):
)


def merge(base, override):
def merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]:
result = base.copy()
result.update(override)
return result


def settings_loader():
def settings_loader() -> tuple[
dict[str, Any],
dict[str, Any],
dict[str, Any],
Callable,
list[str],
list[str],
str | None,
str,
int,
str | None,
str | None,
]:
parser = argparse.ArgumentParser()
parser.add_argument("-f", type=str, help="Path to parameter file.")
parser.add_argument("-s", type=str, help="Section name in YAML file.")
Expand All @@ -79,6 +100,14 @@ def settings_loader():
parser.add_argument(
"--output-dir", type=str, default="../../results/symm_net", dest="output_dir"
)
parser.add_argument("--seed", type=int, default=0, help="Random seed.")
parser.add_argument(
"--run-dir",
type=str,
default=None,
dest="run_dir",
help="Exact output directory; bypasses create_run_dirs() when set.",
)
args = parser.parse_args()

if args.f:
Expand Down Expand Up @@ -119,4 +148,7 @@ def settings_loader():
group_tags_list,
args.f,
args.output_dir,
args.seed,
args.run_dir,
args.s,
)
Loading
Loading