Python, H5PY, большие данные

Пакет Python для работы с огромными объемами числовых данных в Python

HDF5 позволяет хранить огромные объемы числовых данных и легко управлять этими данными из NumPy.

HDF5 - отличный механизм для хранения больших числовых массивов однородного типа для моделей данных, которые могут быть организованы иерархически и извлекать выгоду из тегирования наборов данных с произвольными метаданными.

Это сильно отличается от реляционных баз данных в стиле SQL. У HDF5 есть немало организационных уловок в рукаве, но если вы обнаружите, что вам нужно установить отношения между значениями в различных таблицах или вы хотите выполнять JOIN-соединения с вашими данными, реляционная база данных, вероятно, более подходящая.

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

Иерархический формат данных версии 5 или «HDF5» - это стандартный механизм для хранения больших объемов числовых данных. По мере увеличения объемов данных организация данных становится все более важной; функции в наборах данных HDF5 с одинаковыми именами, иерархически организованные группы и определяемые пользователем «атрибуты» метаданных становятся важными для процесса анализа.

Файл HDF5 представляет собой контейнер для двух типов объектов:
* Наборы данных, которые представляют собой массивы, подобные коллекциям данных.
* Группы, которые представляют собой контейнеры в виде папок, которые содержат наборы данных и другие группы.

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

Пакет H5py Python

Пакет h5py Python представляет собой интерфейс Pythonic для двоичного формата данных HDF5. Это помогает хранить огромные объемы числовых данных и легко манипулировать данными из модуля NumPy.

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

H5py использует метафоры NumPy и Python, такие как словарь и синтаксис массива NumPy для своих операций с данными.

Например, вы можете перебирать наборы данных в файле или проверять атрибуты .shape или .dtype наборов данных. Вам не нужно ничего особенного знать о HDF5.

H5py основан на объектно-ориентированной оболочке Cython для HDF5 C API. Практически все, что вы можете сделать из C в HDF5, вы можете сделать из h5py. Самое важное, что нужно помнить при использовании h5py:

Группы работают как словари, а наборы данных работают как массивы NumPy

Установка

Установите через pip из PyPI, используя следующую команду:

pip install h5py

Для Anaconda / MiniConda используйте следующую команду:

conda install h5py

Для Canopy используйте следующую команду:

enpkg h5py

Открытие и создание файлов

Файлы HDF5 также работают как стандартные файловые объекты Python. Они поддерживают стандартные режимы, такие как r / w / a, и должны быть закрыты, когда они больше не используются. Нет понятия «текстовый» или «двоичный» режим.

import h5py
f = h5py.File('myfile.hdf5','r')

Организация данных и метаданных

Ниже приведен пример кода для данных метеостанции, которые измеряли температуру, скажем, каждые 10 секунд. Используя массив NumPy, данные были представлены для эксперимента:

import numpy as np
temperature = np.random.random(1024)
temperature
Output
array([ 0.44149738, 0.7407523 , 0.44243584, …, 0.19018119,
 0.64844851, 0.55660748])
dt = 10.0
start_time = 1375204299  # in Unix time
station = 15
np.savez("weather.npz", data=temperature, start_time=start_time, station=station)
out = np.load("weather.npz")
out["data"]
Output
array([ 0.44149738,  0.7407523 ,  0.44243584, ...,  0.19018119,
        0.64844851,  0.55660748])
out["start_time"]
Output
array(1375204299)
out["station"]
Output
array(15)

Пока все выглядит хорошо. Но что, если у нас есть более одного количества на станцию? Скажите, есть еще данные о скорости ветра, которые нужно записать? Предположим, у нас есть несколько станций. Мы могли бы ввести какое-то соглашение об именах.

Напротив, вот как приложение может приблизиться к хранилищу с HDF5:

import h5py
f = h5py.File(“weather.hdf5”)
f[“/15/temperature”] = temperature
f[“/15/temperature”].attrs[“dt”] = 10.0
f[“/15/temperature”].attrs[“start_time”] = 1375204299
f[“/15/wind”] = wind
f[“/15/wind”].attrs[“dt”] = 5.0
----
f[“/20/temperature”] = temperature_from_station_20
----
(and so on)

Этот пример иллюстрирует две важные особенности HDF5
* организации иерархических групп и атрибутов.
* Группы, как и папки в файловой системе, позволяют хранить связанные наборы данных вместе.

В этом случае измерения температуры и ветра с одной и той же метеостанции хранятся вместе в группах с именами «/ 15», «/ 20» и т. Д. Атрибуты позволяют прикреплять описательные метаданные непосредственно к данным, которые они описывают. Итак, если вы поделитесь этим файлом с кем-либо, они смогут легко найти информацию, необходимую для понимания данных:

dataset = f[“/15/temperature”]
for key, value in dataset.attrs.iteritems():
… print “%s: %s” % (key, value)
dt: 10.0
start_time: 1375204299

Работа с большими объемами данных

В качестве высокоуровневого «связующего» языка Python все чаще используется для быстрой визуализации больших наборов данных и для координации крупномасштабных вычислений, выполняемых на компилируемых языках, таких как C и FORTRAN. Сейчас довольно часто приходится иметь дело с наборами данных размером в сотни гигабайт или даже терабайт; Сам HDF5 может масштабироваться до эксабайт.

На всех машинах, кроме самых больших, невозможно загрузить такие наборы данных непосредственно в память. Одной из самых сильных сторон HDF5 является поддержка подмножества и частичного ввода-вывода.

Например, возьмем набор данных «Температура» из 1024 элементов, который мы создали ранее:

dataset = f[“/15/temperature”]

Здесь объект с именем dataset - это прокси-объект, представляющий набор данных HDF5. Он поддерживает операции нарезки, подобные массиву, которые будут знакомы частым пользователям NumPy:

dataset[0:10]
Output
array([ 0.44149738, 0.7407523 , 0.44243584, 0.3100173 , 0.04552416,
 0.43933469, 0.28550775, 0.76152561, 0.79451732, 0.32603454])
dataset[0:10:2]
Output
array([ 0.44149738, 0.44243584, 0.04552416, 0.28550775, 0.79451732])

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

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

Например, вот набор данных размером 2 терабайта, который вы можете создать практически на любом компьютере:

big_dataset = f.create_dataset(“big”, shape=(1024, 1024, 1024, 512), 
dtype=’float32')

Хотя хранилище еще не выделено, нам доступно все «пространство» набора данных. Мы можем писать где угодно в наборе данных, и используются только байты на диске, необходимые для хранения данных:

big_dataset[344, 678, 23, 36] = 42.0

Когда объем хранилища ограничен, вы даже можете использовать прозрачное сжатие для каждого набора данных:

compressed_dataset = f.create_dataset(“comp”, shape=(1024,), dtype=’int32', compression=’gzip’)
compressed_dataset[:] = np.arange(1024)
compressed_dataset[:]
Output
array([ 0, 1, 2, …, 1021, 1022, 1023])

Параллельный HDF5

Parallel HDF5 - это конфигурация библиотеки HDF5, которая позволяет вам совместно использовать открытые файлы в нескольких параллельных процессах. Он использует стандарт MPI (интерфейс передачи сообщений) для межпроцессного взаимодействия. Следовательно, при использовании Parallel HDF5 из Python ваше приложение также должно будет использовать библиотеку MPI.

Это достигается с помощью пакета Python mpi4py, который предоставляет отличные полные привязки Python для MPI.

from mpi4py import MPI
import h5py

rank = MPI.COMM_WORLD.rank  # The process ID (integer 0-3 for 4-process run)

f = h5py.File('parallel_test.hdf5', 'w', driver='mpio', comm=MPI.COMM_WORLD)

dset = f.create_dataset('test', (4,), dtype='i')
dset[rank] = rank

f.close()

Запускаем программу:

mpiexec -n 4 python demo2.py

Смотрим на файл с h5dump:

h5dump parallel_test.hdf5
HDF5 "parallel_test.hdf5" {
GROUP "/" {
   DATASET "test" {
      DATATYPE  H5T_STD_I32LE
      DATASPACE  SIMPLE { ( 4 ) / ( 4 ) }
      DATA {
      (0): 0, 1, 2, 3
      }
   }
}
}

Избегайте использования ОЗУ для больших массивов - вместо этого используйте диск для хранения

Избегайте создания большого массива с сохранением ОЗУ, если только это не потребуется для вычислений, иначе ОЗУ не заполнится. Это очень важно при работе в виртуальной среде с ограниченными вычислительными средами, такими как Kaggle Kernel, AWS, Google Colab. В таких случаях рекомендуется хранить на диске вместо ОЗУ.

Создайте массив NumPy из 600 600 600,6 и присвойте индексу значение 100.

results = np.ones((600,600,600,6))
results[2,4,5,1] = 100

Используя пакет H5py, мы можем сделать то же самое, что и выше, сохраняя данные на диске, и это не повлияло на операцию назначения данных с использованием ОЗУ.

import h5py
hdf5_store = h5py.File(“./cache.hdf5”, “a”)
results = hdf5_store.create_dataset(“results”, (600,600,600,6), compression=”gzip”)
# do something…
results[2,4,5,1] = 100

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

Последние мысли

Поскольку Python все чаще используется для обработки больших наборов числовых данных, больше внимания уделяется использованию стандартных форматов для хранения и передачи данных. HDF5, самая последняя версия формата иерархических данных, первоначально разработанная в Национальном центре суперкомпьютерных приложений (NCSA), быстро стала предпочтительным механизмом для хранения научных данных в Python. В то же время многих исследователей, которые используют (или интересуются) HDF5, привлекает Python из-за его простоты использования и возможностей быстрой разработки.

Дальнейшие ссылки

  1. HDF5 для Python
  2. Руководство пользователя H5py
  3. H5py GitHub
  4. Книга О’Рейли, Python и HDF5

«Мы вступаем в новый мир, в котором данные могут быть важнее программного обеспечения». - Тим О’Рейли, основатель O’Reilly Media.