2014-04-21 58 views
0

我使用np.random.multinomial採樣多項分佈M時間(按給出的概率[X_0 X_1 .. X_n]它返回從指定的多項式採樣計數[C_0 C_1 ... C_n],其中\sum_i C_i = M)。給定這些採樣值(C_i's),我想隨機將它們均勻分配給我擁有的某些對象。分配採樣多項式值均勻地隨機

目前我在做什麼是:

draws = np.random.multinomial(M, probs, size=1) 
draws = draws[0] 
draws_list = [] 
for idx,num in enumerate(draws): 
    draws_list += [idx]*num 
random.shuffle(draws_list) 

然後draws_list是採樣值的隨機洗牌的名單。

的問題是,填充draws_list(for循環)是很慢的。有沒有更好/更快的方法來做到這一點?

回答

1

試試看看這個代碼。這個策略是先分配內存,然後填充數據。

draws_list1 = np.empty(M, dtype=np.int) 
acc = 0 
for idx, num in enumerate(draws): 
    draws_list1[acc:acc+num].fill(idx) 
    acc += num 

下面是分析的完整代碼。

import numpy as np 
import cProfile 

M=10000000 

draws = np.random.multinomial(M, [1/6.]*6, size=1) 
draws = draws[0] 

draws_list1 = np.empty(M, dtype=np.int) 

def impl0(): 
    draws_list0 = [] 
    for idx, num in enumerate(draws): 
     draws_list0 += [idx]*num 
    return draws_list0 

def impl1(): 
    acc = 0 
    for idx, num in enumerate(draws): 
     draws_list1[acc:acc+num].fill(idx) 
     acc += num 
    return draws_list1 

cProfile.run("impl0()") 
cProfile.run("impl1()") 

這裏是cProfile結果。如果語句np.empty位於功能impl10.020 seconds都過去了。

 3 function calls in 0.095 seconds 

Ordered by: standard name 

ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.020 0.020 0.095 0.095 <string>:1(<module>) 
     1 0.076 0.076 0.076 0.076 prof.py:11(impl0) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 


     9 function calls in 0.017 seconds 

Ordered by: standard name 

ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.017 0.017 <string>:1(<module>) 
     1 0.000 0.000 0.017 0.017 prof.py:17(impl1) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     6 0.017 0.003 0.017 0.003 {method 'fill' of 'numpy.ndarray' objects}