问题
正如 hpaulj 在 cmets 中指出的那样,您看到的 ValueError 是因为您的 p 参数包含在列表括号 [] 中。这个额外的封闭list 使np.random.choice 将您的p 解释为形状为(1, x) 的二维数组,而不是一维数组。由于np.random.choice 的第一个参数是一个整数,因此该函数期望p 是一维的,因此当它发现它不是一维时会抛出一个错误(有关完整的详细信息,请参阅choice docs)。
您可以通过删除p 周围的括号来修复ValueError:
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 的行。以下是如何修复代码中的切片,以便在 for 循环中迭代 mat 的行:
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)])
测试
为了证明现在正在生成正确的切片,我添加了一个打印语句,用于在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 列的数组,将二维x,y 索引转换为其扁平一维等效i 的通用公式是:
i = x + M*y
您可以在此old thread 中找到更深入的讨论。