2016-03-01 6 views
1

Моделирование, которое я выполняю, требует от меня рисования значений из распределения вероятности. Я делаю это следующим образом:Быстрая выборка из пользовательского дистрибутива

import numpy as np 
import scipy.special as sp 
from scipy.stats import rv_continuous 


class epsilon_pdf(rv_continuous): 

    def _pdf(self, x, omega): 

     return np.exp(omega ** -1 * np.cos(x))/(2 * np.pi * 
                sp.iv(0, omega ** -1)) 


random_epsilon = epsilon_pdf(a=-np.pi, b=np.pi) 
n_trials = 1 # 10 ** 6 
goal_dict = {'omega': 2 ** -4, 'xi': 2 ** 0} 
for trial_num in xrange(n_trials): 
    # Choose m. 
    m = np.random.poisson(goal_dict['xi']) 
    # Draw m values for epsilon. 
    epsilon_values = random_epsilon.rvs(omega=goal_dict['omega'], size=m) 

(Что написано выше, является минимальный пример игрушка.)

Основной проблемой я столкнулся в том, что вызов random_epsilon.rvs невероятно медленно - очень медленно что, когда я устанавливаю n_trials на нужный 10 ** 6, определенные значения omega и xi заставляют сценарий занять 377 часов.

Может ли кто-нибудь подумать о переформулировке кода Python моего распределения вероятности и моей выборке из него, которая была бы быстрее? (Может быть, есть способ сделать это с помощью NumPy, что будет быстрее?)

(я не уверен, является ли мое распределение является стандартным, что было дано имя.)

+1

Если ваш код работает, возможно, вы должны быть на http://www.codereview.stackexchange.com – zondo

+0

@zondo есть способ перенести это? – dbliss

+0

Я уверен, что есть способ, но я никогда этого не делал, поэтому я не мог сказать вам, как это сделать. – zondo

ответ

1
import numpy as np 
from scipy.stats import rv_continuous 
import scipy.special as sp 
import time 
from numpy import ma as ma 

class epsilon_pdf(rv_continuous): 
    def _pdf(self, x, omega): 
     return np.exp(omega ** -1 * np.cos(x))/(2 * np.pi * 
                sp.iv(0, omega ** -1)) 

random_epsilon = epsilon_pdf(a=-np.pi, b=np.pi) 
n_trials = 1000 # 10 ** 6 
goal_dict = {'omega': 2 ** -4, 'xi': 2 ** 0} 

random_epsilon_rvs = lambda x: random_epsilon.rvs(
    omega=goal_dict['omega'], 
    size = x 
    ) 

random_epsilon_rvs = np.vectorize(random_epsilon_rvs, otypes=[np.ndarray]) 

t0 = time.time() 
for trial_num in xrange(n_trials): 
    # Choose m. 
    m = np.random.poisson(goal_dict['xi']) 
    # Draw m values for epsilon. 
    epsilon_values = random_epsilon.rvs(omega=goal_dict['omega'], size=m) 

t1 = time.time() 
a = np.random.poisson(2**-4, size = (1, n_trials))[0] 
mask = a>0 
b = a[mask] 
c = random_epsilon_rvs(b) 

t2 = time.time() 

print t1-t0,t2-t1 
# 11.7730000019 vs 0.682999849319 
+0

, какая строка выбрасывает исключение? – dbliss

+0

и вы уверены, что это дает вам правильный результат? 'a' вы переходите к' random_epsilon_rvs' - это массив. моя догадка заключается в том, что вы получаете для 'b' - это массив N-D, где N равно числу элементов в' a'. это не то, что желательно, а не то, что дает код в моем вопросе. – dbliss

+0

У меня возникло желание вытащить 'random_epsilon.rvs' из цикла' for' параллельно вам, но для меня он делает * без разницы * для синхронизации. запрос 'size = m' из' random_epsilon.rvs' 'n' times в цикле 'for' эквивалентен для меня одновременным вызовом' random_epsilon.rvs' с 'size = (n, m)'. разве это не так? – dbliss