numpy.random.choice
позволяет взвешенный выбор из вектора, то есть
arr = numpy.array([1, 2, 3])
weights = numpy.array([0.2, 0.5, 0.3])
choice = numpy.random.choice(arr, p=weights)
выбирает 1 с вероятностью 0,2, 2 с вероятностью 0,5 и 3 с вероятностью 0,3.
Что делать, если мы хотим сделать это быстро в векторном виде для 2D-массива (матрицы), для которого каждая из строк является вектором вероятностей? То есть, мы хотим вектор выбора из стохастической матрицы? Это очень медленный путь:
import numpy as np
m = 10
n = 100 # Or some very large number
items = np.arange(m)
prob_weights = np.random.rand(m, n)
prob_matrix = prob_weights / prob_weights.sum(axis=0, keepdims=True)
choices = np.zeros((n,))
# This is slow, because of the loop in Python
for i in range(n):
choices[i] = np.random.choice(items, p=prob_matrix[:,i])
print(choices)
:
array([ 4., 7., 8., 1., 0., 4., 3., 7., 1., 5., 7., 5., 3.,
1., 9., 1., 1., 5., 9., 8., 2., 3., 2., 6., 4., 3.,
8., 4., 1., 1., 4., 0., 1., 8., 5., 3., 9., 9., 6.,
5., 4., 8., 4., 2., 4., 0., 3., 1., 2., 5., 9., 3.,
9., 9., 7., 9., 3., 9., 4., 8., 8., 7., 6., 4., 6.,
7., 9., 5., 0., 6., 1., 3., 3., 2., 4., 7., 0., 6.,
3., 5., 8., 0., 8., 3., 4., 5., 2., 2., 1., 1., 9.,
9., 4., 3., 3., 2., 8., 0., 6., 1.])
Этот пост предполагает, что cumsum
и bisect
могут быть потенциальным подходом и быстро. Но в то время как numpy.cumsum(arr, axis=1)
может делать это вдоль одной оси массива numpy, функция bisect.bisect
работает только на одном массиве за раз, Аналогично, numpy.searchsorted
работает только с 1D-массивами.
Есть ли быстрый способ сделать это, используя только векторизованные операции?