Skip to main content

Gaussian Graphical Models with StARS, EBIC, and Nonparanormal methods

Project description

PyGGM: Gaussian Graphical Models in Python

Python 3.9+ License: MIT

A Python package for Gaussian Graphical Models with multiple regularization selection methods and nonparanormal transformations.

Features

  • Multiple Regularization Selection Methods:

    • StARS (Stability Approach to Regularization Selection)
    • EBIC (Extended Bayesian Information Criterion)
    • Cross-Validation
  • Nonparanormal Methods:

    • Gaussian copula transformation
    • Rank-based correlations (Spearman/Kendall) with sine transformation
  • Robust Utilities:

    • PSD projection for numerical stability
    • Comprehensive input validation
  • Visualization Tools:

    • Network graphs with customizable layouts
    • Precision matrix heatmaps
    • Diagnostic plots for model selection
  • Performance:

    • Parallelization support via joblib
    • Scikit-learn compatible API

Installation

From source

git clone https://github.com/naandip/pyggm.git
cd pyggm
pip install -e .

Development installation

pip install -e ".[dev]"

Quick Start

import numpy as np
from pyggm import GaussianGraphicalModel
from pyggm.visualization import plot_network, plot_stars_path

# Generate or load data
np.random.seed(42)
X = np.random.randn(200, 50)

# Fit model with StARS selection
model = GaussianGraphicalModel(
    method='stars',
    correlation='pearson',
    n_subsamples=50,
    n_jobs=-1  # Use all cores
)
model.fit(X)

# Results
print(f"Selected alpha: {model.alpha_:.4f}")
print(f"Number of edges: {model.n_edges_}")

# Visualize
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
plot_network(model.precision_, ax=axes[0])
plot_stars_path(model, ax=axes[1])
plt.show()

Usage Examples

1. Basic Usage with Different Methods

StARS (Recommended for sparse graphs)

from pyggm import GaussianGraphicalModel

model = GaussianGraphicalModel(
    method='stars',
    beta=0.05,           # Instability threshold
    n_subsamples=50,     # Number of subsamples
    n_jobs=-1            # Parallel processing
)
model.fit(X)

EBIC (Good for model selection)

model = GaussianGraphicalModel(
    method='ebic',
    gamma=0.5            # Sparsity penalty (0 = BIC, 0.5 = recommended)
)
model.fit(X)

Cross-Validation

model = GaussianGraphicalModel(
    method='cv',
    cv=5,                # Number of folds
    n_jobs=-1
)
model.fit(X)

2. Nonparanormal Transformation

For non-Gaussian data, use the nonparanormal transformer:

from pyggm import NonparanormalTransformer, GaussianGraphicalModel

# Transform data to approximately Gaussian
transformer = NonparanormalTransformer()
X_transformed = transformer.fit_transform(X)

# Fit graphical model
model = GaussianGraphicalModel(method='stars')
model.fit(X_transformed)

3. Rank-Based Correlations

Use rank correlations for robustness to outliers:

# Spearman correlation
model = GaussianGraphicalModel(
    method='stars',
    correlation='spearman'  # or 'kendall'
)
model.fit(X)

4. Fixed Regularization Parameter

If you already know the regularization parameter:

model = GaussianGraphicalModel(alpha=0.1)
model.fit(X)

5. Model Evaluation

# Compute log-likelihood on test data
score = model.score(X_test)

# Access model attributes
print(f"Precision matrix: {model.precision_.shape}")
print(f"Covariance matrix: {model.covariance_.shape}")
print(f"Adjacency matrix: {model.adjacency_.shape}")
print(f"Number of edges: {model.n_edges_}")

6. Network Analysis

Convert the estimated graph to NetworkX for further analysis:

import networkx as nx

# Convert to NetworkX graph
G = model.to_networkx(threshold=0.01, weighted=True)

# Network statistics
print(f"Number of nodes: {G.number_of_nodes()}")
print(f"Number of edges: {G.number_of_edges()}")
print(f"Average degree: {sum(dict(G.degree()).values()) / G.number_of_nodes():.2f}")

# Centrality measures
degree_centrality = nx.degree_centrality(G)
betweenness_centrality = nx.betweenness_centrality(G)

# Find connected components
components = list(nx.connected_components(G))
print(f"Number of connected components: {len(components)}")

7. Visualization

from pyggm.visualization import (
    plot_network,
    plot_precision_matrix,
    plot_stars_path,
    plot_edge_stability,
    plot_model_selection
)
import matplotlib.pyplot as plt

# Create comprehensive visualization
fig = plt.figure(figsize=(16, 10))

# Network plot
ax1 = plt.subplot(2, 3, 1)
plot_network(model.precision_, threshold=0.01, layout='spring', ax=ax1)

# Precision matrix heatmap
ax2 = plt.subplot(2, 3, 2)
plot_precision_matrix(model.precision_, ax=ax2)

# StARS path (if using StARS)
if hasattr(model, 'instabilities_'):
    ax3 = plt.subplot(2, 3, 3)
    plot_stars_path(model, ax=ax3)

    ax4 = plt.subplot(2, 3, 4)
    plot_edge_stability(model, ax=ax4)

# Model selection plot
ax5 = plt.subplot(2, 3, 5)
plot_model_selection(model, ax=ax5)

plt.tight_layout()
plt.show()

8. Complete Pipeline Example

import numpy as np
from pyggm import GaussianGraphicalModel, NonparanormalTransformer
from pyggm.visualization import plot_network, plot_stars_path
import matplotlib.pyplot as plt

# 1. Load/generate data
np.random.seed(42)
n, p = 200, 30

# Create data with known structure
true_precision = np.eye(p)
true_precision[0, 1] = true_precision[1, 0] = 0.5
true_precision[2, 3] = true_precision[3, 2] = 0.4
true_cov = np.linalg.inv(true_precision)
X = np.random.multivariate_normal(np.zeros(p), true_cov, n)

# 2. Optional: Apply nonparanormal transformation
# (Skip if data is already Gaussian)
transformer = NonparanormalTransformer()
X_transformed = transformer.fit_transform(X)

# 3. Fit model
model = GaussianGraphicalModel(
    method='stars',
    beta=0.05,
    n_subsamples=50,
    n_jobs=-1,
    random_state=42,
    verbose=1
)
model.fit(X_transformed)

# 4. Evaluate
print(f"\nModel Summary:")
print(f"  Selected alpha: {model.alpha_:.4f}")
print(f"  Number of edges: {model.n_edges_}")
print(f"  Sparsity: {1 - model.n_edges_ / (p * (p-1) / 2):.2%}")

# 5. Visualize
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
plot_network(model.precision_, threshold=0.01, ax=axes[0])
plot_stars_path(model, ax=axes[1])
plt.savefig('ggm_results.png', dpi=300, bbox_inches='tight')
plt.show()

# 6. Export to NetworkX for further analysis
G = model.to_networkx(threshold=0.01)
print(f"\nNetwork statistics:")
print(f"  Nodes: {G.number_of_nodes()}")
print(f"  Edges: {G.number_of_edges()}")
print(f"  Density: {2 * G.number_of_edges() / (p * (p-1)):.3f}")

API Reference

GaussianGraphicalModel

Main estimator class for Gaussian Graphical Models.

Parameters:

  • method (str): Regularization selection method ('stars', 'ebic', or 'cv')
  • correlation (str): Correlation type ('pearson', 'spearman', or 'kendall')
  • alpha (float or None): Fixed regularization parameter
  • n_alphas (int): Number of alpha values to evaluate
  • alpha_min_ratio (float): Ratio of min to max alpha
  • beta (float): StARS instability threshold
  • n_subsamples (int): Number of subsamples for StARS
  • gamma (float): EBIC gamma parameter
  • cv (int): Number of CV folds
  • ensure_psd (bool): Project correlation matrix to PSD
  • n_jobs (int): Number of parallel jobs
  • random_state (int or None): Random seed
  • verbose (int): Verbosity level

Attributes:

  • precision_: Estimated precision matrix
  • covariance_: Estimated covariance matrix
  • adjacency_: Binary adjacency matrix
  • alpha_: Selected regularization parameter
  • n_edges_: Number of edges
  • alphas_: Grid of alphas evaluated
  • instabilities_: StARS instabilities (if method='stars')
  • ebic_scores_: EBIC scores (if method='ebic')
  • cv_scores_: CV scores (if method='cv')

Methods:

  • fit(X): Fit the model
  • score(X): Compute average log-likelihood
  • to_networkx(threshold, weighted, labels): Convert to NetworkX graph

NonparanormalTransformer

Gaussian copula transformation for non-Gaussian data.

Parameters:

  • truncate (bool): Whether to truncate extreme values

Methods:

  • fit(X): Learn empirical CDFs
  • transform(X): Apply transformation
  • fit_transform(X): Fit and transform in one step

Algorithm Details

StARS (Stability Approach to Regularization Selection)

StARS selects the regularization parameter by evaluating the stability of edge selection across multiple subsamples. It chooses the smallest alpha where the instability is below a threshold β (default 0.05).

Key parameters:

  • n_subsamples: More subsamples = more stable selection (default 50)
  • subsample_size: Defaults to floor(10 * sqrt(n))
  • beta: Lower values = sparser graphs (default 0.05)

Reference: Liu, H., Roeder, K., & Wasserman, L. (2010). Stability approach to regularization selection (stars) for high dimensional graphical models. NIPS.

EBIC (Extended BIC)

EBIC extends the standard BIC with an additional penalty for graph sparsity:

EBIC = -2 * log_likelihood + |E| * log(n) + 4 * |E| * gamma * log(p)

Key parameters:

  • gamma: Controls sparsity penalty (0 = standard BIC, 0.5 recommended for high-dimensional settings)

Reference: Foygel, R., & Drton, M. (2010). Extended Bayesian information criteria for Gaussian graphical models. NIPS.

Nonparanormal

The nonparanormal assumes a Gaussian copula: after transforming each variable's marginal distribution to Gaussian, the joint distribution is multivariate Gaussian.

Transformations:

  • Copula: X_j → Φ^(-1)(F_hat_j(X_j))
  • Spearman: ρ → 2 * sin(π/6 * ρ)
  • Kendall: τ → sin(π/2 * τ)

Reference: Liu, H., Lafferty, J., & Wasserman, L. (2009). The nonparanormal: Semiparametric estimation of high dimensional undirected graphs. JMLR.

Performance Tips

  1. Use parallelization: Set n_jobs=-1 to use all CPU cores
  2. For large p: Consider using method='ebic' (faster than StARS)
  3. For robust estimation: Use correlation='spearman' or apply NonparanormalTransformer
  4. For interpretability: Use method='stars' with default beta=0.05

Testing

Run the test suite:

# Install test dependencies
pip install -e ".[dev]"

# Run all tests
pytest

# Run with coverage
pytest --cov=pyggm --cov-report=html

# Run specific test file
pytest tests/test_ggm.py -v

Development

Code formatting

# Format code
black src/ tests/

# Check with ruff
ruff check src/ tests/ --fix

Type checking

mypy src/pyggm/

Citation

If you use PyGGM in your research, please cite the relevant papers:

@article{liu2010stars,
  title={Stability approach to regularization selection (stars) for high dimensional graphical models},
  author={Liu, Han and Roeder, Kathryn and Wasserman, Larry},
  journal={Advances in neural information processing systems},
  volume={23},
  year={2010}
}

@article{foygel2010ebic,
  title={Extended Bayesian information criteria for Gaussian graphical models},
  author={Foygel, Rina and Drton, Mathias},
  journal={Advances in neural information processing systems},
  volume={23},
  pages={604--612},
  year={2010}
}

@article{liu2009nonparanormal,
  title={The nonparanormal: Semiparametric estimation of high dimensional undirected graphs},
  author={Liu, Han and Lafferty, John and Wasserman, Larry},
  journal={Journal of Machine Learning Research},
  volume={10},
  number={10},
  year={2009}
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Acknowledgments

This package wraps scikit-learn's GraphicalLasso implementation and implements the StARS and EBIC selection procedures based on the cited papers.

Support


PyGGM - A Python package for Gaussian Graphical Models

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyggm-0.1.0.tar.gz (27.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyggm-0.1.0-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file pyggm-0.1.0.tar.gz.

File metadata

  • Download URL: pyggm-0.1.0.tar.gz
  • Upload date:
  • Size: 27.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for pyggm-0.1.0.tar.gz
Algorithm Hash digest
SHA256 219ba716c020b790728677473176e9f703bff143f9b0bb23d77425c2d140a55d
MD5 089f46a3f81079276ce9569af334977f
BLAKE2b-256 4a45cc41149a2dace03eb7fdd0e07bba50dc3d4922b2d9166a13aeac2f97ab17

See more details on using hashes here.

File details

Details for the file pyggm-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyggm-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for pyggm-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a05622691456a5bab0995b7ff3ae5902259ff38d707742d89308a60bb9e3d649
MD5 0265b95325d6b541065da0509a11d8e3
BLAKE2b-256 97e80a652119f51fa011abc42fbf2c71ed6d59a5934e3fbd2ea12afffeb090ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page