【问题标题】:convert a text of binary values to numpy file将二进制值的文本转换为 numpy 文件
【发布时间】:2015-06-17 22:07:56
【问题描述】:

如何将包含二进制值字符(01)的巨大文本文件 (>16G) 转换为 numpy 数组文件,而不会炸毁 python 中的内存?假设我们在机器上有足够的存储空间,但没有足够的 RAM 用于转换。

样本数据:

0,0,0,0,0,1,0,0,0 
1,0,0,1,0,0,0,0,0
...

示例代码:

converted_data = [ map(int,line.split(',')) for line in f ]

【问题讨论】:

  • “二进制值字符串”是什么意思?现有文件的确切格式是什么?根据现有格式,您也许可以使用内存映射数组做一些事情。
  • 这是一个很好的话题,但没有足够的信息来提供有用的答案。您可以发布可以读取较小文件的代码吗?如果做不到,请提供文件格式等详细信息。
  • 测试文件包含“0”和“1”字符,用逗号隔开。
  • 这是我用来进行转换的示例代码:
  • 您是否对导入过程的内存消耗感兴趣(可以通过串行读取和转换数据而不是一次读取所有数据来减少)或converted_data 的占用空间(将> 1G,除非你可以利用稀疏结构)?

标签: python memory numpy text


【解决方案1】:

您使用 pickle 创建了许多 bin 文件,并且您有一些代码可以加载和卸载数据的不同部分。

假设你有一个 16GB 的文件,你可以创建 16 个 1GB 的 pickle 文件。

如果你说你有足够的内存,泡菜文件完成后,你应该可以把它全部加载到内存中。

【讨论】:

    【解决方案2】:

    据我所知,您读取文件的方法已经非常节省内存。

    我假设使用open 获取文件对象将不会将整个文件从文件系统读取到 RAM 中,而是根据需要访问文件系统上的文件。

    然后您遍历文件对象的yields the file's lines(在您的情况下为字符串,因为您已在文本模式下打开文件),即文件对象充当generator。因此可以假设这里没有构建所有行的列表,并且这些行被逐一读取以被连续消耗。

    您在列表收缩中执行此操作。列表收缩是否收集其右侧(in 关键字之后的部分)产生的所有值,然后将其传递到左侧(for 关键字之前的部分)进行处理?一个小实验可以告诉我们:

    print('defining generator function')
    
    def firstn(n):
            num = 0
            while num < n:
                    print('yielding ' + str(num))
                    yield num
                    num += 1
    
    print('--')
    
    [print('consuming ' + str(i)) for i in firstn(5)]
    

    上面的输出是

    defining generator function
    --
    yielding 0
    consuming 0
    yielding 1
    consuming 1
    yielding 2
    consuming 2
    yielding 3
    consuming 3
    yielding 4
    consuming 4
    

    所以答案是否定的,每个产生的值在从右侧产生任何其他值之前立即被左侧消耗。一次只能将文件中的一行保存在内存中。

    因此,如果文件中的各行不太长,您的阅读方法似乎与内存效率一样高

    当然,您的列表收缩仍然需要收集左侧处理的结果。毕竟,结果列表是您想要从这一切中得到的。因此,如果内存不足,很可能是结果列表变得太大。

    我不知道 NumPy 是否使用布尔集合比数字更有效地存储这一事实。但是如果确实如此,你必须让它知道你的整数实际上是布尔值的,以便从更节省内存的数据类型中受益:

    import numpy as np
    f = open ( "data.txt" , 'r')
    converted_data = [ np.fromstring(line, dtype=bool, sep=',') for line in f ]
    

    如果您不需要同时使用所有 converted_data,而是必须能够对其进行迭代,请考虑将其也设为生成器,而不是列表。您不需要太多使用 yield 关键字来实现这一点。只需用圆括号替换列表推导的方括号,您就得到了一个生成器表达式:

    converted_data_generator = ( np.fromstring(line, dtype=bool, sep=',') for line in f )
    

    【讨论】:

    • 希望从我的措辞中可以看出,我的许多结论都是基于推测。所以如果有人知道得更好,请纠正我。
    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    相关资源
    最近更新 更多