【问题标题】:More efficient way to access rows based on a list of indices in 2d numpy array?基于 2d numpy 数组中的索引列表访问行的更有效方法?
【发布时间】:2020-07-30 07:47:54
【问题描述】:

所以我有 2d numpay 数组 arr。比较大的一个:arr.shape = (2400, 60000)

我目前正在做的事情如下:

  • 随机(有替换)选择arr.shape[0]索引
  • 访问(逐行)arr 的选定索引
  • 计算列平均值并选择最大值
  • 我重复了k次

它看起来像:

no_rows = arr.shape[0]
indicies = np.array(range(no_rows))
my_vals = []
for k in range(no_samples):
    random_idxs = np.random.choice(indicies, size=no_rows, replace=True)
    my_vals.append(
        arr[random_idxs].mean(axis=0).max()
    )

我的问题是速度很慢。使用我的arr 大小,1 次循环大约需要 3 秒。因为我想要一个大于 1k 的样本 - 我当前的解决方案非常糟糕(1k*~3s -> ~1h)。我已经对其进行了分析,瓶颈是基于索引访问行。 "mean""max"工作fast. np.random.choice也可以。

您认为有什么需要改进的地方吗?一种更有效的访问索引的方法,或者更好的更快的方法来解决这个问题?

到目前为止我尝试了什么:

  • numpy.take(较慢)
  • numpy.ravel:

类似于:

random_idxs = np.random.choice(sample_idxs, size=sample_size, replace=True) 
test = random_idxs.ravel()[arr.ravel()].reshape(arr.shape)
  • 与当前方法类似,但没有循环。我一次性创建了 3d arr 并访问了其他维度的行

【问题讨论】:

  • 代码中的no_samples 是什么?
  • no_samples 只是定义样本大小的整数。我希望它>1k

标签: python arrays numpy numpy-indexing


【解决方案1】:

由于advanced indexing会生成一个副本,程序会在arr[random_idxs]中分配巨大的内存。

因此,提高效率的最简单方法之一就是批量处理。

BATCH = 512
max(arr[random_idxs,i:i+BATCH].mean(axis=0).max() for i in range(0,arr.shape[1],BATCH))

【讨论】:

  • 谢谢 - 这确实有帮助!我已经设法通过批处理方法将其加快了约 3.5 倍。单次迭代从 ~3s 减少到 ~0.79。我只想补充一点,使用适当的批量大小是件好事。我已经进行了几次测试。以下是结果 (BATCH, avg_time_in_100_iterations): (16, 1.13), (32, 0.87), (64, 0.79), (128, 1.2), (256, 1.33), (512, 1.8) 和 (1024, 2.47)
【解决方案2】:

这不是问题的一般解决方案,但应该使您的特定问题更快。基本上,arr.mean(axis=0).max() 不会改变,那么为什么不从该数组中随机抽取样本呢?

类似:

mean_max = arr.mean(axis=0).max()
my_vals = np.array([np.random.choice(mean_max, size=len(mean_max), replace=True) for i in range(no_samples)])

您甚至可以这样做:my_vals = np.random.choice(mean_max, size=(no_samples, len(mean_max)), replace=True),但我不确定这会如何改变您的统计数据。

【讨论】:

  • 不确定我是否关注。 arr.mean(axis=0).max() 会改变 - 这就是重点。我正在选择带有替换的随机索引。所以每次迭代,每一列的手段应该是不同的。然后我从这些列中选择最高值,并将其作为最终列表的数据点附加。至于您的解决方案 - 它不会运行。 mean_max 你提议的是一个浮点数。这只是 arr 的最高平均值(其中平均值是按列计算的)。因此,您尝试从可用的单个值中随机选择一个值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 2021-10-14
  • 1970-01-01
相关资源
最近更新 更多