Сброс numpy memmap в файл npy
Есть ли способ сохранить массив Numpy Memmap в .npy
файл? Судя по всему, есть способ загрузить такой массив из .npy
файл следующим образом
data = numpy.load("input.npy", mmap_mode='r')
но очистка файла не эквивалентна хранению его в .npy
формат.
Если очистка - единственный путь, есть ли способ определить форму хранимого массива? Я бы предпочел иметь динамическую форму, которая автоматически сохраняется и извлекается (возможно, снова как memmap) в другом скрипте.
Я искал в разных местах об этом, но не нашел никакого результата. Я способ хранить в .npy
Я делаю сейчас
numpy.save(output.filename, output.copy())
который побеждает идею использования memmap, но сохраняет форму.
ПРИМЕЧАНИЕ: я знаю о hdf5 и h5py, но мне было интересно, есть ли для этого чисто тупое решение.
2 ответа
Есть ли способ вывести форму хранимого массива?
Нет Так далеко как np.memmap
Дело в том, что файл является просто буфером - он хранит содержимое массива, но не размеры, dtype и т. д. Невозможно вывести эту информацию, если она каким-то образом не содержится в самом массиве. Если вы уже создали np.memmap
опираясь на простой двоичный файл, вам нужно будет записать его содержимое в новый .npy
файл на диске.
Вы можете избежать создания копии в памяти, открыв новый .npy
файл как другой отображенный в память массив с помощью numpy.lib.format.open_memmap
:
import numpy as np
from numpy.lib.format import open_memmap
# a 10GB memory-mapped array
x = np.memmap('/tmp/x.mm', mode='w+', dtype=np.ubyte, shape=(int(1E10),))
# create a memory-mapped .npy file with the same dimensions and dtype
y = open_memmap('/tmp/y.npy', mode='w+', dtype=x.dtype, shape=x.shape)
# copy the array contents
y[:] = x[:]
Отказ от ответственности: следующее работает с numpy версией 1.11.2 (и позже, я полагаю), но более ранняя версия, которую я попробовал (1.8.2), выдавала ошибку
Массив сохранен с np.save
по сути, это memmap с заголовком, определяющим dtype, shape и порядок элементов. Вы можете прочитать больше об этом в numy документации.
Когда вы создаете свой np.memmap
, вы можете зарезервировать место для этого заголовка с offset
параметр. Примечание. В документации указано, что длина заголовка должна быть кратна 16:
Допустим, вы резервируете 5 * 16 = 80 байт для заголовка (подробнее об этом ниже):
import numpy as np
x = np.memmap('/tmp/x.npy', mode='w+', dtype=np.ubyte, shape=(int(1E10),), offset=80)
Затем, когда вы закончите манипулировать memmap, вы создадите и напишите заголовок, используя np.lib.format
:
header = np.lib.format.header_data_from_array_1_0(x)
with open('/tmp/x.npy', 'r+b') as f:
np.lib.format.write_array_header_1_0(f, header)
Обратите внимание, что это записывает заголовок с начала файла memmap, так что если len(header) > 80
, тогда он перезапишет часть данных, и ваш файл не будет читаемым. Заголовок представляет собой магическую строку фиксированной длины, два байта версии, два байта, определяющие длину заголовка, и строковое представление словаря, задающего "shape", "descr" и "order". Если вы знаете форму и dtype (descr
) вашего массива, вы можете легко вычислить длину заголовка (я установил это на 80 выше, для простоты).
После написания заголовка вы можете загрузить данные, используя np.load
:
y = np.load('/tmp/x.npy')