сделать random.choice из матрицы вероятностей - PullRequest
0 голосов
/ 09 декабря 2018

Я пытаюсь сделать симулятор входящих сообщений на выходные порты.Мне дано количество входных портов (N) и количество выходных портов (M) и сглаженная матрица вероятностей N * M (мат).Мне также дают количество входящих сообщений в виде массива (in_freq).Я решил, что для направления каждого сообщения с входного порта на выходной, я должен использовать numpy.random.choice, но мне не удалось заставить его работать.

Я попытался:

 for k in range (N):  
       enqueue = np.random.choice(M, in_freq[k], p=[(mat[k*N:k*N+M-1])])

, когда enqueue представляет собой массив адресатов сообщений.

Но обнаружилось сообщение:

ValueError: объект слишком глубокий для нужного массива

1 Ответ

0 голосов
/ 09 декабря 2018

Проблема

ValueError, который вы видите, как указал hpaulj в комментариях, из-за того, что ваш аргумент p заключен в скобки [].Это дополнительное вложение list заставляет np.random.choice интерпретировать ваш p как двумерный массив формы (1, x) вместо одномерного массива.Поскольку ваш первый аргумент np.random.choice является целым числом, функция ожидает, что p будет 1D, и поэтому выдает ошибку, когда видит, что это не так (подробные сведения см. В choice документах ).

Вы можете исправить это ValueError, просто сняв скобки вокруг p:

enqueue = np.random.choice(M, in_freq[k], p=mat[k*N:k*N+M-1])

Однако теперь ваш код будет вызывать новый и другой ValueError:

ValueError: a and p must have same size

Это ValueError вызвано тем фактом, что способ генерации срезов строк сглаженной матрицы NxM mat является неправильным.

Решение

Из описания в вашем вопросе кажется, что вы намеревались циклически перемещаться по строкам исходного 2D mat, разрезая 1D mat.Вот как вы можете исправить нарезку в своем коде, чтобы выполнять итерацию по строкам mat в цикле for:

import numpy as np

N = 10
M = 5

in_freq = np.random.randint(0, 10, N)
mat = np.random.rand(N, M)
# normalize so that each row is a probability dist
mat /= mat.sum(axis=1, keepdims=True)
# flatten to match OP's question
mat = mat.flat

for k in range(N):
    print((M*k, M*(k + 1)))
    enqueue = np.random.choice(M, in_freq[k], p=mat[M*k:M*(k + 1)])

Тестирование

Чтобы продемонстрировать, чтотеперь генерируются правильные срезы, я добавил оператор print, который выводит индексы срезов на каждой итерации цикла for.Вот результат этого:

(0, 5)
(5, 10)
(10, 15)
(15, 20)
(20, 25)
(25, 30)
(30, 35)
(35, 40)
(40, 45)
(45, 50)

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

Примечания по преобразованию двумерного индексак его 1D сглаженному эквиваленту

Для массива с N строками и M столбцами общая формула для преобразования 2D x,y индекса в его сглаженный 1D эквивалент i имеет вид:

i = x + M*y

Более подробное обсуждение можно найти в этой старой теме .

...