Introduction¶
BehaveNet is a software package that provides tools for analyzing behavioral video and neural activity. Currently BehaveNet supports:
Video compression using convolutional autoencoders
Video segmentation (and generation) using autoregressive hidden Markov models
Neural network decoding of videos from neural activity
Bayesian decoding of videos from neural activity
BehaveNet automatically saves models using a well-defined and flexible directory structure, allowing for easy management of many models and multiple datasets.
The command line interface¶
Users interact with BehaveNet using a command line interface, so all model fitting is done from the terminal. To simplify this process all necessary parameters are defined in four configuration files that can be manually updated using a text editor:
data_config - dataset ids, video frames sizes, etc. You can automatically generate this configuration file for a new dataset by following the instructions in the following section.
model_config - model hyperparameters
training_config - learning rate, number of epochs, etc.
compute_config - gpu vs cpu, gpu ids, etc.
Example configuration files can be found here.
For example, the command line call to fit an autoencoder would be (using the default json files):
$: cd /behavenet/code/directory/
$: cd behavenet
$: python fitting/ae_grid_search.py --data_config ../configs/data_default.json --model_config ../configs/ae_jsons/ae_model.json --training_config ../configs/ae_jsons/ae_training.json --compute_config ../configs/ae_jsons/ae_compute.json
We recommend that you copy the default config files in the behavenet repo into a separate directory on your local machine and make edits there. For more information on the different hyperparameters, see the hyperparameters glossary.
Adding a new dataset¶
When using BehaveNet with a new dataset you will need to make a new data config json file, which can be automatically generated using a BehaveNet helper function. You will be asked to enter the following information (examples shown for Musall dataset):
lab or experimenter name (
musall
)experiment name (
vistrained
)example animal name (
mSM36
)example session name (
05-Dec-2017
)input channels (
2
) - this can refer to color channels (for RGB data) and/or number of camera views, which should be concatenated along the color channel dimension. In the Musall dataset we use grayscale images from two camera views, so a trial with 189 frames will have a block of video data of shape (189, 2, 128, 128)y pixels (
128
)x pixels (
128
)use output mask (
False
) - an optional output mask can be applied to each video frame if desired; these output masks must also be stored in thedata.hdf5
files asmasks
.frame rate (
30
) - in Hz; BehaveNet assumes that the video data and neural data are binned at the same temporal resolutionneural data type (
ca
) - eitherca
for 2-photon/widefield data, orspikes
for ephys data. This parameter controls the noise distribution for encoding models, as well as several other model hyperparameters.
To enter this information, launch python from the behavenet environment and type:
from behavenet import add_dataset
add_dataset()
This function will create a json file named [lab_id]_[expt_id].json
in the .behavenet
directory in your user home directory, which you can manually update at any point using a text
editor.
Organizing model fits with test-tube¶
BehaveNet uses the test-tube package to organize model fits into user-defined experiments, log meta and training data, and perform grid searches over model hyperparameters. Most of this occurs behind the scenes, but there are a couple of important pieces of information that will improve your model fitting experience.
BehaveNet organizes model fits using a combination of hyperparameters and user-defined experiment
names. For example, let’s say you want to fit 5 different convolutional autoencoder architectures,
all with 12 latents, to find the best one. Let’s call this experiment “arch_search”, which you will
set in the model_config
json in the experiment_name
field. The results will then be stored
in the directory
results_dir/lab_id/expt_id/animal_id/session_id/ae/conv/12_latents/arch_search/
.
Each model will automatically be assigned it’s own “version” by test-tube, so the arch_search
directory will have subdirectories version_0
, …, version_4
. If an additional CAE model is
later fit with 12 latents (and using the “arch_search” experiment name), test-tube will add it to
the arch_search
directory as version_5
. Different versions may have different
architectures, learning rates, regularization values, etc. Each model class (autoencoder, arhmm,
decoders) has a set of hyperparameters that are used for directory names, and another set that are
used to distinguish test-tube versions within the user-defined experiment.
Within the version_x
directory, there are various files saved during training. Here are some of
the files automatically output when training an autoencoder:
best_val_model.pt: the best model (not necessarily from the final training epoch) as determined by computing the loss on validation data
meta_tags.csv: hyperparameters associated with data, computational resources, training, and model
metrics.csv: metrics computed on dataset as a function of epochs; the default is that metrics are computed on training and validation data every epoch (and reported as a mean over all batches) while metrics are computed on test data only at the end of training using the best model (and reported per batch).
session_info.csv: experimental sessions used to fit the model
Additionally, if you set export_latents
to True
in the training config file, you will see
[lab_id]_[expt_id]_[animal_id]_[session_id]_latents.pkl: list of np.ndarrays of CAE latents computed using the best model
and if you set export_train_plots
to True
in the training config file, you will see
loss_training.png: plot of MSE as a function of training epoch on training data
loss_validation.png: same as above using validation data
Grid searching with test-tube¶
Beyond organizing model fits, test-tube is also useful for performing grid searches over model hyperparameters, using multiple cpus or gpus. All you as the user need to do is enter the relevant hyperparameter choices as a list instead of a single value in the associated configuration file.
Again using the autoencoder as an example, let’s say you want to fit a single AE architecture using 4 different numbers of latents, all with the same regularization value. In the model config file, you will set these values as:
{
...
"n_ae_latents": [4, 8, 12, 16],
"l2_reg": 0.0,
...
}
To specify the computing resources for this job, you will next edit the compute config file, which looks like this:
{
...
"device": "cuda", # "cpu" or "cuda"
"gpus_viz": "0", # "add multiple gpus as e.g. "0;1;4"
"tt_n_gpu_trials": 1000,
"tt_n_cpu_trials": 1000,
"tt_n_cpu_workers": 5,
...
}
With the device
field set to cuda
, test-tube will use gpus to run this job. The
gpus_viz
field can further specify which subset of gpus to use. The tt_n_gpu_trials
defines
the maximum number of jobs to run. If this number is larger than the total number of hyperparameter
configurations, all configurations are fit; if this number is smaller than the total number (say if
"tt_n_gpu_trials": 2
in this example) then this number of configurations is randomly sampled
from all possible choices.
To fit models using the cpu instead, set the device
field to cpu
; then tt_n_cpu_workers
defines the total number of cpus to run the job (total number of models fitting at any one time)
and tt_n_cpu_trials
is analogous to tt_n_gpu_trials
.
Finally, multiple hyperparameters can be searched over simultaneously; for example, to search over both AE latents and regularization values, set these parameters in the model config file like so:
{
...
"n_ae_latents": [4, 8, 12, 16],
"l2_reg": [1e-5, 1e-4, 1e-3],
...
}
This job would then fit a total of 4 latent values x 3 regularization values = 12 models.