[algorithm] 균등 분포를 정규 분포로 변환

균등 분포 (대부분의 난수 생성기가 생성하는 0.0과 1.0 사이)를 정규 분포로 어떻게 변환 할 수 있습니까? 내가 선택한 평균 및 표준 편차를 원하면 어떻게합니까?



답변

지구라트 알고리즘은 있지만,이 꽤 효율적이다 박스 뮬러 변환 처음부터 쉽게 구현 (느린 미친되지 않음)입니다.


답변

많은 방법이 있습니다.

  • 마십시오 하지 상자 뮬러를 사용합니다. 특히 많은 가우스 숫자를 그리는 경우. Box Muller는 -6과 6 사이에 고정 된 결과를 산출합니다 (배정 밀도 가정. 수레로 인해 상황이 악화됩니다.). 그리고 다른 사용 가능한 방법보다 효율성이 떨어집니다.
  • Ziggurat는 괜찮지 만 테이블 조회가 필요합니다 (캐시 크기 문제로 인해 일부 플랫폼 별 조정).
  • 균일 비율은 내가 가장 좋아하는 것인데, 몇 번의 덧셈 / 곱셈과 로그의 1/50 정도입니다 (예 : 저기보세요 ).
  • CDF를 반전하는 것은 효율적이며 (그리고 간과 된 이유는 무엇입니까?) Google을 검색하면 사용할 수있는 빠른 구현이 있습니다. 준 난수에는 필수입니다.

답변

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

즉, 특정 확률 함수 p (x)를 목표로하는 경우이를 적분하여 분포를 얻고-> d (x) = 적분 (p (x))을 역으로 사용합니다. Inv (d (x)) . 이제 무작위 확률 함수 (균일 분포를 가짐)를 사용하고 Inv (d (x)) 함수를 통해 결과 값을 캐스팅합니다. 선택한 함수에 따라 분포와 함께 무작위 값이 캐스팅되어야합니다.

이것은 일반적인 수학 접근 방식입니다. 이제이를 사용하여 역 근사 또는 좋은 역 근사를 가지고있는 한 모든 확률 또는 분포 함수를 선택할 수 있습니다.

이것이 도움이 되었기를 바라며 확률 자체가 아닌 분포 사용에 대한 작은 언급에 감사드립니다.


답변

다음은 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 */
}


답변

중앙 한계 정리 위키피디아 항목 mathworld 항목 을 유리하게 사용하십시오.

균등하게 분포 된 n 개의 숫자를 생성하고 합계하고 n * 0.5를 빼면 평균이 0이고 분산이 다음과 같은 대략적인 정규 분포의 결과가 나타납니다 (마지막 항목에 대한 균등 분포에 대한 위키피디아(1/12) * (1/sqrt(N)) 참조 ).

n = 10은 반쯤 괜찮은 속도를 제공합니다. 반 이상 괜찮은 것을 원한다면 tylers 솔루션으로 가십시오 ( 정규 분포에 대한 위키피디아 항목에서 언급했듯이 )


답변

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

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

답변

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

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

이것은 정확합니다 … 모든 느린 루프를 수행 할 필요가 없습니다!