Как лениво объединить объекты, подобные numpy ndarray, для последовательного чтения?

У меня есть список из нескольких больших файлов hdf5, каждый из которых содержит набор данных 4D. Я хотел бы получить их конкатенацию на первой оси, например, массивоподобный объект, который будет использоваться так, как если бы все наборы данных были объединены. Мое окончательное намерение состоит в том, чтобы последовательно читать фрагменты данных по одной и той же оси (например, [0:100,:,:,:], [100:200,:,:,:],...) несколько раз.

Наборы данных в h5py разделяют значительную часть API массива numpy, что позволяет мне вызывать numpy.concatenate, чтобы выполнить задание:

files = [h5.File(name, 'r') for name in filenames]
X = np.concatenate([f['data'] for f in files], axis=0)

С другой стороны, структура памяти неодинакова, и память не может быть разделена между ними (связанный вопрос). Увы, concatenate охотно скопирует все содержимое каждого массивоподобного объекта в новый массив, что я не могу принять в моем случае использования. исходный код функция объединения массивов подтверждает это.

Как я могу получить объединенное представление для нескольких массивоподобных объектов, без жадного считывания их в память? Что касается этого представления, нарезка и индексация этого представления будут вести себя так же, как если бы у меня был конкатенированный массив.

Я могу представить, что написание пользовательской оболочки сработает, но я хотел бы знать, существует ли уже такая реализация в виде библиотеки, или доступно ли другое решение проблемы, столь же осуществимое. Мои поиски пока ничего подобного не дали. Я также готов принять решения, специфичные для h5py.


person E_net4 the curator    schedule 10.01.2017    source источник


Ответы (1)


flist = [f['data'] for f in files] — это список dataset объектов. Фактические данные находятся в h5 файлах и доступны, пока эти файлы остаются открытыми.

Когда вы делаете

arr = np.concatenate(flist, axis=0)

Я думаю, что concatenate первым делает

tmep = [np.asarray(a) for a in flist]

то есть построить список массивов numpy. Я предполагаю, что np.asarray(f['data']) совпадает с f['data'].value или f['data'][:] (как я обсуждал 2 года назад в связанном вопросе SO). Я должен провести несколько тестов времени, сравнив это с

arr = np.concatenate([a.value for a in flist], axis=0)

flist — это своего рода ленивая компиляция этих наборов данных, поскольку данные все еще находятся в файле и доступны только тогда, когда вы делаете что-то еще.

[a.value[:,:,:10] for a in flist]

загрузит часть каждого из этих наборов данных в память; Я ожидаю, что конкатенация в этом списке будет эквивалентна arr[:,:,:10].

Генераторы или генераторные включения - это форма ленивых вычислений, но я думаю, что их нужно превратить в списки перед использованием в concatenate. В любом случае результатом concatenate всегда является массив со всеми данными в непрерывном блоке памяти. Это никогда не блоки данных, находящихся в файлах.

Вам нужно рассказать нам больше о том, что вы собираетесь делать с этим большим составным массивом наборов данных. В общих чертах я думаю, что вы можете создавать массивы, содержащие фрагменты всех наборов данных. Вы также можете выполнять другие действия, как показано в предыдущем ответе, но с затратами времени на доступ.

person hpaulj    schedule 10.01.2017
comment
Я обновил вопрос. То, что я назвал предполагаемой конкатенацией, было бы представлением массивоподобных объектов, которые определенно не использовали бы concatenate numpy. - person E_net4 the curator; 10.01.2017
comment
[100:200,:,:,:] применяются к объединенным наборам, только к одному набору данных или к диапазону «строк», перекрывающих два набора? - person hpaulj; 10.01.2017
comment
Обновлено снова. Что касается этого представления, срезы и операции с индексами в этом представлении будут вести себя так же, как если бы у меня был конкатенированный массив. Я не могу придумать, как сделать это яснее. - person E_net4 the curator; 10.01.2017
comment
Я думаю, вам нужно написать свою собственную функцию бухгалтерского учета, которая вычисляет, какие срезы каких наборов данных она загружает и объединяет. Посмотрите в np.lib.index_tricks, если вам нужны идеи о том, как преобразовать такую ​​функцию в класс, который принимает нотацию индексации. Я могу набросать такую ​​функцию, если нужно. - person hpaulj; 11.01.2017