使用numpy创建大型随机布尔矩阵

时间:2017-04-20 19:49:06

标签: python numpy random

我正在尝试创建一个巨大的boolean矩阵,该矩阵随机填充TrueFalse,给定概率为p。起初我使用了这段代码:

N = 30000
p = 0.1
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])  

但遗憾的是,似乎没有终止这个大N。所以我尝试通过这样做将它分成单行的生成:

N = 30000
p = 0.1
mask = np.empty((N, N))
for i in range (N):
     mask[i] = np.random.choice(a=[False, True], size=N, p=[p, 1-p])            
     if (i % 100 == 0):
          print(i)

现在发生了一些奇怪的事情(至少在我的设备上):第一个~1100行非常快速地生成 - 但在它之后,代码变得非常慢。为什么会这样?我在这里想念什么?有没有更好的方法来创建一个大型矩阵,其中True个条目的概率pFalse条目的概率为1-p

编辑:你们很多人都认为RAM会出现问题:由于运行代码的设备有近500GB的RAM,这不会成为问题。

3 个答案:

答案 0 :(得分:9)

问题在于你的RAM,这些值在创建时存储在内存中。我刚用这个命令创建了这个矩阵:

np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])

我使用了一个带有64GB RAM和8个内核的AWS i3实例。要创建此矩阵,htop表明它占用了大约20GB的RAM。如果您关心,这是一个基准:

time np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])

CPU times: user 18.3 s, sys: 3.4 s, total: 21.7 s
Wall time: 21.7 s


 def mask_method(N, p):
    for i in range(N):
        mask[i] = np.random.choice(a=[False, True], size=N, p=[p, 1-p])
        if (i % 100 == 0):
            print(i)

time mask_method(N,p)

CPU times: user 20.9 s, sys: 1.55 s, total: 22.5 s
Wall time: 22.5 s

请注意,掩码方法在其峰值时仅占用约9GB的RAM。

编辑:第一个方法在完成该过程后刷新RAM,其中函数方法保留所有内容。

答案 1 :(得分:4)

  

所以我尝试通过这样做将它分成单行的生成:

np.random.choice的工作方式是首先在float64为数据的每个单元格生成[0, 1),然后使用{{1}将其转换为数组中的索引}。这个中间表示比布尔数组大8倍!

由于您的数据是布尔值,因此您可以使用

获得两倍的加速
np.search_sorted

当然,您可以在循环解决方案中使用

似乎np.random.rand(N, N) > p 可以在这里进行一些缓冲 - 您可能想要针对numpy提出问题。

另一种选择是尝试生成np.random.choice而不是float32 s。我不确定numpy现在是否能做到这一点,但你可以请求这个功能。

答案 2 :(得分:0)

另一种可能性是批量生成它(即计算许多子阵列并在最后将它们堆叠在一起)。但是,考虑不要像OP那样在mask循环中更新一个数组(for)。这将强制整个数组在每次索引更新期间加载到主内存中。

取而代之的是:获取30000x30000,拥有9000个100x100个独立数组,在100x100循环中相应地更新每个for数组,最后堆叠这9000个数组在一个巨大的阵列中。这绝对不需要超过4GB的RAM,也会非常快。

最小例子:

In [9]: a
Out[9]: 
array([[0, 1],
       [2, 3]])

In [10]: np.hstack([np.vstack([a]*5)]*5)
Out[10]: 
array([[0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
       [2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
       [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
       [2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
       [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
       [2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
       [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
       [2, 3, 2, 3, 2, 3, 2, 3, 2, 3],
       [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
       [2, 3, 2, 3, 2, 3, 2, 3, 2, 3]])

In [11]: np.hstack([np.vstack([a]*5)]*5).shape
Out[11]: (10, 10)