Simplest Way to Generate an Assymetric Gaussian?

I feel like this should be easy and I’m just missing something, but what is the most straightforward way to define a skewed Gaussian distribution, i.e.

x \sim \frac{1}{\sqrt{2\cdot\pi\cdot(\frac{\sigma_1+\sigma_2}{2})^2}} \begin{cases} \exp(\frac{-1}{2}(\frac{x}{\sigma_1}))^2, x\lt 0 \\ \exp(\frac{-1}{2}(\frac{x}{\sigma_2}))^2, x \ge 0 \end{cases}

There doesn’t appear to be a standard distribution for this. The approaches I can think of are:

  1. Use some transformation to adjust x where x<0
  2. Define a new distribution
  3. Adjust the values after sample, i.e.
x = sample('x', dist.Normal(0,sig))
if x<0: x*=sigratio

Any direction as to the best way to approach this?

it depends what you’re doing but if you just need this distribution in the model and don’t need to sample from the distribution you only need to define log_prob in the custom distribution. and indeed the easiest route is to just use a factor statement with a custom log_prob. to compute the latter you can use distributions.Normal(...).log_prob(...) to make it readable. but #3 should also work fine if you use jnp.where. #1 would probably be complicated

p.s. your normalization constant looks wrong

I’m trying to constrain the values of \sigma_1 and \sigma_2 using MCMC or SVI, or at least find the “best” value. Specifically, I want to combine this with another continuous distribution via MixtureGeneral, so I need a method that offers the same support.
Obviously I could use factor to do this manually, but I try to avoid this hack as a last resort as it can play strangely with SVI.

Ideally, I want something like:

def model(Y,E):
    sig1 = sample('sig1', [SOME PRIOR])
    sig2 = sample('sig1', [SOME PRIOR])
    mean = sample('sig1', [SOME PRIOR])

    with plate('data', len(Y)):
        sample('y', [SOME DISTRIBUTION])

sampler = MCMC(NUTS(model))

There is obviously also the issue of the gaussian errors being randomly distributed as well, which makes things a little messier.

If you want a fully fledged distribution your best bet is probably to create a custom transform roughly along the lines of AffineTransform