Python 使用numpy创建大型随机布尔矩阵
我试图创建一个巨大的Python 使用numpy创建大型随机布尔矩阵,python,numpy,random,Python,Numpy,Random,我试图创建一个巨大的布尔矩阵,该矩阵随机填充真和假,概率为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.ra
布尔
矩阵,该矩阵随机填充真
和假
,概率为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行的生成速度非常快,但之后,代码变得非常慢。为什么会这样?我错过了什么?有没有更好的方法来创建一个大矩阵,其中包含概率p
的True
条目和概率1-p
的False
条目
编辑:很多人都认为RAM会有问题:因为运行代码的设备几乎有500GB的RAM,所以这不会是问题。问题是您的RAM,在创建时,这些值会存储在内存中。我刚刚使用以下命令创建了此矩阵:
np.random.choice(a=[False,True],size=(N,N),p=[p,1-p])
我使用了一个带有64GB RAM和8个内核的AWSI3实例。要创建此矩阵,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,其中函数方法保留所有RAM。另一种可能是成批生成RAM(即计算多个子数组并将它们堆叠在一起)。但是,不要考虑更新一个数组(<代码>掩码< /代码>)。这将迫使在每次索引更新期间将整个数组加载到主内存中 例如:要获得
30000x30000
,让9000个100x100
单独的数组,在for
循环中相应地更新每个100x100
数组,最后将这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)
因此,我尝试通过以下操作将其拆分为单行:
np.random.choice
的工作方式是首先在[0,1)
中为数据的每个单元格生成一个float64
,然后使用np.search\u sorted
将其转换为数组中的索引。这个中间表示比布尔数组大8倍
由于您的数据是布尔型的,因此使用
np.random.rand(N, N) > p
当然,您可以在循环解决方案中使用
似乎np.random.choice
可以在这里进行一些缓冲-您可能希望针对numpy提交一个问题
另一种选择是尝试生成
float32
s,而不是float64
s。我不确定numpy现在是否可以这样做,但您可以请求该功能。无法理解该部分-似乎不会因为这个大N
而终止。对此进行了澄清?为什么使用布尔数组但不设置数据类型?以及如果您的内存足够,请检查III。否则,垃圾处理会减慢每种方法的速度。一旦内存耗尽,它会减慢机器的速度?@Serge但为什么?我的意思是:我正在第3行创建NxN数组-因此没有理由让内存耗尽。此外,内存确实没有问题,因为机器中有很多内存-大约0.5 TB。@FlashTek:在你写之前,你的操作系统实际上不会把RAM分配给它。好吧,有趣的是,np.random.rand(N,N)的解决方案>p
是我的第一个想法,我放弃了这个想法,因为我认为直接numpy调用会更快。@FlashTek:问题是np.random.choice
需要做更多的工作,因为它必须处理两个以上结果的情况。当选择的数量是两个时,一定要考虑特殊情况。但是你知道为什么会这样吗在我的第一篇博文中发生了多少次减速?哪种减速?你第二次尝试的速度更快的原因是因为你没有一次分配所有的浮动,而且它们比你的最终结果大得多。不,我是说第二次尝试的减速发生在第1100行生成之后-如上所述。