Как сделать выборку из усеченного гауссовского распределения без использования SciPy? - PullRequest
0 голосов
/ 09 февраля 2019

SciPy - огромная библиотека.Довольно неловко, что для использования простой функции, то есть вычисления усеченного дистрибутива, мне нужно установить (и импортировать) 23 МБ кода.

Есть какое-то решение для более простого решения этой проблемы?

1 Ответ

0 голосов
/ 09 февраля 2019

Вы можете реализовать это вручную с помощью выборки обратного преобразования .Вы в основном вычисляете обратное кумулятивной функции распределения для значений, взятых из равномерного распределения между 0 и 1.

import numpy as np

def normal(x, mu, sig):
    return 1. / (np.sqrt(2 * np.pi) * sig) * np.exp(-0.5 * np.square(x - mu) / np.square(sig))


def trunc_normal(x, mu, sig, bounds=None):
    if bounds is None: 
        bounds = (-np.inf, np.inf)

    norm = normal(x, mu, sig)
    norm[x < bounds[0]] = 0
    norm[x > bounds[1]] = 0

    return norm


def sample_trunc(n, mu, sig, bounds=None):
    """ Sample `n` points from truncated normal distribution """
    x = np.linspace(mu - 5. * sig, mu + 5. * sig, 10000)
    y = trunc_normal(x, mu, sig, bounds)
    y_cum = np.cumsum(y) / y.sum()

    yrand = np.random.rand(n)
    sample = np.interp(yrand, y_cum, x)

    return sample


# Example
import matplotlib.pyplot as plt
samples = sample_trunc(10000, 0, 1, (-1, 1))
plt.hist(samples, bins=100)
plt.show()
...