Если вы работаете в области компьютерного зрения, вы наверняка слышали о HDF5. Формат иерархических данных (HDF) версии 5 - это популярный формат для хранения и обмена неструктурированными данными, такими как изображения, видео или тома в необработанном формате, для использования в различных областях исследований. или развитие. Он поддерживается многими языками программирования и API и поэтому становится все более популярным. Это также относится к хранению данных для использования в рабочих процессах машинного обучения. В этом посте я представляю возможный подход (включая готовый код) к использованию данных HDF5 для обучения алгоритмов глубокого обучения в PyTorch.

Формат файла HDF5

Файл HDF5 состоит из двух основных типов объектов: наборов данных и групп. Наборы данных - это многомерные массивы однородного типа, такие как 8-разрядные целые числа без знака или 32-разрядные числа с плавающей запятой. С другой стороны, группы представляют собой иерархические структуры, предназначенные для хранения наборов данных или других групп, выстраивая иерархию наборов данных, подобную файловой системе. Кроме того, группы и наборы данных могут иметь прикрепленные к ним метаданные в виде определяемых пользователем атрибутов.

Python поддерживает формат HDF5 с помощью пакета h5py. Этот пакет включает в себя собственный HDF C API и поддерживает почти все функции формата, включая чтение и запись файлов HDF5.

Если вам нужно просмотреть или отредактировать файлы HDF5 в визуальном редакторе, вы можете загрузить официальное приложение HDFView. Приложение поддерживает просмотр наборов данных разных форматов в виде таблицы или изображения. Кроме того, он позволяет редактировать файл, создавая новые группы и наборы данных, а также переименовывая и перемещая существующие.

Наборы данных PyTorch

Для эффективной загрузки данных в PyTorch PyTorch требует, чтобы вы написали свой собственный класс Dataset (или использовали один из предопределенных). Это достигается путем наследования от torch.utils.data.Dataset, переопределения функций __len__ (так что вызов len () в наборе данных возвращает длину набора данных) и __getitem__ (для включения индексации).

Затем класс torch.utils.data.DataLoader используется для выборки из набора данных предопределенным способом (например, вы можете случайным образом перемешать набор данных, выбрать размер пакета и т. Д.) . Основное преимущество (и магия) загрузки данных в PyTorch заключается в том, что загрузка данных может происходить параллельно без необходимости иметь дело с несколькими потоками и механизмами синхронизации. Это работает путем простой установки параметра num_workers в конструкторе DataLoader на желаемое количество потоков. В качестве примера использования классов Dataset и DataLoader в PyTorch рассмотрите приведенный ниже фрагмент кода, показывающий, как использовать набор данных HDF5 в вашей программе. В следующем разделе мы рассмотрим, как на самом деле реализовать набор данных.

Класс набора данных HDF5

Я разработал класс набора данных HDF5, имея в виду несколько целей:

  1. Использовать папки (включая подпапки), содержащие файлы HDF5, в качестве источника данных,
  2. поддерживать простую иерархию групп HDF5 в наборе данных,
  3. включить отложенную загрузку данных (т.е. по запросу DataLoader), чтобы разрешить работу с наборами данных, которые не помещаются в память,
  4. поддерживать кеш данных, чтобы ускорить процесс загрузки данных, и
  5. разрешить настраиваемые преобразования данных.

Я решил применить к набору данных простую структуру, состоящую из отдельных наборов данных, помещенных в отдельные группы, например:

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

Без лишних слов, вот фактический код:

Как видите, набор данных инициализируется путем поиска всех файлов HDF5 в каталоге (и подкаталогах), и создается структура data_info, содержащая информацию о каждом фрагменте данных, например, из какого файла он взят, какого типа он имеет. («данные» или «метка» в этом примере, но вы можете определить другие) и его форму. Форма часто используется для определения размера набора данных, поэтому это важная информация для хранения. Кроме того, для каждого фрагмента мы также сохраняем его индекс кэша данных. Индекс ≥0, если данные в настоящее время загружены, и -1, если мы еще не загрузили его.

Если DataLoader теперь запрашивает некоторые данные, вызывается функция __getitem__, которая, в свою очередь, вызывает функцию get_data. Обратите внимание, что мы не можем просто проиндексировать какой-либо массив здесь, потому что сначала мы должны убедиться, что данные действительно находятся в памяти. Поэтому в get_data мы ищем данные в кеше или, если их нет в кеше, загружаем их и возвращаем вызывающей стороне. Это происходит в функции _load_data, которая выполняет две функции: загружает данные и добавляет их в кеш и удаляет случайный фрагмент данных из кеша, если data_cache_size был превышен.

После получения данных их необходимо преобразовать в соответствии с преобразованием, указанным в конструкторе, и преобразовать в тип torch.Tensor.

Заключение

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