从概率矩阵中做出random.choice

时间:2018-12-09 17:19:39

标签: python numpy random

我正在尝试创建将传入消息输出到端口的模拟器。 我得到了输入端口的数量(N)和输出端口的数量(M)以及N * M的平坦矩阵(mat)。我还收到了作为数组的传入消息数(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])])

当入队消息的目的地数组时。

但是遇到了消息:

  

ValueError:对象太深,无法放入所需的数组

1 个答案:

答案 0 :(得分:1)

问题

正如hpaulj在评论中指出的那样,您看到的ValueError是由于您的p参数包装在列表括号[]中。这种list的额外包围使np.random.choicep解释为形状为(1, x)的2D数组,而不是1D数组。由于您对np.random.choice的第一个参数是整数,因此该函数期望p为一维,因此在发现不是{D1}时将引发错误(有关详细信息,请参见choice docs

您可以通过删除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的行切片的方式不正确。

解决方案

从您问题的描述中,您似乎想要通过切片1D mat来遍历原始2D 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的行所需的分片确实正在按预期生成。

关于将2D索引转换为其1D展平等效项的说明

给定一个具有N行和M列的数组,将2D x,y索引转换为平坦的1D等效项i的一般公式为:

i = x + M*y

您可以在此old thread中找到更深入的讨论。