2010-06-24 7 views
8

좋아, 내 문제는 여기에있다. 우리는 기존 데이터 세트를 보강하기 위해 한 회사의 데이터 세트를 구매하려고합니다. 이 질문의 목적을 위해이 데이터 세트가 유기적 인 번호로 순위를 매긴다는 것을 의미합니다 (즉, 한 장소에 할당 된 번호는 다른 장소에 할당 된 번호와 관련이 없음을 의미). 기술적 인 범위는 0에서 무한대까지이지만, 내가 본 샘플 세트에서 보면 0에서 70까지입니다. 샘플을 보면, 가장 확실하게 균일 한 분포는 아닙니다 (10,000 개 중 40 개 이상이 5 개, 50 점은 10 점 이상, 1000 점은 1 점 이상). 이 세트를 구입하기 전에 시뮬레이션을 통해 유용성을 확인할 수 있습니다.확률 분포로 난수 생성

그래서 시뮬레이션을 위해 각 장소 (약 150,000 개의 난수)에 임의의 숫자를 생성하려고 생각했습니다. 그러나 나는 또한 데이터의 정신을 간직하고 배포를 상대적으로 동일하게 (또는 최소한 합리적으로) 유지하려고합니다. 나는 하루 종일 내 머리를 짚어서 그 일을 할 길을 생각하고 비어있게되었습니다.

하나의 생각은 난수 (0과 sqrt (70) 사이)를 제곱하는 것이 었습니다. 그러나 그것은 1과 2보다 작은 수를 모두 선호합니다.

저는 실제 분포가 첫 번째 사분면에서 쌍곡선이어야한다고 생각합니다 ... 나는 선형 분포, 무작위 수의 분포를 쌍곡선 분포로 바꾸는 방법에 대해서만 공백입니다 (쌍곡선이 첫 번째 장소에서 원한다.)

의견이 있으십니까? 70 -

  • 40 : 0.02 % - 0.05 %
  • 10-40 : 0.5 % - 1 %
  • 1

    그래서, 요약하면, 여기에 내가 (약)하고자하는 배포판의 - 10 : 10 % - 20 %

  • 0-1 : 나머지 (78.95 % - 89.48 %)
+0

나는이 통계 용어집 [http://www.stats.gla.ac.uk/steps/glossary/probability_distributions.html#cdf]를 발견했다. 도움이 될 수도 있습니다. – IAbstract

+0

나는 그것을 얻지 못한다. 150k 세트를 통해 배포하려는 0에서 70 사이의 10k 부동 소수점 숫자가 있습니까? –

+0

@Jonas Elfström : 글쎄, 그 반대편. 지정된 분포로 150k 임의의 부동 소수점 수를 생성하고 싶습니다 ... – ircmaxell

답변

10

신뢰성 분석에 사용되는 분포를보십시오.이 긴 꼬리가있는 경향이 있습니다. 상대적으로 단순한 가능성은 P (X> x) = exp [- (x/b)^a] 인와 이블 분포이다.

값을 P (X> 1) = 0.1 및 P (X> 10) = 0.005로 맞추면 a = 0.36 및 b = 0.1이됩니다. 이것은 P (X> 40) * 10000 = 1.6이 조금 낮지 만 P (X> 70) * 10000 = 0.2는 합리적이라고 암시한다.

EDIT 오, 균일에서와 이블 분포 랜덤 변수를 생성 (0,1)의 값 U는 단지 B 형 * 계산 [를 - 로그 (1-U)]^(1/a). 이것은 내가 잘못 계산 한 경우 1-P (X> x)의 역함수입니다.

+0

와우, 난 후 결과 집합 거의 동일 보인다 (4> 40> 10 (60), 1030> 1). 우수한! 감사! – ircmaxell

8

서면 년 전 PHP4를 들어, 단순히 분배를 선택 :

<?php 

define('RandomGaussian',   'gaussian') ;   // gaussianWeightedRandom() 
define('RandomBell',    'bell') ;    // bellWeightedRandom() 
define('RandomGaussianRising',  'gaussianRising') ; // gaussianWeightedRisingRandom() 
define('RandomGaussianFalling', 'gaussianFalling') ; // gaussianWeightedFallingRandom() 
define('RandomGamma',    'gamma') ;    // gammaWeightedRandom() 
define('RandomGammaQaD',   'gammaQaD') ;   // QaDgammaWeightedRandom() 
define('RandomLogarithmic10',  'log10') ;    // logarithmic10WeightedRandom() 
define('RandomLogarithmic',  'log') ;    // logarithmicWeightedRandom() 
define('RandomPoisson',   'poisson') ;   // poissonWeightedRandom() 
define('RandomDome',    'dome') ;    // domeWeightedRandom() 
define('RandomSaw',    'saw') ;    // sawWeightedRandom() 
define('RandomPyramid',   'pyramid') ;   // pyramidWeightedRandom() 
define('RandomLinear',    'linear') ;   // linearWeightedRandom() 
define('RandomUnweighted',   'non') ;    // nonWeightedRandom() 



function mkseed() 
{ 
    srand(hexdec(substr(md5(microtime()), -8)) & 0x7fffffff) ; 
} // function mkseed() 




/* 
function factorial($in) { 
    if ($in == 1) { 
     return $in ; 
    } 
    return ($in * factorial($in - 1.0)) ; 
} // function factorial() 


function factorial($in) { 
    $out = 1 ; 
    for ($i = 2; $i <= $in; $i++) { 
     $out *= $i ; 
    } 

    return $out ; 
} // function factorial() 
*/ 




function random_0_1() 
{ 
    // returns random number using mt_rand() with a flat distribution from 0 to 1 inclusive 
    // 
    return (float) mt_rand()/(float) mt_getrandmax() ; 
} // random_0_1() 


function random_PN() 
{ 
    // returns random number using mt_rand() with a flat distribution from -1 to 1 inclusive 
    // 
    return (2.0 * random_0_1()) - 1.0 ; 
} // function random_PN() 




function gauss() 
{ 
    static $useExists = false ; 
    static $useValue ; 

    if ($useExists) { 
     // Use value from a previous call to this function 
     // 
     $useExists = false ; 
     return $useValue ; 
    } else { 
     // Polar form of the Box-Muller transformation 
     // 
     $w = 2.0 ; 
     while (($w >= 1.0) || ($w == 0.0)) { 
      $x = random_PN() ; 
      $y = random_PN() ; 
      $w = ($x * $x) + ($y * $y) ; 
     } 
     $w = sqrt((-2.0 * log($w))/$w) ; 

     // Set value for next call to this function 
     // 
     $useValue = $y * $w ; 
     $useExists = true ; 

     return $x * $w ; 
    } 
} // function gauss() 


function gauss_ms($mean, 
        $stddev) 
{ 
    // Adjust our gaussian random to fit the mean and standard deviation 
    // The division by 4 is an arbitrary value to help fit the distribution 
    //  within our required range, and gives a best fit for $stddev = 1.0 
    // 
    return gauss() * ($stddev/4) + $mean; 
} // function gauss_ms() 


function gaussianWeightedRandom($LowValue, 
           $maxRand, 
           $mean=0.0, 
           $stddev=2.0) 
{ 
    // Adjust a gaussian random value to fit within our specified range 
    //  by 'trimming' the extreme values as the distribution curve 
    //  approaches +/- infinity 
    $rand_val = $LowValue + $maxRand ; 
    while (($rand_val < $LowValue) || ($rand_val >= ($LowValue + $maxRand))) { 
     $rand_val = floor(gauss_ms($mean,$stddev) * $maxRand) + $LowValue ; 
     $rand_val = ($rand_val + $maxRand)/2 ; 
    } 

    return $rand_val ; 
} // function gaussianWeightedRandom() 


function bellWeightedRandom($LowValue, 
          $maxRand) 
{ 
    return gaussianWeightedRandom($LowValue, $maxRand, 0.0, 1.0) ; 
} // function bellWeightedRandom() 


function gaussianWeightedRisingRandom($LowValue, 
             $maxRand) 
{ 
    // Adjust a gaussian random value to fit within our specified range 
    //  by 'trimming' the extreme values as the distribution curve 
    //  approaches +/- infinity 
    // The division by 4 is an arbitrary value to help fit the distribution 
    //  within our required range 
    $rand_val = $LowValue + $maxRand ; 
    while (($rand_val < $LowValue) || ($rand_val >= ($LowValue + $maxRand))) { 
     $rand_val = $maxRand - round((abs(gauss())/4) * $maxRand) + $LowValue ; 
    } 

    return $rand_val ; 
} // function gaussianWeightedRisingRandom() 


function gaussianWeightedFallingRandom($LowValue, 
             $maxRand) 
{ 
    // Adjust a gaussian random value to fit within our specified range 
    //  by 'trimming' the extreme values as the distribution curve 
    //  approaches +/- infinity 
    // The division by 4 is an arbitrary value to help fit the distribution 
    //  within our required range 
    $rand_val = $LowValue + $maxRand ; 
    while (($rand_val < $LowValue) || ($rand_val >= ($LowValue + $maxRand))) { 
     $rand_val = floor((abs(gauss())/4) * $maxRand) + $LowValue ; 
    } 

    return $rand_val ; 
} // function gaussianWeightedFallingRandom() 


function logarithmic($mean=1.0, $lambda=5.0) 
{ 
    return ($mean * -log(random_0_1()))/$lambda ; 
} // function logarithmic() 


function logarithmicWeightedRandom($LowValue, 
            $maxRand) 
{ 
    do { 
     $rand_val = logarithmic() ; 
    } while ($rand_val > 1) ; 

    return floor($rand_val * $maxRand) + $LowValue ; 
} // function logarithmicWeightedRandom() 


function logarithmic10($lambda=0.5) 
{ 
    return abs(-log10(random_0_1())/$lambda) ; 
} // function logarithmic10() 


function logarithmic10WeightedRandom($LowValue, 
             $maxRand) 
{ 
    do { 
     $rand_val = logarithmic10() ; 
    } while ($rand_val > 1) ; 

    return floor($rand_val * $maxRand) + $LowValue ; 
} // function logarithmic10WeightedRandom() 


function gamma($lambda=3.0) 
{ 
    $wLambda = $lambda + 1.0 ; 
    if ($lambda <= 8.0) { 
     // Use direct method, adding waiting times 
     $x = 1.0 ; 
     for ($j = 1; $j <= $wLambda; $j++) { 
      $x *= random_0_1() ; 
     } 
     $x = -log($x) ; 
    } else { 
     // Use rejection method 
     do { 
      do { 
       // Generate the tangent of a random angle, the equivalent of 
       //  $y = tan(pi * random_0_1()) 
       do { 
        $v1 = random_0_1() ; 
        $v2 = random_PN() ; 
       } while (($v1 * $v1 + $v2 * $v2) > 1.0) ; 
       $y = $v2/$v1 ; 
       $s = sqrt(2.0 * $lambda + 1.0) ; 
       $x = $s * $y + $lambda ; 
      // Reject in the region of zero probability 
      } while ($x <= 0.0) ; 
      // Ratio of probability function to comparison function 
      $e = (1.0 + $y * $y) * exp($lambda * log($x/$lambda) - $s * $y) ; 
     // Reject on the basis of a second uniform deviate 
     } while (random_0_1() > $e) ; 
    } 

    return $x ; 
} // function gamma() 


function gammaWeightedRandom($LowValue, 
           $maxRand) 
{ 
    do { 
     $rand_val = gamma()/12 ; 
    } while ($rand_val > 1) ; 

    return floor($rand_val * $maxRand) + $LowValue ; 
} // function gammaWeightedRandom() 


function QaDgammaWeightedRandom($LowValue, 
           $maxRand) 
{ 
    return round((asin(random_0_1()) + (asin(random_0_1()))) * $maxRand/pi()) + $LowValue ; 
} // function QaDgammaWeightedRandom() 


function gammaln($in) 
{ 
    $tmp = $in + 4.5 ; 
    $tmp -= ($in - 0.5) * log($tmp) ; 

    $ser = 1.000000000190015 
      + (76.18009172947146/$in) 
      - (86.50532032941677/($in + 1.0)) 
      + (24.01409824083091/($in + 2.0)) 
      - (1.231739572450155/($in + 3.0)) 
      + (0.1208650973866179e-2/($in + 4.0)) 
      - (0.5395239384953e-5/($in + 5.0)) ; 

    return (log(2.5066282746310005 * $ser) - $tmp) ; 
} // function gammaln() 


function poisson($lambda=1.0) 
{ 
    static $oldLambda ; 
    static $g, $sq, $alxm ; 

    if ($lambda <= 12.0) { 
     // Use direct method 
     if ($lambda <> $oldLambda) { 
      $oldLambda = $lambda ; 
      $g = exp(-$lambda) ; 
     } 
     $x = -1 ; 
     $t = 1.0 ; 
     do { 
      ++$x ; 
      $t *= random_0_1() ; 
     } while ($t > $g) ; 
    } else { 
     // Use rejection method 
     if ($lambda <> $oldLambda) { 
      $oldLambda = $lambda ; 
      $sq = sqrt(2.0 * $lambda) ; 
      $alxm = log($lambda) ; 
      $g = $lambda * $alxm - gammaln($lambda + 1.0) ; 
     } 
     do { 
      do { 
       // $y is a deviate from a Lorentzian comparison function 
       $y = tan(pi() * random_0_1()) ; 
       $x = $sq * $y + $lambda ; 
      // Reject if close to zero probability 
      } while ($x < 0.0) ; 
      $x = floor($x) ; 
      // Ratio of the desired distribution to the comparison function 
      // We accept or reject by comparing it to another uniform deviate 
      // The factor 0.9 is used so that $t never exceeds 1 
      $t = 0.9 * (1.0 + $y * $y) * exp($x * $alxm - gammaln($x + 1.0) - $g) ; 
     } while (random_0_1() > $t) ; 
    } 

    return $x ; 
} // function poisson() 


function poissonWeightedRandom($LowValue, 
           $maxRand) 
{ 
    do { 
     $rand_val = poisson()/$maxRand ; 
    } while ($rand_val > 1) ; 

    return floor($x * $maxRand) + $LowValue ; 
} // function poissonWeightedRandom() 


function binomial($lambda=6.0) 
{ 
} 


function domeWeightedRandom($LowValue, 
          $maxRand) 
{ 
    return floor(sin(random_0_1() * (pi()/2)) * $maxRand) + $LowValue ; 
} // function bellWeightedRandom() 


function sawWeightedRandom($LowValue, 
          $maxRand) 
{ 
    return floor((atan(random_0_1()) + atan(random_0_1())) * $maxRand/(pi()/2)) + $LowValue ; 
} // function sawWeightedRandom() 


function pyramidWeightedRandom($LowValue, 
           $maxRand) 
{ 
    return floor((random_0_1() + random_0_1())/2 * $maxRand) + $LowValue ; 
} // function pyramidWeightedRandom() 


function linearWeightedRandom($LowValue, 
           $maxRand) 
{ 
    return floor(random_0_1() * ($maxRand)) + $LowValue ; 
} // function linearWeightedRandom() 


function nonWeightedRandom($LowValue, 
          $maxRand) 
{ 
    return rand($LowValue,$maxRand+$LowValue-1) ; 
} // function nonWeightedRandom() 




function weightedRandom($Method, 
         $LowValue, 
         $maxRand) 
{ 
    switch($Method) { 
     case RandomGaussian   : 
      $rVal = gaussianWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomBell    : 
      $rVal = bellWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomGaussianRising : 
      $rVal = gaussianWeightedRisingRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomGaussianFalling : 
      $rVal = gaussianWeightedFallingRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomGamma   : 
      $rVal = gammaWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomGammaQaD   : 
      $rVal = QaDgammaWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomLogarithmic10 : 
      $rVal = logarithmic10WeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomLogarithmic  : 
      $rVal = logarithmicWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomPoisson   : 
      $rVal = poissonWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomDome    : 
      $rVal = domeWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomSaw    : 
      $rVal = sawWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomPyramid   : 
      $rVal = pyramidWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     case RandomLinear   : 
      $rVal = linearWeightedRandom($LowValue, $maxRand) ; 
      break ; 
     default      : 
      $rVal = nonWeightedRandom($LowValue, $maxRand) ; 
      break ; 
    } 

    return $rVal; 
} 

?> 
+0

코드를 보내 주셔서 감사합니다. 그러나, 나는 당신이 제공 한 모든 방법을 찾아 보았고, 나는 내 모델에 맞는 것을 보지 못했습니다. 통계는 결코 내 장점이 아니 었습니다. 당신이 맞는 모델이라고 지적 할 수 있다면, 나는 모든 귀가 될 것입니다 ... 감사합니다 ... – ircmaxell

+0

하나의 옵션은 일련의 값을 생성하고 각기 다른 값을 사용하여 그래프에 그려 보는 것입니다 정의 된 분포를 사용하여 곡선의 모양을 확인합니다. 위키 백과는 그 분포의 많은에 대한 광범위한 항목을 .....이 생각 (I 올바르게 해석 한 경우) 당신은 당신이 더 낮은 범위 값을 원하는 경우 더 상위 범위의 값을 원하는, 또는 gaussianWeightedFallingRandom 경우 gaussianWeightedRisingRandom을하려고 무엇을 설명합니다. .. poisson은 종종 많은 실제 상황에서 유용한 방법입니다. –

+0

좋아, 각각 시도했습니다. GaussianWeightedFallingRandom은 가장 근접하지만 여전히 충분히 빠르지 않습니다 (40이 5, 200이 10, 50이 10 대신 5700, 1000이 1 대신에 9500이 떨어집니다. CSH를 시도해 보았습니다. 가) 높은 범위와 일치하지만이 경우 중간. 생각? – ircmaxell

0

이렇게하는 순진한 방법은 현재 볼 수없는 방식으로 배포를 왜곡 할 것입니다. 아이디어는 단순히 첫 번째 데이터 집합을 정렬하고 쌍으로 반복하는 것입니다. 그런 다음 각 쌍 사이에 15 개의 새로운 숫자를 무작위로 배열하여 새 배열을 가져옵니다.

Ruby 예제는 PHP를 많이 사용하지 않기 때문에 가능합니다. PHP와 같은 간단한 개념으로 쉽게 번역 할 수 있기를 바랍니다.

numbers=[0.1,0.1,0.12,0.13,0.15,0.17,0.3,0.4,0.42,0.6,1,3,5,7,13,19,27,42,69] 
more_numbers=[] 
numbers.each_cons(2) { |a,b| 15.times { more_numbers << a+rand()*(b-a) } } 
more_numbers.sort! 
2

주어진 분포를 따르는 난수를 생성하는 가장 쉬운 (하지만 매우 효율적이지) 방법은 Von Neumann Rejection라는 기술이다.

기술의 간단한 explination이 없습니다. 배포본을 완전히 묶는 상자를 만듭니다. (배포판에 전화 하시려면 f) 상자에 임의의 지점 (x,y)을 선택하십시오. y < f(x) 인 경우 x을 임의의 숫자로 사용하십시오. y > f(x) 인 경우 xy을 모두 버리고 다른 점을 지정하십시오. 사용할 값이 충분할 때까지 계속하십시오. 거부하지 않는 x의 값은 f에 따라 배포됩니다.

+0

내가 잘못하지 않는 한,'f (x)'에 의해 정의 된 커브 아래 임의의 점을 얻는 것이 아닌가? 내 곡선이 쌍곡선으로 보일 때, 점의 가장 큰 밀도는 원점 주위에있을 것이므로 생성 된 숫자가 원점과 꼭지점 사이에 생성 된 바운딩 된 상자의 중간으로 왜곡되지는 않을 것입니다. 나는 그것을 필요로한다)? – ircmaxell