Как получить нормальное распределение в диапазоне в numpy?

В задании машинного обучения. Мы должны получить группу случайного w.r.t нормального распределения со связанными. Мы можем получить нормальный номер распределения с np.random.normal(), но он не предлагает какой-либо связанный параметр. Я хочу знать, как это сделать?

Ответ 1

Параметризация truncnorm сложна, поэтому вот функция, которая переводит параметризацию в нечто более интуитивное:

from scipy.stats import truncnorm

def get_truncated_normal(mean=0, sd=1, low=0, upp=10):
    return truncnorm(
        (low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)


Как его использовать?

  • Введите генератор с параметрами: среднее значение, стандартное отклонение и диапазон усечения:

    >>> X = get_truncated_normal(mean=8, sd=2, low=1, upp=10)
    
  • Затем вы можете использовать X для генерации значения:

    >>> X.rvs()
    6.0491227353928894
    
  • Или, массив numpy с N сгенерированными значениями:

    >>> X.rvs(10)
    array([ 7.70231607,  6.7005871 ,  7.15203887,  6.06768994,  7.25153472,
            5.41384242,  7.75200702,  5.5725888 ,  7.38512757,  7.47567455])
    

Визуальный пример

Вот график трех разных усеченных нормальных распределений:

X1 = get_truncated_normal(mean=2, sd=1, low=1, upp=10)
X2 = get_truncated_normal(mean=5.5, sd=1, low=1, upp=10)
X3 = get_truncated_normal(mean=8, sd=1, low=1, upp=10)

import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, sharex=True)
ax[0].hist(X1.rvs(10000), normed=True)
ax[1].hist(X2.rvs(10000), normed=True)
ax[2].hist(X3.rvs(10000), normed=True)
plt.show()

введите описание изображения здесь

Ответ 2

Если вы ищете Усеченное нормальное распределение, SciPy имеет функцию для него truncnorm

Стандартная форма этого распределения - стандартная нормальная усеченная в диапазон [a, b] - обратите внимание, что a и b определены по домену стандартного нормального. Чтобы преобразовать значения клипа для определенного среднего и стандартное отклонение, используйте:

a, b = (myclip_a - my_mean)/my_std, (myclip_b - my_mean)/my_std

truncnorm принимает a и b как параметры формы.

>>> from scipy.stats import truncnorm
>>> truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10)
array([-1.83136675,  0.77599978, -0.01276925,  1.87043384,  1.25024188,
        0.59336279, -0.39343176,  1.9449987 , -1.97674358, -0.31944247])

Приведенный выше пример ограничен 2 и 2 и возвращает 10 случайных вариаций (с использованием метода .rvs())

>>> min(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
-1.9996074381484044
>>> max(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
1.9998486576228549

Здесь график гистограммы для -6, 6:

введите описание изображения здесь