【问题标题】:Converting Python List to Numpy Array InPlace将 Python 列表就地转换为 Numpy 数组
【发布时间】:2016-08-19 06:12:04
【问题描述】:

我有一个很大的 python 列表(16 GB),我想将它转换为 numpy 数组,就地。我买不起这种说法

huge_array = np.array(huge_list).astype(np.float16)

我正在寻找一些有效的方法来将这个 huge_list 转换为 numpy array 而不会复制它。

谁能提出一个有效的方法来做到这一点?这可能涉及先将列表保存到磁盘,然后将其加载为 numpy 数组,我可以接受。

我将非常感谢任何帮助。

编辑 1:huge_list 是在运行时创建的内存中 python 列表,因此它已经占用了 16GB。我需要将其转换为numpy float16 数组。

【问题讨论】:

  • 你排除了np.save和np.load吗?
  • 那个np.array方法耗时太长,还是会产生内存错误?
  • 我关心的是内存,而不是速度。所以 np.array 很可能会抛出内存错误。 @DanPatterson huge_list 尚未在磁盘上,它是在运行时生成的内存中,然后我必须将其转换为 numpy float16 数组
  • @Ahmed:生成列表的原因是什么?你能把它直接生成到一个数组中吗?
  • @Eric 该列表正在逐步生成,我们没有提前知道它的大小。所以它是由 list.append() 方法生成的。由于 numpy 数组是不可变的,因此没有必要直接创建 numpy 数组,因为它不会节省内存。

标签: python arrays list numpy in-place


【解决方案1】:

np.array(huge_list, dtype=np.float16) 会更快,因为它只复制列表一次而不是两次


你可能不需要担心制作这个副本,因为副本比原版小很多:

>>> x = [float(i) for i in range(10000)]
>>> sys.getsizeof(x)
83112
>>> y = np.array(x, dtype=np.float16)
>>> sys.getsizeof(y)
20096

但这还不是最糟糕的——对于 python 列表,列表中的每个数字都在占用自己的内存:

>>> sum(sys.getsizeof(i) for i in x)
240000

所以 numpy 数组要小约 ​​15 倍!

【讨论】:

  • 内存是首要问题,速度是次要问题。
  • 这也使用了 np.array(huge_list).view(np.float16) 的 1/5 内存,假设 huge_list 包含浮点数
  • 感谢您指出这一点,我已经纠正了这一点,但重点是,我的机器安装了 32GB 内存。该列表大小为 16GB (float16),我不想通过创建另一个 16GB 副本来溢出我的内存。
  • @Ahmed:副本不会是 16GB。 x = [1.0]*100, sys.getsizeof(x) == 864, sys.getsizeof(np.array(x, dtype=np.float16)) == 296
【解决方案2】:

正如我之前提到的,最简单的方法是将数组转储到文件中,然后将该文件加载为 numpy 数组。

首先我们需要大列表的大小:

huge_list_size = len(huge_list)

接下来我们将其转储到磁盘

dumpfile = open('huge_array.txt', 'w')

for item in huge_list:
    dumpfile.write(str(item)+"\n")
dumpfile.close()

如果这一切都发生在同一个环境中,请确保我们清除内存

del huge_list

接下来我们定义一个简单的读取生成器

def read_file_generator(filename):
    with open(filename) as infile:
        for i, line in enumerate(infile):
            yield [i, line]

然后我们创建一个 numpy 零数组,我们用刚刚创建的生成器填充它

huge_array = np.zeros(huge_list_size, dtype='float16')

for i, item in read_file_generator('huge_array.txt'):
    huge_array[i] = item

我之前的回答不正确。我建议以下作为解决方案,它不像hpaulj 所评论的那样

您可以通过多种方式执行此操作,最简单的方法是转储 数组到一个文件,然后将该文件加载为一个 numpy 数组:

dumpfile = open('huge_array.txt', 'w')

for item in huge_array:
  print>>dumpfile, item

然后将其加载为 numpy 数组

huge_array = numpy.loadtxt('huge_array.txt')

如果您想对该数据执行进一步的计算,您还可以 使用 joblib 库进行内存映射,这在 处理大型 numpy 数组计算。可在 https://pypi.python.org/pypi/joblib

【讨论】:

  • 但是loadtxt 将值加载到一个列表中,并在它们全部加载后执行np.array(alist)
  • 我在 numpy 1.10.4 中检查了 np.loadtxt 的来源以确定。在方法 loadtxt 的 npyio 中的第 808 行,确实指定了列表并在之后不久读取,在第 936 行,列表通过“np.array(X,dtype)”调用转换为 numpy 数组。谢谢,我不知道。我会尽快调整答案
  • 按承诺更新了答案。我确实必须同意 hpaulj 的观点,即分块可能是一个更好的解决方案,但这必须在数据生成期间完成,并且不会回答问题。
【解决方案3】:

你可以使用numpysaveload函数:

您可以使用普通 python 列表作为np.save 的参数,np.load 将直接加载到 numpy 数组中。

示例:

from tempfile import TemporaryFile
outfile = TemporaryFile()
x = [1, 2, 3]
np.save(outfile, x)

outfile.seek(0)
np.load(outfile)

【讨论】:

    猜你喜欢
    • 2017-03-08
    • 2019-03-12
    • 2010-12-30
    • 1970-01-01
    • 2019-08-30
    • 2021-11-29
    • 2015-01-07
    相关资源
    最近更新 更多