Structure learning for sparse graphs with latent variables
Matlab M
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
optimize_discrete1D First commit Nov 28, 2016
optimize_structure First commit Nov 28, 2016
run_larger_set.m First commit Nov 28, 2016
run_small_set.m First commit Nov 28, 2016

Structural sparsity


The input data is a matrix of objects and features. The structural sparsity model learns a sparse graph to organize the set of objects. The algorithm searches for a graph that explains the features while favoring sparse graph structures. Each graph defines a Gaussian Markov Random Fields with latent variables.

Please cite the following paper:
Lake, B. M., Lawrence, N. D., and Tenenbaum, J. B. (2016). The emergence of organizing structure in conceptual representation. Preprint available on arXiv:1611.09384.


Before running the code, you must install the following:

The Lightspeed toolbox from Tom Minka.

PQN optimization algorithm from Mark Schmidt, introduced in this paper:
M. Schmidt, E. van den Berg, M. Friedlander, and K. Murphy (2009). "Optimizing Costly Functions with Simple Constraints: A Limited-Memory Projected Quasi-Newton Algorithm." AISTATS.

Graphviz if you you want to visualize the learned graphs.

Also, we recommend using a machine with 4 or more cores. As implemented, the search algorithm evaluates moves in parallel.


Setting your path The main folders for PQN, lightspeed, and structural sparsity should all be added (along with their subfolders) to your path. For instance, to add the folder "structural_sparsity" please type:

cd structural_sparsity


To run a small set of test experiments, enter this directory and then type:


To run some of the datasets used in the paper:


If GraphViz is installed, these scripts will visualize the progress of the algorithm, as well as the best graph found at the end. Note that at some points, the algorithm may appear to be changing the graph for the worse. This is because it can make up to 5 "bad" moves before terminating, which helps to avoid local optima. At the end, the best structure scored is the one returned.

Please note that these scripts will not necessarily find the exact same graphs as reported in the paper. The algorithm is stochastic, and the default is to run each dataset once. It was run 10 times for the experiments in the paper, and the highest scoring run was chosen.

Further examining the results

The results of each run are saved in directories such as: OUT_BETAX, where X is replaced by whatever the beta (sparsity) parameter was. After loading a results file, the best structure found is saved as the variable M.

To convert M to an adjacency graph, type:

R  = make_adj(M);

The structure R now contains the adjacency matrix. The variable is a structure with the fields...

  • R.W: [n x n scalar] weight matrix for all nodes in the graph (denoted as S in the paper)
  • R.W_allowed [n x n logical] binary matrix for active connections (non-zero elements of W)
  • R.isclust = [n x 1 logical] which nodes are latent clusters?
  • R.sigma = [scalar] variance parameter

The graph can be visualized by typing:


See the file "viz_graphs/displayS.m" for the different visualization styles.


Mac OS X: If GraphViz (specifically, the neato program) is installed, but it cannot be found by Matlab, try opening Matlab through the terminal rather than through a shortcut.

If you receive an error message about the wrong number of input or output variables for a function, make sure the structural_sparsity folder is at the top of your path. This is likely a naming conflict with something else in your path.


This program incorporates some code written by others.
I would like to acknowledge:

  • function "colorspy" from Alexandre d'Aspremont
  • function "checkgrad" from Charles Kemp
  • graphviz interface files by Leon Peshkin