我需要为特定的神经网络生成用于辍学的掩码。 我正在寻找使用numpy(仅限CPU)实现此目标的最快方法。
我尝试过:
def gen_mask_1(size, p=0.75):
return np.random.binomial(1, p, size)
def gen_mask_2(size, p=0.75):
mask = np.random.rand(size)
mask[mask>p]=0
mask[mask!=0]=1
return mask
其中p
是拥有1
这两种方法的速度可比。
%timeit gen_mask_1(size=2048)
%timeit gen_mask_2(size=2048)
45.9 µs ± 575 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
47.4 µs ± 372 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
有更快的方法吗?
更新
按照到目前为止的建议,我测试了一些额外的实现。设置@njit
(parallel=True
)时,我无法运行TypingError: Failed in nopython mode pipeline (step: convert to parfors)
,但是如果没有,它的效率就会降低。
我在这里找到了与英特尔mlk_random
的Python绑定(感谢@MatthieuBrucher的提示!):https://github.com/IntelPython/mkl_random
到目前为止,结合使用mlk_random和@nxpnsv的方法可获得最佳效果。
@njit
def gen_mask_3(size, p=0.75):
mask = np.random.rand(size)
mask[mask>p]=0
mask[mask!=0]=1
return mask
def gen_mask_4(size, p=0.75):
return (np.random.rand(size) < p).astype(int)
def gen_mask_5(size):
return np.random.choice([0, 1, 1, 1], size=size)
def gen_mask_6(size, p=0.75):
return (mkl_random.rand(size) < p).astype(int)
def gen_mask_7(size):
return mkl_random.choice([0, 1, 1, 1], size=size)
%timeit gen_mask_4(size=2048)
%timeit gen_mask_5(size=2048)
%timeit gen_mask_6(size=2048)
%timeit gen_mask_7(size=2048)
22.2 µs ± 145 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
25.8 µs ± 336 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
7.64 µs ± 133 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
29.6 µs ± 1.18 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
答案 0 :(得分:2)
您可以使用Numba编译器,并通过在函数上应用njit
装饰器来加快处理速度。以下是一个非常大的size
from numba import njit
def gen_mask_1(size, p=0.75):
return np.random.binomial(1, p, size)
@njit(parallel=True)
def gen_mask_2(size, p=0.75):
mask = np.random.rand(size)
mask[mask>p]=0
mask[mask!=0]=1
return mask
%timeit gen_mask_1(size=100000)
%timeit gen_mask_2(size=100000)
2.33 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
512 µs ± 25.1 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
答案 1 :(得分:2)
另一个选项是numpy.random.choice
,输入0和1s,其中1s的比例为p
。例如,对于p
= 0.75,请使用np.random.choice([0, 1, 1, 1], size=n)
:
In [303]: np.random.choice([0, 1, 1, 1], size=16)
Out[303]: array([1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0])
这比使用np.random.binomial
更快:
In [304]: %timeit np.random.choice([0, 1, 1, 1], size=10000)
71.8 µs ± 368 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [305]: %timeit np.random.binomial(1, 0.75, 10000)
174 µs ± 348 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
要处理p
的任意值,可以使用p
的{{1}}选项,但是代码比np.random.choice
慢:
np.random.binomial
答案 2 :(得分:1)
正如我在评论中说的,问题是实现
def gen_mask_2(size, p=0.75):
mask = np.random.rand(size)
mask[mask>p]=0
mask[mask!=0]=1
return mask
通过比较,可以改善,得到一个bool
,然后可以将其转换为int
。这会删除您原本拥有的带有掩盖分配的两个比较,并且只需要一个衬里即可:)
def gen_mask_2(size, p=0.75):
return = (np.random.rand(size) < p).astype(int)