Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:Pyro ppl Pyro SineSkewed

From Leeroopedia


Attribute Value
Sources pyro/distributions/sine_skewed.py
Domains Probabilistic Programming, Directional Statistics, Protein Bioinformatics, Torus Distributions
Last Updated 2026-02-09

Overview

Description

The SineSkewed distribution implements the Sine Skewing procedure from Ameijeiras-Alonso and Ley (2019) for breaking the pointwise symmetry of distributions defined on a torus. A torus distribution has support on products of circles, i.e., the Cartesian product of d copies of S^1 where S^1 = [-pi, pi). The 1-torus is a circle, the 2-torus is commonly associated with the donut shape, and higher-dimensional toruses generalize this structure.

Given a symmetric base distribution on a d-dimensional torus, the Sine Skewed distribution introduces an asymmetry controlled by a skewness parameter vector of dimension d. The key mathematical property is that the skewness parameters must satisfy the constraint that the sum of their absolute values is at most 1 (i.e., |skew_1| + |skew_2| + ... + |skew_d| <= 1). This constraint ensures that the sine skewing does not alter the normalization constant of the base distribution.

The distribution is particularly useful in protein bioinformatics, where torus-valued data arises from the dihedral angle pairs (phi, psi) of amino acid residues in the Ramachandran plot.

This class extends TorchDistribution and supports sampling, log probability computation, batch expansion, and works with Pyro's inference engines including HMC, NUTS, and SVI.

Usage

SineSkewed is designed to be wrapped around a symmetric torus distribution such as VonMises, SineBivariateVonMises, ProjectedNormal (1D), or Uniform(-pi, pi). It is used as a likelihood in SVI, and can be used with HMC/NUTS for inference over skewness parameters. For 2-torus and higher, using it as a latent variable in SVI leads to slow inference because the base distribution cannot be reparameterized.

Code Reference

Source Location

Property Value
File pyro/distributions/sine_skewed.py
Module pyro.distributions.sine_skewed
Repository pyro-ppl/pyro

Signature

class SineSkewed(TorchDistribution):
    arg_constraints = {
        "skewness": constraints.independent(constraints.interval(-1.0, 1.0), 1)
    }
    support = constraints.independent(constraints.real, 1)

    def __init__(self, base_dist: TorchDistribution, skewness, validate_args=None):
        ...

    def sample(self, sample_shape=torch.Size()):
        ...

    def log_prob(self, value):
        ...

    def expand(self, batch_shape, _instance=None):
        ...

Import

from pyro.distributions import SineSkewed

# Or from the module directly:
from pyro.distributions.sine_skewed import SineSkewed

I/O Contract

Constructor Parameters

Parameter Type Description
base_dist TorchDistribution A symmetric base distribution on a d-dimensional torus. Supported: 1D VonMises, SineBivariateVonMises, 1D ProjectedNormal, Uniform(-pi, pi).
skewness torch.Tensor Skewness parameter with shape (..., d). Each element must be in [-1, 1], and the sum of absolute values along the last dimension must be <= 1.
validate_args bool or None Whether to validate input arguments. Default: None.

Constraints

Constraint Details
arg_constraints skewness: each element in [-1, 1] (independent constraint over last dimension)
support Independent real-valued constraint over the event dimension (values on the torus in [-pi, pi))
Normalization constraint sum(abs(skewness), dim=-1) <= 1 -- a warning is emitted if violated
Shape constraint base_dist.event_shape == skewness.shape[-1:] -- skewness must have one weight per torus dimension

Methods

Method Return Type Description
sample(sample_shape) torch.Tensor Draws samples using the acceptance method from Section 2.3 of the reference. Returns values in [-pi, pi).
log_prob(value) torch.Tensor Computes log probability as base_dist.log_prob(value) + log(1 + sum(skewness * sin(value - base_dist.mean))) per Eq. 2.1 in the reference.
expand(batch_shape) SineSkewed Returns a new SineSkewed instance with expanded batch dimensions.

Usage Examples

Basic SineSkewed VonMises (1-Torus)

import torch
import pyro.distributions as dist

# 1D Von Mises base distribution on a circle
base = dist.VonMises(loc=torch.tensor(0.0), concentration=torch.tensor(5.0))

# Apply sine skewing with a single skewness parameter
skewness = torch.tensor([0.3])
ss_dist = dist.SineSkewed(base, skewness)

# Sample and compute log probability
sample = ss_dist.sample(torch.Size([100]))
log_p = ss_dist.log_prob(sample)
print(sample.shape)  # torch.Size([100, 1])
print(log_p.shape)   # torch.Size([100])

SineSkewed SineBivariateVonMises (2-Torus) for Protein Bioinformatics

import torch
import pyro
import pyro.distributions as dist
from pyro.distributions import SineBivariateVonMises, SineSkewed

def model(obs):
    # Priors for the bivariate von Mises parameters
    phi_loc = pyro.sample('phi_loc', dist.VonMises(torch.tensor(3.14), torch.tensor(2.0)))
    psi_loc = pyro.sample('psi_loc', dist.VonMises(torch.tensor(-1.57), torch.tensor(2.0)))
    phi_conc = pyro.sample('phi_conc', dist.Beta(torch.tensor(2.0), torch.tensor(5.0)))
    psi_conc = pyro.sample('psi_conc', dist.Beta(torch.tensor(2.0), torch.tensor(5.0)))
    corr_scale = pyro.sample('corr_scale', dist.Beta(torch.tensor(2.0), torch.tensor(5.0)))

    # Skewness priors respecting the L1 constraint
    skew_phi = pyro.sample('skew_phi', dist.Uniform(-1.0, 1.0))
    psi_bound = 1 - skew_phi.abs()
    skew_psi = pyro.sample('skew_psi', dist.Uniform(-1.0, 1.0))
    skewness = torch.stack((skew_phi, psi_bound * skew_psi), dim=-1)

    with pyro.plate('obs_plate'):
        base = SineBivariateVonMises(
            phi_loc=phi_loc, psi_loc=psi_loc,
            phi_concentration=1000 * phi_conc,
            psi_concentration=1000 * psi_conc,
            weighted_correlation=corr_scale,
        )
        return pyro.sample('phi_psi', SineSkewed(base, skewness), obs=obs)

Computing Log Probabilities

import torch
import pyro.distributions as dist

# Create a skewed distribution on the 1-torus
base = dist.VonMises(loc=torch.tensor(0.0), concentration=torch.tensor(3.0))
skewness = torch.tensor([-0.5])
ss = dist.SineSkewed(base, skewness)

# Evaluate log probability at specific angles
values = torch.linspace(-3.14, 3.14, 50).unsqueeze(-1)
log_probs = ss.log_prob(values)
print(log_probs.shape)  # torch.Size([50])

Related Pages

  • SineBivariateVonMises -- A common base distribution for 2-torus data used with SineSkewed
  • VonMises -- Circular distribution commonly used as a 1-torus base distribution
  • ProjectedNormal -- Another option for 1-torus base distributions
  • Distributions_Init -- Central registry of all Pyro distributions
  • Unit -- Trivial distribution used for factor statements in Pyro models

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment