【问题标题】:select elements from array mimizing memory usage从数组中选择元素以最小化内存使用
【发布时间】:2014-01-12 23:13:51
【问题描述】:

假设我有一个非常大的np.array,其中包含 N 个元素,并且我只想选择一些通过 S 选择的值。通常的方式是:

selected_items = original_array[selection1(original_array) & original_array > 3]

这很好,但使用了大量的临时内存。如果我是正确的,我需要 S 个大小为 N 的布尔值掩码,再加上至少一个用于 & 结果的掩码。在内存使用方面有更好的解决方案吗?例如显式循环不需要这个:

selected_items = []
tests = (selection1, lambda x: x > 3)
for x in orignal_items:
    if all( (t(x) for t in tests) ):
       selected_items.append(x)

我喜欢numpy,但它的设计真的是内存渴望,所以似乎不适合处理大数据。另一方面,python 中的显式循环不是很高效。

numpy 有解决办法吗?

还有其他基于 python 的大数据分析框架吗?

【问题讨论】:

  • 恕我直言,如果您有N 的空间,那么为3*N 需要空间似乎不是什么大问题。我们不是在谈论像O(N^2) 这样的内存扩展。 This link 可能会感兴趣
  • 这是一个简单的例子。在我的现实生活中,不幸的是 numpy(如 Matlab、Mathematica、...)似乎不是正确的工具,因为它们将所有值都存储在内存中。我有绅士,每个条目都有数百个字段。
  • @RuggeroTurra Numpy 可以通过np.memmap 处理磁盘上的阵列,或者您也可以查看PyTables

标签: python numpy bigdata


【解决方案1】:

您可以在使用它从数组中选择数据子集之前就地构建选择“掩码”,而不是循环遍历项目。例如:

import numpy as np


x = np.arange(1, 100)

# x less than 75
selection = x < 75

# and greater than 35
selection &= x > 35

# and odd.
selection &= x & 1

print x[selection]

# [37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73]

这不是一个完美的解决方案,但它可能会有所帮助。

【讨论】:

    【解决方案2】:

    布尔值存储为一个字节;除非您将整个内存塞满 uint8,否则相对而言,它不太可能成为那么大的问题,特别是如果您充分利用就地运算符。但是,如果您的数据几乎无法放入内存,那么研究可以有效执行此类查询的磁盘存储可能会很好。 pytables 浮现在脑海中;特别是关于您关于大数据 python 框架的更一般性的问题。

    【讨论】:

      【解决方案3】:

      另一个主要使用数学的基于 python 的框架是 SAGE。内置了许多算法,包括排序和搜索算法。我最近正在使用它进行 RSA 建模,但也许你应该尝试一下。

      【讨论】:

      • 相对于 python 及其生态系统,SAGE 与大数据有什么特别的相关性吗?
      【解决方案4】:

      布尔选择掩码在 RAM 中每个空间值占用一个字节。如果您的数据可以放入 RAM,那么布尔掩码也有可能适合。

      您可以使用就地操作在单个布尔选择掩码中累积选择。通过这种方式,您可以使用一个选择掩码的固定 RAM 要求应用任意数量的逻辑操作。

      要执行就地布尔运算,您可以使用提供out 参数的Numpy Logic Functions。例如:

      # (selection1  _AND_  original_array) > 3
      mask = selection1(original_array)
      mask = np.logical_and(mask, original_array, out=mask)
      mask = np.greater(mask, 3, out=mask)
      

      您还可以使用中缀运算符(分别为+=*=、OR 和 AND)执行就地操作。

      如果您没有足够的 RAM 来创建一个布尔掩码,并且所选元素的数量很少,您可以求助于按索引号选择元素。例如numpy.nonzero() 返回每​​个非零元素的索引。

      最后,如果您的数据不适合 RAM,那么您可以使用 pytables。这允许您在切片中保存和加载数据。 Pytables 不仅为您提供非常快速的 IO 操作,而且还可以使用单个命令对磁盘数据集执行非常快速(复杂)的查询(请参阅 pytable 文档:Expr module)。然而,pytables 在开始时可能有点吓人。所以如果你胆子小,我不建议使用它(而且你不是绝对需要它)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-27
        • 1970-01-01
        • 2020-03-27
        • 2012-10-17
        • 1970-01-01
        相关资源
        最近更新 更多