Как я могу преобразовать равномерное распределение (поскольку большинство генераторов случайных чисел производят, например, между 0.0 и 1.0) в нормальное распределение? Что, если я хочу среднего и стандартного отклонения от моего выбора?
Преобразование равномерного распределения в нормальное распределение
Ответ 1
алгоритм Зиггурата довольно эффективен для этого, хотя Box- Преобразование Muller проще реализовать с нуля (и не безумно медленно).
Ответ 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);
, это результат:
Очевидно, что это действительно неэффективно по сравнению с встроенным 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;
}
Ответ 16
Приближение:
function rnd_snd() {
return (Math.random()*2-1)+(Math.random()*2-1)+(Math.random()*2-1);
}