Кажется, что вы можете сделать немного быстрее, используя равномерную выборку, а затем "инвертировать" кумулятивное искажение, используя np.searchsorted
:
# assume arbitrary probabilities
weights = np.random.randn(1000)**2
weights /= weights.sum()
def weighted_random(w, n):
cumsum = np.cumsum(w)
rdm_unif = np.random.rand(n)
return np.searchsorted(cumsum, rdm_unif)
# first method
%timeit np.random.choice(a = 1000, size = 1000, replace = True, p = weights)
# 10000 loops, best of 3: 220 µs per loop
# proposed method
%timeit weighted_random(weights, n)
# 10000 loops, best of 3: 158 µs per loop
Теперь мы можем эмпирически проверить, что вероятности верны:
samples =np.empty((10000,1000),dtype=int)
for i in xrange(10000):
samples[i,:] = weighted_random(weights)
empirical = 1. * np.bincount(samples.flatten()) / samples.size
((empirical - weights)**2).max()
# 3.5e-09