zim*_*rol 18 python random numpy
我正在尝试创建一个boolean随机填充True并False具有给定概率的巨大矩阵p.起初我使用了这段代码:
N = 30000
p = 0.1
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
Run Code Online (Sandbox Code Playgroud)
但遗憾的是,它似乎并没有因此而终止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)
Run Code Online (Sandbox Code Playgroud)
现在发生了一些奇怪的事情(至少在我的设备上):第一个~1100行非常快速地生成 - 但在它之后,代码变得非常慢.为什么会这样?我在这里想念什么?有没有更好的方法来创建它有一个很大的矩阵True的概率条目p和False条目的概率1-p?
编辑:你们许多人都认为RAM会出现问题:由于运行代码的设备有近500GB的RAM,这不会有问题.
Ben*_*Ben 12
真的很惊讶还没有人提到这个解决方案..
这条线
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
Run Code Online (Sandbox Code Playgroud)
运行 NXN伯努利试验。(在你的例子中,有 900M!)伯努利试验只是一个随机实验,有两种可能的结果,概率为 p 和 1-p。
N 个伯努利试验的总和(每个试验的概率为 p)可以通过二项式分布建模。
我们可以利用这个事实来随机模拟 True 元素的总数。使用 NumPy,
import numpy as np
N = 30000
p = 0.1
# Build a random number generator
rng = np.random.default_rng(123)
# Randomly determine the total number of True values
Ntrue = rng.binomial(n=N*N, p=p, size=1)[0] # 90016776
Run Code Online (Sandbox Code Playgroud)
现在我们可以通过随机选择 row 和 col 索引而不需要放回来随机确定每个 True 元素的位置。
# Randomly determine true position
position_ids = rng.choice(a=N*N, size=Ntrue, replace=False)
positions = np.unravel_index(position_ids, shape=(N,N))
Run Code Online (Sandbox Code Playgroud)
现在我们可以填充压缩稀疏行(CSR)矩阵。
from scipy import sparse
# Build a compressed sparse row matrix with the constructor:
# csr_matrix((data, (row_ind, col_ind)), [shape=(M, N)])
result = sparse.csr_matrix((np.ones(shape=Ntrue), positions), shape=(N,N))
Run Code Online (Sandbox Code Playgroud)
请注意,此解决方案避免存储和计算900M 布尔值。
有趣的是,在偶然发现这个问题之前,我写了一个几乎相同的问题。
aws*_*ice 10
问题是你的RAM,这些值在创建时存储在内存中.我刚用这个命令创建了这个矩阵:
np.random.choice(a=[False, True], size=(N, N), p=[p, 1-p])
我使用了AWS i364GB RAM和8个内核的实例.要创建此矩阵,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
Run Code Online (Sandbox Code Playgroud)
请注意,掩码方法在其峰值时仅占用约9GB的RAM.
编辑:第一个方法在完成该过程后刷新RAM,其中函数方法保留所有内容.
因此,我尝试通过执行以下操作将其拆分为单行的生成:
有效的方法np.random.choice是,首先为数据的每个单元生成一个float64in [0, 1),然后使用将其转换为数组中的索引np.search_sorted。这个中间表示比布尔数组大8倍!
由于您的数据是布尔值,因此您可以将速度提高两倍
np.random.rand(N, N) > p
Run Code Online (Sandbox Code Playgroud)
自然地,您可以在循环解决方案中使用
似乎np.random.choice可以在此处进行一些缓冲-您可能要针对numpy提出问题。
另一种选择是尝试生成float32s而不是float64s。我不确定numpy是否可以立即执行此操作,但是您可以请求该功能。
| 归档时间: |
|
| 查看次数: |
11954 次 |
| 最近记录: |