0

我有一个二进制 numpy 矩阵,我想随机关闭 30% 的矩阵,其中关闭 30% 意味着用 0 替换 30% 的 1。一般来说,我想这样做很多次,所以如果我这样做 5 次,我希望最终矩阵有 100*(1-0.3)^5 = 16% 的原始矩阵,最初都是 1。

重要的是我想关闭 30% 的活动位(一),而不是关闭整个矩阵的 30%(一和零,关闭零只是零)。

我想出了一个方法来做到这一点,但它似乎没有实现上述目标,因为在关闭 30% 的 5 个会话之后,矩阵是 23% 1s 而不是 16% 1s。

为了通过示例进行说明,我的方法如下:

>>> mask=np.array([[1,1,1,1,1],[1,1,1,0,0],[1,1,0,0,0]])
>>> mask
array([[1, 1, 1, 1, 1],
       [1, 1, 1, 0, 0],
       [1, 1, 0, 0, 0]])
>>> np.where(mask==0, np.zeros_like(mask), mask * np.random.binomial(1, 0.7, mask.shape))
array([[1, 1, 1, 0, 0],
       [0, 1, 1, 0, 0],
       [1, 1, 0, 0, 0]])

上面的代码给出了一个新矩阵,如果一个位为 0,则保持为 0,如果为 1,则在 30% 的时间内关闭。

在这个小例子中,一切似乎都很好,因为我已经删除了 30% 的那些(我有 10 个,现在我有 7 个)。但我认为我的方法不能很好地推广到大型矩阵。我相信这是由于以下原因:

尽管 Bernoulli 试验应该是相互独立的,但 numpy 可能会试图确保总体而言,所有试验中有 30% 是 Tails。但是在我的代码中,“所有试验”等于整个矩阵的大小,而不是矩阵中的数量,这就是导致问题的原因。

什么是清除 30% 的活动位而不是 30% 的所有位的一种干净的 Python 方式?

4

1 回答 1

0

看来我想通了。基本上,我创建了一个相同大小的新零矩阵,我只编辑初始矩阵为 1 的字段,执行伯努利试验的次数是初始矩阵中 1 的数量,而不是完整的矩阵的大小,根据需要。

>>> mask=np.array([[1,1,1,1,1],[1,1,1,0,0],[1,1,0,0,0]])
>>> new_mask = np.zeros_like(mask)
>>> new_mask[mask==1] = np.random.binomial(1,0.7,mask[mask==1].shape)* mask[mask==1]
>>> new_mask
array([[0, 1, 0, 1, 1],
       [1, 1, 1, 0, 0],
       [1, 0, 0, 0, 0]])

这适用于大型矩阵,它确实给了我约 16% 1s 的最终大小(有关上下文,请参阅问题正文)。

于 2020-07-24T21:05:30.853 回答