【问题标题】:load np.memmap without knowing shape在不知道形状的情况下加载 np.memmap
【发布时间】:2016-04-20 15:51:15
【问题描述】:

是否可以在不知道形状的情况下加载numpy.memmap 并仍然恢复数据的形状?

data = np.arange(12, dtype='float32')
data.resize((3,4))
fp = np.memmap(filename, dtype='float32', mode='w+', shape=(3,4))
fp[:] = data[:]
del fp
newfp = np.memmap(filename, dtype='float32', mode='r', shape=(3,4))

在最后一行中,我希望能够不指定形状并且仍然让变量newfp 具有形状(3,4),就像使用joblib.load 一样。这可能吗?谢谢。

【问题讨论】:

    标签: python numpy memory-mapped-files joblib


    【解决方案1】:

    除非该信息已明确存储在文件中的某个位置,否则不会。就np.memmap而言,文件只是一个平面缓冲区。

    我建议使用 np.save 来保存 numpy 数组,因为这也保留了指定它们的维度、数据类型等的元数据。您还可以通过将 memmap_mode= 参数传递给 @987654323 来将 .npy 文件作为 memmap 加载@。

    joblib.dump 结合使用 pickling 来存储通用 Python 对象和 np.save 来存储 numpy 数组。


    要初始化由.npy 文件支持的空内存映射数组,您可以使用numpy.lib.format.open_memmap

    import numpy as np
    from numpy.lib.format import open_memmap
    
    # initialize an empty 10TB memory-mapped array
    x = open_memmap('/tmp/bigarray.npy', mode='w+', dtype=np.ubyte, shape=(10**13,))
    

    您可能会惊讶于这一事实,即使阵列大于总可用磁盘空间(我的笔记本电脑只有 500GB SSD,但我刚刚创建了一个 10TB 的 memmap)。这是可能的,因为创建的文件是sparse

    发现open_memmap 的功劳应归于kiyo's previous answer here

    【讨论】:

    • 问题是我正在处理非常大的数据,memmap 避免填满所有 RAM。我还将它与joblib.Parallel 一起使用以并行写入磁盘。
    • 正如我所说,您还可以通过将memmap_mode= 参数传递给np.load,将.npy 文件作为内存映射数组打开。另一种选择是将joblib.dumpjoblib.loadmemmap_mode= 参数结合使用,该参数在后台使用np.savenp.load
    • 假设我需要初始化 100 GB 的数据,而我只有 32 GB 的 RAM。在那种情况下,我不得不在写模式下使用memmap。现在,np.load 在这种情况下不起作用:我必须在读取模式下使用memmap 再次读取它。问题是,如何在不知道数据形状的情况下做到这一点,并且仍然得到正确的形状。
    • 我明白了 - 您应该在问题中包含此信息。在这种情况下,您可以使用numpy.lib.format.open_memmap 来初始化由.npy 文件支持的空内存映射数组(请参阅this previous answer)。
    【解决方案2】:

    来自@ali_m 的answer 完全有效。我想提一下我的个人喜好,以防它帮助任何人。我总是以形状作为前 2 个元素来开始我的 memmap 数组。这样做很简单:

    # Writing the memmap array
    fp = np.memmap(filename, dtype='float32', mode='w+', shape=(3,4))
    fp[:] = data[:]
    fp = np.memmap(filename, dtype='float32', mode='r+', shape=(14,))
    fp[2:] = fp[:-2]
    fp[:2] = [3, 4]
    del fp
    

    或者更简单:

    # Writing the memmap array
    fp = np.memmap(filename, dtype='float32', mode='w+', shape=(14,))
    fp[2:] = data[:]
    fp[:2] = [3, 4]
    del fp
    

    那么你可以很容易的将数组读取为:

    #reading the memmap array
    newfp = np.memmap(filename, dtype='float32', mode='r')
    row_size, col_size = newfp[0:2]
    newfp = newfp[2:].reshape((row_size, col_size))
    

    【讨论】:

    • 这很好,只要您只使用具有固定 dtype 的 2D 数组(而且您确实应该将数组维度存储为整数而不是浮点数)。使用np.savenumpy.lib.format.open_memmap 的主要优点是它们会自动存储指定数组形状和数据类型的元数据。
    【解决方案3】:

    numpy.memmap 的替代品是tifffile.memmap

    from tifffile import memmap
    newArray = memmap("name", shape=(3,3), dtype='uint8')
    newArray[1,1] = 11
    del(newArray)
    

    newArray 文件已创建,具有值:

    0  0  0
    0  11 0
    0  0  0  
    

    现在让我们回读一下:

    array = memmap("name", dtype='uint8')
    print(array.shape) # prints (3,3)
    print(array)
    

    打印:

    0  0  0
    0  11 0
    0  0  0
    

    【讨论】:

      猜你喜欢
      • 2016-06-16
      • 2017-10-13
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多