it-swarm-ko.tech

균일 분포를 정규 분포로 변환

균일 분포 (대부분의 난수 생성기에서 생성 된 (예 : 0.0과 1.0))를 정규 분포로 변환하려면 어떻게해야합니까? 선택한 평균 및 표준 편차를 원하는 경우 어떻게합니까?

96
Terhorst

Box-Muller transform 은 처음부터 쉽게 구현할 수 있지만 속도가 느리지는 않지만 Ziggurat algorithm 은 매우 효율적입니다.

48
Tyler

많은 방법이 있습니다 :

  • not Box Muller를 사용하십시오. 특히 많은 가우스 숫자를 그리는 경우. Box Muller는 -6과 6 사이에 고정 된 결과를 산출합니다 (배정 밀도를 가정하고 수레로 인해 상황이 악화됨). 그리고 사용 가능한 다른 방법보다 효율성이 떨어집니다.
  • Ziggurat는 훌륭하지만 테이블 조회가 필요합니다 (캐시 크기 문제로 인한 일부 플랫폼 특정 조정)
  • 균일 비율은 내가 가장 좋아하는 것으로, 몇 가지 더하기/곱하기와 1/50의 로그입니다 (예 : look there ).
  • CDF is 효율적이면서도 간과 한 이유는 무엇입니까? Google을 검색하면 CD를 빠르게 구현할 수 있습니다. 준-랜덤 번호는 필수입니다.
42
Alexandre C.

함수의 분포를 다른 함수의 분포로 변경하려면 원하는 함수의 역수를 사용해야합니다.

즉, 특정 확률 함수 p(x)를 목표로하면 분포를 적분하여 분포를 얻습니다.-> d(x) = 적분 (p (x))와 그 역수를 사용하십시오 : Inv (d (x)) 이제 확률 분포 함수 (균일 분포)를 사용하고 결과 값을 함수 Inv (d (x))를 통해 캐스트하십시오. 선택한 함수에 따라 분포로 캐스트 된 임의 값.

이것은 일반적인 수학 접근법입니다.이를 사용하면 역 또는 근사 근사가있는 한 보유한 확률 또는 분포 함수를 선택할 수 있습니다.

이것이 도움이 되길 바랍니다. 확률 자체가 아니라 분포를 사용하는 것에 대한 작은 언급에 감사드립니다.

27
Adi

다음은 극좌표 형식의 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 */
}
21
user5084

중심 한계 정리 wikipedia entrymathworld entry 를 활용하십시오.

균일하게 분포 된 숫자 중 n 개를 생성하고, 합산하고, n * 0.5를 빼면 평균이 0이고 분산이 (1/12) * (1/sqrt(N)) 인 대략 정규 분포의 결과를 얻습니다 ( 균일 분포의 위키 백과 참조) 마지막 것)

n = 10은 반 정도의 빠른 속도를 제공합니다. 타일러 솔루션을 반 이상으로 원한다면 ( 정규 배포판의 위키 백과 항목 )

5
jilles de wit

8 년 후에 이것에 무언가를 추가 할 수는 없지만, Java의 경우 독자에게 Random.nextGaussian () 메소드를 가리키고 싶습니다 평균 0.0 및 표준 편차 1.0의 가우스 분포를 생성합니다.

간단한 덧셈 및/또는 곱셈은 요구에 대한 평균 및 표준 편차를 변경합니다.

1
Pepijn Schmitz

Box-Muller를 사용합니다. 이것에 대한 두 가지 :

  1. 반복 당 두 개의 값으로 끝납니다.
    일반적으로 한 값을 캐시하고 다른 값을 반환합니다. 다음에 샘플을 호출하면 캐시 된 값을 반환합니다.
  2. Box-Muller는 Z- 점수를 제공합니다
    그런 다음 표준 편차로 Z- 점수를 스케일링하고 정규 분포에서 전체 값을 구하기위한 평균을 추가해야합니다.
1
hughdbrown

표준 Python 라이브러리 모듈 random 은 원하는 것을 가지고 있습니다 :

정규 변량 (mu, sigma)
정규 분포. mu는 평균이고, sigma는 표준 편차입니다.

알고리즘 자체는 Python 라이브러리에서 random.py의 함수를 살펴보십시오.

수동 입력은 여기에 있습니다

1
Brent.Longborough

R1, R2는 임의의 균일 한 숫자입니다.

표준 분포, SD가 1 : 1 인 sqrt (-2 * log (R1)) * cos (2 * pi * R2)

이것은 정확합니다 ... 느린 루프를 모두 수행 할 필요는 없습니다!

1
Erik Aronesty

Q 균일 분포 (대부분의 난수 생성기 (예 : 0.0과 1.0) 생성)를 정규 분포로 변환하려면 어떻게해야합니까?

  1. 소프트웨어 구현을 위해 [0,1] (Mersenne Twister, Linear Congruate Generator)에서 의사 균일 한 랜덤 시퀀스를 제공하는 랜덤 생성기 이름을 알고 있습니다. 그것을 U (x)라고합시다

  2. 확률 이론이라고 불리는 수학적 영역이 존재합니다. 첫 번째 : r.v를 모델링하려는 경우 적분 분포 F를 사용하면 F ^ -1 (U (x))를 평가할 수 있습니다. PR 이론에서 그러한 r.v. 적분 분포 F를 갖습니다.

  3. 2 단계는 F ^ -1이 문제없이 분석적으로 도출 될 수있는 경우 계산 방법을 사용하지 않고 r.v. ~ F를 생성하는 데 적용 할 수 있습니다. (예 : exp. 분포)

  4. 정규 분포를 모델링하기 위해 y1 ~ [0,2pi]에서 균일 한 y1 * cos (y2)를 계산할 수 있습니다. y2는 relei 분포입니다.

Q : 선택한 평균 및 표준 편차를 원하는 경우 어떻게합니까?

시그마 * N (0,1) + m을 계산할 수 있습니다.

그러한 이동 및 스케일링은 N (m, 시그마)로 이어진다는 것을 알 수있다

0
bruziuz

이것은 Box-Muller 변환의 극좌표 형식을 사용하는 Matlab 구현입니다.

기능 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 과 비교할 때 실제로 비효율적입니다.

0
madx

도움이 될 수있는 다음 코드가 있습니다.

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)]

정규 분포에 대한 난수 생성기를 작성하는 것보다 빠르기 때문에 구현 된 함수 rnorm ()을 사용하는 것이 더 쉽습니다. 증명하는 다음 코드를 참조하십시오

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

Excel에서 =norminv(Rand();0;1)을 사용해보십시오. 이것은 제로 평균 및 단 분산 분산으로 정규 분포되어야하는 난수를 생성합니다. "0"은 임의의 값으로 제공 될 수 있으므로 숫자는 원하는 평균이되며 "1"을 변경하면 입력의 제곱과 같은 분산을 얻게됩니다.

예를 들어 : =norminv(Rand();50;3)은 MEAN = 50 VARIANCE = 9 인 정규 분포 숫자를 산출합니다.

0
Hippo