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

Определены воспроизводимые модели

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

модель: = скрипт (код, среда, данные)

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

docker run \
    -e GIT_HASH=${GIT_HASH} \
    -e QUILT_HASH=${QUILT_HASH} \
    YOUR/IMAGE@${DOCKER_HASH}

Воспроизводимость увеличивает маневренность

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

Версионные данные - это отсутствующий компонент

Вы, вероятно, знакомы с такими системами, как Git и Docker, которые инкапсулируют код и среду соответственно. Эти системы предоставляют неизменяемые хэши, которые представляют собой моментальные снимки во времени. Через мгновение мы представим Quilt как источник неизменяемых хешей для данных. Хеш Quilt представляет собой моментальный снимок данных во времени.

Системы управления версиями кода не оптимальны для управления версиями данных, поскольку данные принципиально отличаются от кода: данные обычно в тысячи раз больше, чем код, данные требуют специализированных API-интерфейсов для транспорта и сериализации, а данные требуют исследования (посредством поиска, просмотра и визуализации).

Исходный код Quilt и статус проекта

Quilt - это платформа с открытым ядром, предназначенная для управления такими данными, как код: с версиями, пакетами, репозиториями и совместными рабочими процессами. Исходный код Quilt доступен на GitHub. Вы можете использовать клиент quilt3 Python как отдельную библиотеку для создания, документирования и обмена наборами данных. При желании вы можете запустить Quilt stack, который добавляет каталог веб-данных с поиском, предварительным просмотром файлов и контролем доступа на основе ролей. Разработка Quilt финансируется Quilt Data.

Обзор и предварительные условия

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

  1. Установка версионных наборов данных - требуется Python 3.6 или выше.
  2. Воспроизводимое обучение глубокой нейронной сети - требуется машина с графическим процессором с установленным nvidia-docker и не менее 100 ГБ свободного дискового пространства. Чтобы сократить время обучения, рассмотрите экземпляры с восемью графическими процессорами V100.
  3. Совместное использование и документирование пользовательских наборов данных - требуется Python 3.6 или выше, quilt3 (pip install quilt3) и корзина Amazon S3 с настроенным интерфейсом командной строки AWS. Чтобы поэкспериментировать с S3, вы можете подписаться на уровень бесплатного пользования AWS.

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

Установка версионных наборов данных с quilt3

Загрузка больших наборов данных часто зависит от ненадежных скриптов и медленных или ненадежных хранилищ данных. quilt3 предлагает упрощенный интерфейс для создания, установки и взаимодействия с наборами данных. Например, вы можете использовать quilt3 для установки набора данных Общие объекты в контексте (COCO). Начните с установки quilt3:

pip install quilt3

Для установки COCO вам потребуется как минимум 22 ГБ свободного дискового пространства. Если вы планируете обучить Detectron2 в следующем разделе, вам не нужно запускать следующий код. Вот как установить COCO с quilt3:

# Note: installing COCO requires at least 22GB of disk
quilt3 install cv/coco2017 \
    --top-hash 3722a4 \
    --dest ./detectron2/datasets/coco/ \
    --registry s3://quilt-ml

cv/coco2017 - имя набора данных

  • --top-hash - это дайджест SHA-256, автоматически рассчитываемый quilt3 для интересующей редакции
  • --dest - это каталог, в который данные копируются на локальный диск
  • --registry указывает, где находится пакет данных, обычно это сегмент S3.

Если вы хотите поэкспериментировать с меньшим набором данных (1,1 МБ), попробуйте quilt / altair:

quilt3 install quilt/altair \
    --registry s3://quilt-example \
    --dest ./YOUR/DIR/

Дополнительные сведения о создании собственных наборов данных с помощью quilt3 см. В разделе Совместное использование и документирование пользовательских наборов данных ниже.

Необязательно: проверка набора данных

Перед обучением вы можете убедиться, что в вашей локальной копии набора данных нет изменений:

quilt3 verify cv/coco2017 \
    --top-hash 3722a4 \
    --dir ./datasets/coco2017 \
    --registry s3://quilt-ml

quilt3 verify вычисляет хэш SHA-256 каждого файла в наборе данных. Проверка cv/coco2017 занимает около двух с половиной минут на экземпляре с 4 виртуальными ЦП и 16 ГиБ памяти.

Воспроизводимое обучение глубокой нейронной сети: Detectron2 на COCO

Существует множество способов комбинировать Git, Docker и Quilt для воспроизводимого обучения. Ниже приводится один из примеров. Мы определяем наш код, среду и хэши данных, извлекаем образ Docker (quiltdata / pytorch-detectron2-demo), затем запускаем задание обучения:

# define hashes
GIT_HASH=0a7a9d10
QUILT_HASH=3722a498
DOCKER_HASH=sha256:8d12a8997c6f65923f7e7788f70f70134b5f845ddcba5570beb5182c18d2526e
# pull image
DOCKER_IMAGE=quiltdata/pytorch-detectron2-demo@${DOCKER_HASH}
docker pull ${DOCKER_IMAGE}
# run image (interactively for illustration)
nvidia-docker run -it \
    --ulimit memlock=-1 \
    --ulimit stack=67108864 \
    --shm-size=8gb \
    # Optional: mount a volume (be sure to clone detectron2 there)
    # --volume /YOUR/DIR/:/io \
    -e GIT_HASH=${GIT_HASH} \
    -e QUILT_HASH=${QUILT_HASH} \
    ${DOCKER_IMAGE}
## clone and install detectron2
git clone https://github.com/facebookresearch/detectron2
cd detectron2
git checkout ${GIT_HASH}
### "Running setup.py develop for detectron2" takes several minutes
pip install -e .
## install data
quilt3 install cv/coco2017 \
    --registry=s3://quilt-ml \
    --dest=./datasets/coco/ \
    --top-hash=${QUILT_HASH}
## train
python tools/train_net.py \
    --num-gpus 8 \
    --config-file \
        configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml

Управление версиями и загрузка обученных моделей

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

import os
import quilt3
model_pkg = quilt3.Package()
# capture all logs and checkpoints from /output
model_pkg.set_dir(".", "./detectron2/output/")
model_pkg.push(
    "detectron2-trained-models/mask_rcnn_R_50_FPN_1x",
    registry="s3://YOUR-S3-BUCKET", 
    message=(
        f"detectron2@{os.environ.get('GIT_HASH')}, "
        f"trained in quiltdata/pytorch-detectron2-demo@{os.environ.get('DOCKER_HASH')}, "
        f"on cv/coco2017@{os.environ.get('QUILT_HASH')}"
    )
)

Теперь, когда мы сохранили модель в Quilt, соавторы могут загружать прошлые модели вместе с их контрольными точками и журналами для вывода, аудита и отладки:

quilt3 install detectron2-trained-models/mask_rcnn_R_50_FPN_1x \
    --registry=s3://quilt-ml \
    --dest=/detectron2/models/mask_rcnn_R_50_FPN_1x/ \
    --top-hash=6e830aa5

cd /detectron2

python tools/train_net.py \
    --config-file ./configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
    --eval-only MODEL.WEIGHTS \
        models/mask_rcnn_R_50_FPN_1x/model_final.pth

python demo/demo.py \
    --config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml \
    --input YOUR_INPUT_1.jpg YOUR_INPUT_2.jpg \
    --opts MODEL.WEIGHTS \     
        models/mask_rcnn_R_50_FPN_1x/model_final.pth

Загрузка данных из quilt3 в PyTorch

Detectron2 предоставляет собственные пути кода для загрузки набора данных COCO. Для пользовательских наборов данных вы можете использовать DatasetFolder torchvision или создать подкласс torch Dataset:

from torch.utils.data import Dataset
class ExamplePyTorchDataset(Dataset):
    def __init__(self, quilt_package_name, registry, pkg_hash=None):
        # insert your own package here
        pkg = quilt3.Package.browse(
            "quilt/coco2017",
            registry="s3://quilt-ml",
            top_hash="3722a4"
        )
        # only return files in the train/ directory
        self.img_entries = [
            e for l, e in pkg.walk()
            if l.startswith("train/")
        ]
    def __len__(self):
        return len(self.img_entries)
    def __getitem__(self, idx):
        entry = self.img_entries[idx]
        img_annotations = entry.meta["annotations"]
        return {
            "image": entry.get_bytes(),
            "annotations": img_annotations
        }

Использование API quilt3 в вашем подклассе набора данных имеет несколько преимуществ по сравнению с исходным Python, включая кэширование, управление версиями и абстракцию сети и хранилища - все это приводит к более кратким и надежным обучающим скриптам.

Для более высокой производительности вы можете использовать DataLoader torch. См. Написание пользовательских наборов данных, загрузчиков данных и преобразований для получения дополнительной информации.

Совместное использование и документирование пользовательских наборов данных

Самый простой способ создать собственный версионный набор данных - сделать снимок содержимого локального каталога в пакете Quilt:

p = quilt3.Package()
# snapshot a directory into package root
p.set_dir(".", "./your/local/dataset/")

В качестве более конкретного примера давайте создадим, задокументируем и предоставим общий доступ к настраиваемому подмножеству COCO, которое содержит только изображения животных. Начнем с использования quilt3 browse для загрузки облегченного представления существующего пакета COCO:

coco = quilt3.Package.browse(
    "quilt/coco2017",
    registry="s3://quilt-ml",
    top_hash="3722a4"
)

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

(remote Package)
 └─annotations/
   └─captions_train2017.json
   └─captions_val2017.json
   └─instances_train2017.json
   └─instances_val2017.json
   └─person_keypoints_train2017.json
   └─person_keypoints_val2017.json
 └─train2017/
 ...

Каждая запись в манифесте пакета имеет логический ключ (удобный путь), физический ключ (URI для байтов) и необязательные метаданные (устраняющие необходимость работы с внешними файлами аннотаций). Мы можем получить доступ к записям пакетов с помощью скобок. Например, coco[“train2017”][“000000000009.jpg”].meta дает dict:

{
  'image_info': {
    'license': 3,
    'file_name': '000000000009.jpg',
    'coco_url': 'http://images.cocodataset.org/train2017/000000000009.jpg',
    'height': 480,
    'width': 640,
    'date_captured': '2013-11-19 20:40:11',
    'flickr_url':
'http://farm5.staticflickr.com/4026/4622125393_84c1fdb8d6_z.jpg',
    'id': 9
  },
  'annotations': [...]
}

Мы можем использовать свойство .meta записей пакета Quilt, чтобы отфильтровать COCO до изображений животных:

coco_animals = coco.filter(
    lambda l, e: l.endswith(".jpg") and
    "animal" in (a["supercategory"] for a in e.meta["annotations"])
)

filter принимает лямбда-функцию с двумя аргументами: logical_key и entry.

Лучше всего добавить файл README в coco_animals, чтобы у других разработчиков был достаточный контекст для работы с нашим новым набором данных:

coco_animals.set("README.md", "./YOUR/DIR/README.md")

Теперь мы можем отправить coco_animals на S3, чтобы появилась облачная копия набора данных, доступная всем, у кого есть разрешения на чтение родительской корзины S3:

coco_animals.push(
    # fill in your details below
    "USERNAME/DATASET_NAME",
    registry="s3://YOUR_S3_BUCKET",
    message="Experimental subset of COCO 2017"
)

После того, как вы отправили набор данных в S3, ваши коллеги могут использовать quilt3.list_packages() для обнаружения наборов данных. Используйте quilt3 catalog для просмотра содержимого набора данных:

quilt3 catalog s3://quilt-example/akarve/coco_animals/

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

Каталог Quilt создает легкие, совместимые с браузером превью больших файлов, таких как Блокноты Jupyter, Паркетные столы, Визуализации Vega-Lite, изображения и многое другое.

Команда quilt3 catalog рекомендуется только для открытых данных. Для конфиденциальных данных запустите частный стек Quilt, который ограничивает данные вашим виртуальным частным облаком.

Ранее мы отмечали, что quilt3.browse() загружает упрощенный манифест вместо физических данных. Когда мы готовы работать с физическими данными, мы можем лениво получить их с помощью методов get quilt3. Например, если вы хотите отобразить содержимое файла README в Jupyter, вы можете вызвать get_as_string:

from IPython.display import display, Markdown
display(
    Markdown(
        coco_animals["README.md"].get_as_string()
    )
)

get_as_string() - это удобная оболочка для get_bytes(), которую мы использовали в Загрузка данных из quilt3 в PyTorch для получения данных двоичного изображения.

Заключение и как внести свой вклад

Мы продемонстрировали, как повысить скорость и точность итерации модели с помощью воспроизводимых обучающих сценариев. Мы также представили Quilt как систему управления версиями наборов данных.

Поделитесь наборами данных с сообществом

Если у вас есть интересный общедоступный набор данных, которым вы хотите поделиться, мы рекомендуем вам подать заявку на отслеживание данных на open.quiltdata.com, где большие общедоступные наборы данных размещаются бесплатно.

Добавить код в Quilt

Команда Quilt активно работает над масштабированием, производительностью и облачными инструментами для управления данными, такими как код. Взносы приветствуются. Посетите дорожную карту, ​​документацию и канал Slack Quilt, чтобы узнать больше. В дорожной карте Quilt особое внимание уделяется техническим областям, таким как Python, Parquet, MinIO и бессерверные функции.