Nano Hash - криптовалюты, майнинг, программирование

Генерация случайных чисел с вероятностным распределением

Хорошо, вот и моя проблема. Мы планируем приобрести набор данных у компании, чтобы расширить существующий набор данных. Для целей этого вопроса предположим, что этот набор данных ранжирует места с органическим номером (это означает, что номер, присвоенный одному месту, не имеет отношения к номеру, назначенному другому). Технический диапазон составляет от 0 до бесконечности, но из наборов образцов, которые я видел, от 0 до 70. Судя по выборке, это определенно не равномерное распределение (из 10 000 может быть 5 мест с оценкой более 40, 50 с оценкой более 10 и 1000 с оценкой более 1). Прежде чем мы решим приобрести этот набор, мы хотели бы смоделировать его, чтобы увидеть, насколько он может быть полезен.

Итак, чтобы смоделировать это, я подумал о создании случайного числа для каждого места (около 150 000 случайных чисел). Но я также хочу придерживаться духа данных и сохранять относительно одинаковое распределение (или, по крайней мере, достаточно близкое). Я весь день ломал себе голову, пытаясь придумать, как это сделать, и ничего не вышло.

Одна мысль, которая у меня возникла, заключалась в том, чтобы возвести случайное число в квадрат (от 0 до sqrt (70)). Но это будет благоприятствовать как числам меньше 1, так и большим.

Я думаю, что его реальное распределение должно быть гиперболическим в первом квадранте ... Я просто не понимаю, как превратить линейное, равномерное распределение случайных чисел в гиперболическое распределение (если гиперболическое - это даже то, что я хочу в первом квадранте). место).

Есть предположения?

Итак, подведем итог, вот распределение, которое я хотел бы (приблизительно):

  • 40 - 70: 0.02% - 0.05%
  • 10 - 40: 0.5% - 1%
  • 1 - 10: 10% - 20%
  • 0 - 1: остаток (78,95% - 89,48%)

  • Я нашел этот статистический глоссарий [stats.gla.ac.uk/ шаги / глоссарий /]. Это может помочь. 24.06.2010
  • Я не совсем понимаю. У вас есть 10 тыс. Чисел с плавающей запятой от 0 до 70, которые вы хотите распределить по набору из 150 тыс.? 24.06.2010
  • @Jonas Elfström: Ну, наоборот. Я хочу сгенерировать 150 тыс. Случайных чисел с плавающей запятой с указанным распределением ... 24.06.2010

Ответы:


1

Посмотрите на распределения, используемые при анализе надежности - они, как правило, имеют длинные хвосты. Относительно простой вариант - это распределение Вейбулла с 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, что разумно.

РЕДАКТИРОВАТЬ О, и чтобы сгенерировать случайную величину, распределенную по Вейбуллу, из равномерного (0,1) значения U, просто вычислите b * [- log (1-u)] ^ (1 / a). Это функция, обратная 1-P (X> x) на случай, если я что-то просчитал.

24.06.2010
  • Вау, это выглядит почти идентично результирующему набору, который мне нужен (4 ›40, 60› 10, 1030 ›1). Отлично! Спасибо! 24.06.2010
  • Есть ли шанс обновить свой ответ рабочим кодом PHP? 12.03.2020

  • 2

    Написано много лет назад для 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;
    }
    
    ?>
    
    24.06.2010
  • Спасибо за код. Однако я попытался найти все предложенные вами методы и не нашел ни одного, подходящего для моей модели. Статистика никогда не была моей сильной стороной. Если бы вы могли указать на модель, которая, по вашему мнению, может подойти, я бы все уши ... Спасибо ... 24.06.2010
  • Один из вариантов - попытаться создать серию значений и нанести их на график с использованием каждого из различных предопределенных распределений, чтобы увидеть, как выглядят кривые. В Википедии также есть обширные записи о многих из этих дистрибутивов ... хотя для того, что вы описываете (если я правильно интерпретировал), попробуйте gaussianWeightedRisingRandom, если вам нужны более высокие значения диапазона, или gaussianWeightedFallingRandom, если вы хотите более низкие значения диапазона. .. хотя метод Пуассона часто бывает полезным во многих реальных ситуациях. 24.06.2010
  • Хорошо, я пробовал каждую. GaussianWeightedFallingRandom наиболее близок, но он все еще не падает достаточно быстро (200 вместо 5 на 40, 5700 вместо 50 на 10 и 9500 вместо 1000 на 1. Я пробовал csch, и он выглядит намного ближе ( так как он соответствует высоким диапазонам), но слишком быстро падает в середине. 24.06.2010
  • В этом случае попробуйте использовать gaussianWeightedRandom ($ LowValue, $ maxRand, $ mean, $ stddev), но задав свои собственные значения для среднего и стандартного отклонения, или измените вызов gauss () в GaussianWeightedFallingRandom (), чтобы вызвать gauss_ms ($ mean , $ stddev) с вашими собственными значениями среднего и стандартного отклонения. Это может потребовать некоторых экспериментов ... но посмотрите на страницу википедии, чтобы увидеть, как изменения этих параметров влияют на форму кривой. 24.06.2010
  • @MarkBaker Отличный ресурс !! Я вижу, что сообщение уже довольно старое, но могу ли я спросить, не может ли дискретная функция распределения, основанная на эмпирических данных, быть лучше, чем теоретическая функция здесь? 30.04.2014
  • @ hek2mgl - Если бы я писал это сейчас, я бы сделал это совсем по-другому 30.04.2014

  • 3

    Самый простой (но не очень эффективный) способ генерировать случайные числа, соответствующие заданному распределению, - это метод, называемый Фон Нейман. Отклонение.

    Простое объяснение техники таково. Создайте коробку, полностью закрывающую ваш дистрибутив. (позвольте назвать ваш дистрибутив f) Затем выберите случайную точку (x,y) в поле. Если y < f(x), используйте x как случайное число. Если y > f(x), отбросьте и x, и y и выберите другую точку. Продолжайте, пока у вас не будет достаточного количества значений для использования. Значения x, которые вы не отклоняете, будут распределены в соответствии с f.

    24.06.2010
  • Если я не ошибаюсь, разве это не случайные точки под кривой, определенной f(x)? Учитывая, что моя кривая выглядит гиперболической, наибольшая плотность точек будет вокруг начала координат, поэтому сгенерированные числа не будут смещены в сторону середины ограниченного прямоугольника, созданного между началом координат и вершиной (и, следовательно, не будут отдавать предпочтение меньшим числам как Мне это нужно)? 24.06.2010

  • 4

    Такой наивный способ сделать это, скорее всего, исказит дистрибутив так, как я сейчас не вижу. Идея состоит в том, чтобы просто перебрать ваш первый набор данных, отсортированных и попарно. Затем рандомизируйте 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!
    
    24.06.2010
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..