numpy 生成约束为无空行的随机二进制矩阵

kxxlusnw  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(119)

我想生成一个随机的二进制矩阵,所以我使用W=np.random.binomial(1, p, (n,n)),它运行得很好,但是我需要一个约束,即没有一行是0。
我创建以下函数:

def random_matrix(p,n):
    m=0
    while m==0:
        W = np.random.binomial(1, p, (n,n))
        m=min(W.sum(axis=1))
    return W

它也工作得很好,但在我看来效率太低了。有没有更快的方法来创建这个约束?

0md85ypi

0md85ypi1#

一种使生成不包含仅为0的行的随机二进制矩阵的过程更有效的方法是使用np.random.choice函数从矩阵的每行随机选择非零项并将其值设置为1。这避免了使用while循环和重复检查仅为0的行的需要,对于大型矩阵,这可能会导致计算开销很大。
下面是一个示例,说明如何使用np.random.choice函数生成一个随机二进制矩阵,其中没有只包含0的行:

W = np.random.binomial(1, p, (n,n))
for row in W:
    nonzero_indices = np.where(row != 0)[0]
    if nonzero_indices.size == 0:
        random_index = np.random.randint(0, n)
        row[random_index] = 1
    else:
        random_index = np.random.choice(nonzero_indices)
        row[random_index] = 1
jv2fixgn

jv2fixgn2#

当矩阵很大时,仅因为少数数据列全是零,就重新产生整个矩阵的效率并不高。只重新产生目的数据列,在统计上应该是安全的。范例如下:

def random_matrix(p,n):
    W = np.random.binomial(1, p, (n,n))

    while True:
        null_rows = np.where(W.sum(axis=1) == 0)[0]
        # If there is no null row, then m>0 so we stop the replacement
        if null_rows.size == 0:
            break
        # Replace only the null rows
        W[null_rows] = np.random.binomial(1, p, (null_rows.shape[0],n))

    return W

更快的解决方案

p接近0时,有一种更有效的方法(当p接近1时,则上述函数已经是快的)。实际上,具有0-1个值的二项式随机变量是伯努利随机变量。具有概率p的伯努利随机值重复多次的和是二项式随机值!因此,您可以使用S = np.random.binomial(n, p, (n,n))生成所有行的总和,然后应用上述方法来去除空值,然后通过为第i行生成x1M3 N1 x1值并使用x1M4 N1 x50来随机化每行中0-1值的顺序来构建最终矩阵。这种方法解决冲突的效率比其他所有方法都要高得多。实际上,它不需要生成整行来检查它是否充满零。解决冲突的速度快了n倍!
如果这还不够,可以使用uint8数据类型来生成W。实际上,内存很慢,所以生成较小的矩阵通常更快,更不用说它占用的RAM更少。
如果这还不够,你可以使用Numba JIT编译器和一个基本循环为每个项目生成S个项目。这应该会更快,因为除了最后一个,没有临时数组要创建。对于大型矩阵,这个算法甚至可以并行化(每行都可以独立生成)。最后一个解决方案应该接近最优。

相关问题