Вы можете реализовать это вручную с помощью выборки обратного преобразования .Вы в основном вычисляете обратное кумулятивной функции распределения для значений, взятых из равномерного распределения между 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()