Почему я могу обработать большой файл только тогда, когда я не исправляю предупреждение об устаревании HDF5? - PullRequest
0 голосов
/ 27 апреля 2020

Получив предупреждение H5pyDeprecationWarning: dataset.value has been deprecated. Use dataset[()] instead. , я изменил свой код на:

import h5py
import numpy as np 

f = h5py.File('myfile.hdf5', mode='r')
foo = f['foo']
bar = f['bar']
N, C, H, W = foo.shape. # (8192, 3, 1080, 1920)
data_foo = np.array(foo[()]) # [()] equivalent to .value

, и когда я попытался прочитать (не очень) большой файл изображений, я получил Killed: 9 на моем терминале, мой процесс был убит, потому что он занимал слишком много памяти, в последней строке кода, несмотря на мой арха c мой комментарий там. .

Тем не менее, мой оригинальный код:

f = h5py.File('myfile.hdf5', mode='r')
data_foo = f.get('foo').value
# script's logic after that worked, process not killed

работал нормально, кроме как из выданного предупреждения ..

Почему мой код работал?

1 Ответ

1 голос
/ 27 апреля 2020

Позвольте мне объяснить, что делает ваш код и почему вы получаете ошибки памяти. Сначала немного основ HDF5 / h5py. (Документы h5py являются отличной отправной точкой. Проверьте здесь: h5py QuickStart )

foo = f['foo'] и foo = f.get('foo') оба возвращают объект набора данных h5py с именем 'foo'. (Примечание: это Чаще встречается это как foo = f['foo'], но нет ничего плохого в методе get().) Объект набора данных отличается от с массивом NumPy. Наборы данных ведут себя как NumPy массивы; оба имеют форму и тип данных и поддерживают нарезку в стиле массива. Однако при доступе к объекту набора данных вы не читаете все данные в память. В результате им требуется меньше памяти для доступа. Это важно при работе с большими наборами данных!

Этот оператор возвращает массив Numpy: data_foo = f.get('foo').value. Предпочтительный метод data_foo = f['foo'][:]. (NumPy нотация срезов - это способ вернуть массив NumPy из объекта набора данных. Как вы обнаружили, .value устарел.)
Это также возвращает массив Numpy: data_foo = foo[()] (при условии foo определяется как указано выше).
Итак, когда вы вводите это уравнение data_foo = np.array(foo[()]), вы создаете новый массив NumPy из другого массива (foo[()] является входным объектом). Я подозреваю, что ваш процесс был уничтожен, потому что объем памяти для создания копии массива (8192, 3, 1080, 1920) превысил ваши системные ресурсы. Это утверждение будет работать для небольших наборов данных / массивов. Однако это не очень хорошая практика.

Вот пример, демонстрирующий использование различных методов (объект набора данных h5py против NumPy массива).

h5f = h5py.File('myfile.hdf5', mode='r')

# This returns a h5py object:
foo_ds = h5f['foo']
# You can slice to get elements like this:
foo_slice1 = foo_ds[0,:,:,:] # first row
foo_slice2 = foo_ds[-1,:,:,:] # last row

# This is the recommended method to get a Numpy array of the entire dataset:
foo_arr = h5f['foo'][:]
# or, referencing h5py dataset object above
foo_arr = foo_ds[:] 
# you can also create an array with a slice
foo_slice1 = h5f['foo'][0,:,:,:] 
# is the same as (from above):
foo_slice1 = foo_ds[0,:,:,:] 
...