Преобразование равномерного распределения в нормальное распределение

Как я могу преобразовать равномерное распределение (поскольку большинство генераторов случайных чисел производят, например, между 0.0 и 1.0) в нормальное распределение? Что, если я хочу среднего и стандартного отклонения от моего выбора?

Ответ 2

Существует множество способов:

  • Используйте не для использования Box Muller. Особенно, если вы рисуете много гауссовских чисел. Box Muller дает результат, который зажат между -6 и 6 (при условии двойной точности. Вещи ухудшаются с поплавками). И это действительно менее эффективно, чем другие доступные методы.
  • Ziggurat в порядке, но вам нужен поиск в таблице (и некоторые настройки для конкретной платформы из-за проблем с размером кеша)
  • Соотношение формы - мой любимый, только несколько добавлений/умножений и log 1/50-й раз (например, посмотреть там).
  • Инверсия CDF эффективна (и не учитывается, почему?), вы быстро реализуете ее, если ищете Google. Это обязательно для Квази-случайных чисел.

Ответ 3

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

Другими словами, если вы нацелитесь на определенную вероятностную функцию p (x), вы получите распределение, интегрируя по ней → d (x) = интеграл (p (x)) и воспользуемся его обратным: Inv (d ( Икс)). Теперь используйте случайную вероятностную функцию (которая имеет равномерное распределение) и передают результат через функцию Inv (d (x)). Вы должны получить случайные значения, отличные от дистрибутива, в соответствии с выбранной вами функцией.

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

Надеюсь, это помогло и спасибо за небольшое замечание об использовании распределения, а не о самой вероятности.

Ответ 4

Вот реализация javascript, использующая полярную форму преобразования Box-Muller.

/*
 * Returns member of set with a given mean and standard deviation
 * mean: mean
 * standard deviation: std_dev 
 */
function createMemberInNormalDistribution(mean,std_dev){
    return mean + (gaussRandom()*std_dev);
}

/*
 * Returns random number in normal distribution centering on 0.
 * ~95% of numbers returned should fall between -2 and 2
 * ie within two standard deviations
 */
function gaussRandom() {
    var u = 2*Math.random()-1;
    var v = 2*Math.random()-1;
    var r = u*u + v*v;
    /*if outside interval [0,1] start over*/
    if(r == 0 || r >= 1) return gaussRandom();

    var c = Math.sqrt(-2*Math.log(r)/r);
    return u*c;

    /* todo: optimize this algorithm by caching (v*c) 
     * and returning next time gaussRandom() is called.
     * left out for simplicity */
}

Ответ 5

Используйте центральную предельную теорему запись википедия запись MathWorld в свою пользу.

Сгенерируйте n из равномерно распределенных чисел, сложите их, вычтите n * 0,5, и вы получите примерно нормальное распределение со средним значением, равным 0, и дисперсией, равной (1/12) * (1/sqrt(N)) (см. Википедия о равномерном распределении для этого последнего)

n = 10 дает вам что-то наполовину приличное быстро. Если вы хотите что-то более чем половинное, выбирайте решение Tylers (как отмечено в записи в Википедии о нормальных дистрибутивах)

Ответ 6

Я бы использовал Box-Muller. Две вещи об этом:

  • В итоге вы получите два значения за итерацию
    Как правило, вы кэшируете одно значение и возвращаете другое. При следующем вызове образца вы возвращаете кешированное значение.
  • Box-Muller дает Z-счет
    Затем вы должны масштабировать Z-показатель стандартным отклонением и добавить среднее значение, чтобы получить полное значение в нормальном распределении.

Ответ 7

Стандартный библиотечный модуль Python random имеет то, что вы хотите:

normalvariate (mu, sigma)
Нормальное распределение. mu - среднее значение, а сигма - стандартное отклонение.

Для самого алгоритма взгляните на функцию в random.py в библиотеке Python.

Здесь находится

Ответ 8

Где R1, R2 - случайные равномерные числа:

НОРМАЛЬНОЕ РАСПРЕДЕЛЕНИЕ с SD 1: sqrt (-2 * log (R1)) * cos (2 * pi * R2)

Это точно... не нужно делать все эти медленные циклы!

Ответ 9

Кажется невероятным, что я могу что-то добавить к этому через восемь лет, но для случая Java я хотел бы указать читателям на Random.nextGaussian( ), который генерирует распределение Гаусса со средним значением 0.0 и стандартным отклонением 1.0 для вас.

Простое сложение и/или умножение изменят среднее и стандартное отклонение к вашим потребностям.

Ответ 10

Я хочу попробовать это в EXCEL: =norminv(rand();0;1). Это будет производить случайные числа, которые должны нормально распределяться с нулевым средним значением и объединяться с дисперсией. "0" может быть снабжено любым значением, так что числа будут иметь желаемое среднее значение, и, изменив "1", вы получите дисперсию, равную квадрату вашего ввода.

Например: =norminv(rand();50;3) приведет к нормально распределенным номерам с MEAN = 50 VARIANCE = 9.

Ответ 11

Q Как преобразовать равномерное распределение (поскольку большинство генераторов случайных чисел производят, например, между 0.0 и 1.0) в нормальное распределение?

  • Для реализации программного обеспечения я знаю пару случайных генераторов, которые дают псевдослучайную последовательность в [0,1] (Mersenne Twister, Linear Congruate Generator). Пусть назовем U (x)

  • Существует математическая область, которая называется теорией вероятностей. Первое: если вы хотите моделировать r.v. с интегральным распределением F, то вы можете попробовать только оценить F ^ -1 (U (x)). В п.теории доказано, что такой р.в. будет иметь интегральное распределение F.

  • Шаг 2 может быть применен для генерации r.v. ~ F без использования каких-либо методов подсчета, когда F ^ -1 можно получить аналитически без проблем. (например, exp.distribution)

  • Чтобы моделировать нормальное распределение, вы можете cacculate y1 * cos (y2), где y1 ~ равномерно в [0,2pi]. и y2 является выпуклым распределением.

В: Что, если я хочу получить среднее и стандартное отклонение от моего выбора?

Вы можете вычислить сигма * N (0,1) + m.

Можно показать, что такое смещение и масштабирование приводят к N (m, sigma)

Ответ 12

Это реализация Matlab с использованием полярной формы преобразования Box-Muller:

Функция randn_box_muller.m:

function [values] = randn_box_muller(n, mean, std_dev)
    if nargin == 1
       mean = 0;
       std_dev = 1;
    end

    r = gaussRandomN(n);
    values = r.*std_dev - mean;
end

function [values] = gaussRandomN(n)
    [u, v, r] = gaussRandomNValid(n);

    c = sqrt(-2*log(r)./r);
    values = u.*c;
end

function [u, v, r] = gaussRandomNValid(n)
    r = zeros(n, 1);
    u = zeros(n, 1);
    v = zeros(n, 1);

    filter = r==0 | r>=1;

    % if outside interval [0,1] start over
    while n ~= 0
        u(filter) = 2*rand(n, 1)-1;
        v(filter) = 2*rand(n, 1)-1;
        r(filter) = u(filter).*u(filter) + v(filter).*v(filter);

        filter = r==0 | r>=1;
        n = size(r(filter),1);
    end
end

И вызывая histfit(randn_box_muller(10000000),100);, это результат: Box-Muller Matlab Histfit

Очевидно, что это действительно неэффективно по сравнению с встроенным Matlab randn.

Ответ 13

У меня есть следующий код, который может помочь:

set.seed(123)
n <- 1000
u <- runif(n) #creates U
x <- -log(u)
y <- runif(n, max=u*sqrt((2*exp(1))/pi)) #create Y
z <- ifelse (y < dnorm(x)/2, -x, NA)
z <- ifelse ((y > dnorm(x)/2) & (y < dnorm(x)), x, z)
z <- z[!is.na(z)]

Ответ 14

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

n <- length(z)
t0 <- Sys.time()
z <- rnorm(n)
t1 <- Sys.time()
t1-t0

Ответ 15

function distRandom(){
  do{
    x=random(DISTRIBUTION_DOMAIN);
  }while(random(DISTRIBUTION_RANGE)>=distributionFunction(x));
  return x;
}