Являются ли случайные числа с биномиальными числами неэффективными? - PullRequest
0 голосов
/ 03 мая 2019

Я выбирал случайные числа из разных распределений и только что понял, насколько медленными являются случайные двоичные случайные числа по сравнению с другими распределениями. Например

%timeit for x in range(100): np.random.binomial(100,0.5)
10000 loops, best of 3: 82.6 µs per loop
%timeit for x in range(100): np.random.uniform()
100000 loops, best of 3: 14.6 µs per loop

Биномиальное число занимает в 6 раз больше, чем однозначное! Это может быть понятно, поскольку биномиальное представление дискретно и требует более сложного преобразования. Но, например, если я попрошу бином с количеством испытаний n = 0 или n = 1, то затраченное время будет примерно таким же:

%timeit for x in range(100): np.random.binomial(0,0.5)
10000 loops, best of 3: 78.8 µs per loop

%timeit for x in range(100): np.random.binomial(1,0.5)
10000 loops, best of 3: 80.1 µs per loop

Это не кажется очень эффективным, потому что результат этих выборок должен быть тривиальным: для нулевых испытаний результаты должны быть всегда нулевыми, а для 1 испытания это должно быть простое испытание Бернулли. Так, например, более быстрая реализация бинома будет:

import numpy as np

def custombinomial(n,p):
    if n == 0:
        return 0
    if n == 1:
        x = np.random.uniform()
        if x<p:
            return 1
        else:
            return 0  
    else:
        return np.random.binomial()

А вот время:

%timeit for x in range(100): custombinomial(0,0.5)
100000 loops, best of 3: 11.8 µs per loop

 %timeit for x in range(100): custombinomial(1,0.5)
10000 loops, best of 3: 31.2 µs per loop

Я уверен, что это можно улучшить для еще больших значений n. Есть ли какая-то причина, по которой я скучаю из-за такой медлительности? Есть ли какая-либо другая библиотека, которая может выдавать более быстрые случайные числа (даже если она включает в себя какой-то C / Cython)?

Кроме того, я знаю, что numpy хорош, если я хочу создать группу случайных чисел одновременно, то есть получить массив биномиально распределенных чисел, но во многих случаях параметры распределения n и p изменятся на лету, поэтому вызов отдельных случайных чисел не будет прямым вариантом. Возможна ли альтернатива, в которой генерируется массив равномерно распределенных случайных чисел, которые преобразуются в конкретные биномы по мере необходимости?.

1 Ответ

1 голос
/ 04 мая 2019

Биномиальный генератор случайных чисел Numpy реализован в C , и алгоритм использует числовую инверсию, если параметры достаточно малы.Это может быть слишком большой работой, если p = 0.5, так как вместо бинарного генератора можно было использовать случайные биты, а не случайные double s.Кроме того, кажется, что основной алгоритм не менялся годами (см. Также mtrand.pyx), поэтому он не использует, например, векторизацию или многопоточность.

Более того, в первые годы существования Numpy не было «особых причин так сильно менять методы распределения», так что этот и другие алгоритмы генерации случайных чисел в Numpy были сохранены во имя воспроизводимой «случайности».Однако ожидается, что изменится , если это еще не произошло: теперь разрешены критические изменения в методах генерации случайных чисел, таких как новый биномиальный алгоритм случайных чисел, но они рассматриваются как новые функции, которые будут введенытолько "на X.Y выпусках, никогда X.Y.Z".Если для вас важны более быстрые биномиальные случайные числа, вы должны подать новый Numpy выпуск .

...