我需要在不命中交换的情况下创建一个包含随机布尔值的大型numpy数组。
我的笔记本电脑有8 GB的内存。创建一个(1200, 2e6)
阵列只需不到2秒,使用2.29 GB内存:
>>> dd = np.ones((1200, int(2e6)), dtype=bool)
>>> dd.nbytes/1024./1024
2288.818359375
>>> dd.shape
(1200, 2000000)
对于相对较小的(1200, 400e3)
,np.random.randint
仍然相当快,大约需要5秒来生成一个458MB的数组:
db = np.array(np.random.randint(2, size=(int(400e3), 1200)), dtype=bool)
print db.nbytes/1024./1024., 'Mb'
但是如果我将数组的大小加倍到(1200, 800e3)
,那么就会遇到交换,创建db
需要大约2.7分钟;(
cmd = """
import numpy as np
db = np.array(np.random.randint(2, size=(int(800e3), 1200)), dtype=bool)
print db.nbytes/1024./1024., 'Mb'"""
print timeit.Timer(cmd).timeit(1)
使用random.getrandbits
需要更长的时间(~8分钟),并且还使用交换:
from random import getrandbits
db = np.array([not getrandbits(1) for x in xrange(int(1200*800e3))], dtype=bool)
对(1200, 2e6)
使用np.random.randint
只会给出一个MemoryError
。
有没有更有效的方法来创建(1200, 2e6)
随机布尔数组?
发布于 2015-12-28 07:24:29
使用np.random.randint
的一个问题是它会生成64位整数,而numpy的np.bool
dtype只使用8位来表示每个布尔值。因此,您将分配一个比所需大8倍的中间数组。
避免中间64位数据类型的一种解决方法是使用np.random.bytes
生成随机字节字符串,该字符串可以使用np.fromstring
转换为8位整数数组。然后,可以将这些整数转换为布尔值,例如,通过测试它们是否小于255 * p,其中p是每个元素为True
的期望概率
import numpy as np
def random_bool(shape, p=0.5):
n = np.prod(shape)
x = np.fromstring(np.random.bytes(n), np.uint8, n)
return (x < 255 * p).reshape(shape)
基准:
In [1]: shape = 1200, int(2E6)
In [2]: %timeit random_bool(shape)
1 loops, best of 3: 12.7 s per loop
一个重要的警告是,概率将向下舍入到最接近的1/256的倍数(对于1/256的精确倍数,如p=1/2,这不应影响准确性)。
更新:
一种更快的方法是利用这样一个事实,即您只需要在输出数组中为每个0或1生成一个随机位。因此,您可以创建一个8位整数的随机数组,该数组的大小是最终输出的1/8,然后使用np.unpackbits
将其转换为np.bool
def fast_random_bool(shape):
n = np.prod(shape)
nb = -(-n // 8) # ceiling division
b = np.fromstring(np.random.bytes(nb), np.uint8, nb)
return np.unpackbits(b)[:n].reshape(shape).view(np.bool)
例如:
In [3]: %timeit fast_random_bool(shape)
1 loops, best of 3: 5.54 s per loop
https://stackoverflow.com/questions/34485591
复制相似问题