矩阵上的快速 numpy 行切片
Fast numpy row slicing on a matrix
我有以下问题:我有一个大小为 (m,200)
(m = 3683
) 的矩阵 yj
,并且我有一个字典,每个键 returns yj
的一个 numpy 行索引数组(对于每个键,大小数组都会改变,以防万一有人想知道)。
现在,我必须多次访问此矩阵(大约 100 万次),并且由于索引编制,我的代码速度变慢了(我分析了代码,这一步花费了 65% 的时间)。
这是我试过的:
- 首先,使用索引进行切片:
>> %timeit yj[R_u_idx_train[1]]
10.5 µs ± 79.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
变量R_u_idx_train
是具有行索引的字典。
- 我认为布尔索引可能会更快:
>> yj[R_u_idx_train_mask[1]]
10.5 µs ± 159 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
R_u_idx_train_mask
是一个字典,returns 一个大小为 m
的布尔数组,其中 R_u_idx_train
给出的索引设置为 True。
- 我也试过了
np.ix_
>> cols = np.arange(0,200)
>> %timeit ix_ = np.ix_(R_u_idx_train[1], cols); yj[ix_]
42.1 µs ± 353 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
- 我也试过了
np.take
>> %timeit np.take(yj, R_u_idx_train[1], axis=0)
2.35 ms ± 88.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
虽然这看起来很棒,但事实并非如此,因为它给出了一个形状为 (R_u_idx_train[1].shape[0], R_u_idx_train[1].shape[0])
的数组(它应该是 (R_u_idx_train[1].shape[0], 200)
)。我想我没有正确使用该方法。
- 我也试过了
np.compress
>> %timeit np.compress(R_u_idx_train_mask[1], yj, axis=0)
14.1 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
- 最后我尝试使用布尔矩阵进行索引
>> %timeit yj[R_u_idx_train_mask2[1]]
244 µs ± 786 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
那么,10.5 µs ± 79.7 ns per loop
我能做到最好吗?我可以尝试使用 cython
但这似乎只是索引的很多工作...
非常感谢。
V.Ayrat在评论中给出了一个非常聪明的解决方案。
>> newdict = {k: yj[R_u_idx_train[k]] for k in R_u_idx_train.keys()}
>> %timeit newdict[1]
202 ns ± 6.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
无论如何,如果知道是否有使用 numpy
加快速度的方法,也许仍然很酷!
我有以下问题:我有一个大小为 (m,200)
(m = 3683
) 的矩阵 yj
,并且我有一个字典,每个键 returns yj
的一个 numpy 行索引数组(对于每个键,大小数组都会改变,以防万一有人想知道)。
现在,我必须多次访问此矩阵(大约 100 万次),并且由于索引编制,我的代码速度变慢了(我分析了代码,这一步花费了 65% 的时间)。
这是我试过的:
- 首先,使用索引进行切片:
>> %timeit yj[R_u_idx_train[1]]
10.5 µs ± 79.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
变量R_u_idx_train
是具有行索引的字典。
- 我认为布尔索引可能会更快:
>> yj[R_u_idx_train_mask[1]]
10.5 µs ± 159 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
R_u_idx_train_mask
是一个字典,returns 一个大小为 m
的布尔数组,其中 R_u_idx_train
给出的索引设置为 True。
- 我也试过了
np.ix_
>> cols = np.arange(0,200)
>> %timeit ix_ = np.ix_(R_u_idx_train[1], cols); yj[ix_]
42.1 µs ± 353 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
- 我也试过了
np.take
>> %timeit np.take(yj, R_u_idx_train[1], axis=0)
2.35 ms ± 88.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
虽然这看起来很棒,但事实并非如此,因为它给出了一个形状为 (R_u_idx_train[1].shape[0], R_u_idx_train[1].shape[0])
的数组(它应该是 (R_u_idx_train[1].shape[0], 200)
)。我想我没有正确使用该方法。
- 我也试过了
np.compress
>> %timeit np.compress(R_u_idx_train_mask[1], yj, axis=0)
14.1 µs ± 124 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
- 最后我尝试使用布尔矩阵进行索引
>> %timeit yj[R_u_idx_train_mask2[1]]
244 µs ± 786 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
那么,10.5 µs ± 79.7 ns per loop
我能做到最好吗?我可以尝试使用 cython
但这似乎只是索引的很多工作...
非常感谢。
V.Ayrat在评论中给出了一个非常聪明的解决方案。
>> newdict = {k: yj[R_u_idx_train[k]] for k in R_u_idx_train.keys()}
>> %timeit newdict[1]
202 ns ± 6.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
无论如何,如果知道是否有使用 numpy
加快速度的方法,也许仍然很酷!