В древнеримской мифологии бог Меркурий был известен как «посланник богов». В крылатых туфлях и крылатой шляпе он проносился между горой Олимп и царствами людей и следил за тем, чтобы воля богов была известна. Он не был самым сильным, мудрейшим, самым почитаемым или самым страшным из богов, но он был быстрым и хитрым, и на него можно было положиться, чтобы направить события к желаемым результатам. Без него Персей не смог бы победить Медузу; Одиссей пал бы под чары Цирцеи; и Геракл не мог вытащить Цербера из Аида, завершив тем самым последний из своих 12 мифических подвигов ...

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

Рабочие процессы машинного обучения обманчиво просты, но основаны на сложном сочетании множества инструментов и технологий

Недавние разработки в области машинного обучения и инструментов обработки данных привели к появлению множества библиотек с открытым исходным кодом, каждая из которых предоставляет хорошо разработанные и прозрачные API-интерфейсы, и каждый из них играет определенную роль при построении надежного рабочего процесса машинного обучения. Часто используемые библиотеки машинного обучения, такие как TensorFlow, PyTorch, Keras или SciKit-Learn, часто составляют основу такого рабочего процесса, но, тем не менее, существует множество функций из разных библиотек, которые обычно необходимо связать вместе, чтобы завершить рабочий процесс. .

В качестве примера рассмотрим рабочий процесс распознавания изображений, в котором вам нужно получить изображения из HDFS; поместите на эти изображения модель Keras; оценить модель с помощью SciKit-Learn; сохранить обученную модель в S3 на AWS; хранить метаданные во время обучения в MongoDB; и в конечном итоге обслужить модель с помощью TensorFlow Serving. Как бы вы настроили такой рабочий процесс?

Вдобавок, что, если ваши требования изменятся в середине проекта, и вам нужно будет получать данные из другого места или использовать другой механизм машинного обучения? Как бы вы отключили один из этих компонентов и заменили его другим? Сколько нового кода вам нужно ввести (и протестировать!), Чтобы он работал правильно?

Посланник богов для рабочих процессов машинного обучения

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

В последнее время нам стало совершенно ясно, что нам нужна библиотека, которая могла бы разбить проекты машинного обучения на их типичные компоненты (такие как чтение данных, преобразование данных, подгонка модели, оценка модели, модель обслуживания и т. Д.), Которые являются модульными и универсальными. достаточно, чтобы позволить нам использовать различные технологии в зависимости от того, что нам нужно.

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

Последняя стабильная версия всегда будет доступна на PyPi и может быть установлена ​​с помощью `pip install mercury-ml`.

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

Как это работает

Mercury-ML предлагает упрощенный доступ к функциям на разных уровнях абстракции.

В качестве краткого примера того, как это работает, давайте рассмотрим два небольших компонента, которые обычно являются частью рабочего процесса машинного обучения: сохранение подобранной модели, а затем сохранение сохраненного объекта в удаленном месте (из которого он впоследствии может быть обслужен). Для этого мы рассмотрим четыре уровня абстракции:

  1. Без использования Mercury-ML (т.е. напрямую с использованием базовых зависимостей)
  2. Использование API провайдеров
  3. Использование API контейнеров
  4. Использование API задач (совместно с API контейнеров)

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

Параметризация:

В этом примере мы сохраним модель Keras и сохраним ее в корзине S3 на AWS. Предположим, у нас есть следующие входные данные:

model = … # assume a fitted Keras model fetched here
filename = “my_model”
local_dir = “./local_models”
extension = “.h5”
remote_dir = “my-bucket/remote-model”

1. Пример прямого доступа к базовым библиотекам (т. Е. Без использования Mercury-ML)

Использование базовых библиотек вместо использования API-интерфейсов Mercury-ML имеет смысл, если вам нужна максимальная гибкость для настройки того, как эти библиотеки используются. Ниже приведен типичный сценарий, который можно составить для этого.

import os
# save model
if not os.path.exists(local_dir):
os.makedirs(local_dir)
filename = filename + extension
local_path = os.path.join(local_dir + "/" + filename)
model.save(local_path)
# copy to s3
import boto3
session = boto3.Session() #assuming connection parameters are implicit
s3 = session.resource("s3")
s3_bucket, s3_partial_key = remote_dir.split("/", 1)
s3_key = s3_partial_key + "/" + filename + extension
s3.Object(s3_bucket, s3_key).put(Body=open(local_path, "rb"))

Здесь нет ничего ужасно скомпилированного, но есть много маленьких шагов, которые нужно сделать правильно. Вам необходимо вручную проверить, существует ли каталог, в который вы хотите локально сохранить свою модель (и нужно знать, что Keras не делает этого за вас). Вы должны знать, что Keras сохраняет свои объекты модели в виде файлов HDF5 с расширением «.h5». Вы должны знать, как открыть соединение S3, и знать, что вызов функции, которая сохраняет в расположение S3, принимает «ведро» и «ключ» (которые вместе взятые можно рассматривать в упрощенном виде как «путь»). Чтобы понять это правильно, вам нужно возиться с множеством вызовов, которые объединяют и разделяют строковые пути.

(И если вы, например, решите сохранить объекты модели в Google Cloud Storage, вам нужно будет сделать это снова).

2. Пример через провайдеров

Поставщики в Mercury-ML стремятся абстрагироваться от большей части этого и позаботиться о мельчайших деталях, предоставляя простой (но также легко настраиваемый) API.

from mercury_ml.keras.providers import model_saving
from mercury_ml.common.providers.artifact_copying import from_disk
import os
# save model
path = model_saving.save_keras_hdf5(
    model=model,
    filename=filename,
    local_dir=local_dir, 
    extension=extension
)
# copy to s3
from_disk.copy_from_disk_to_s3(
    source_dir=local_dir, 
    target_dir=remote_dir, 
    filename=os.path.basename(path)
)

Использование API поставщиков (вместо контейнеров API задач) имеет наибольший смысл, если вы хотите жестко запрограммировать поставщиков, которых хотите использовать. Например, в приведенном выше фрагменте кода вы можете использовать только model_saving.save_keras_hdf5 и from_disk.copy_from_disk_to_s3.

Если вы хотите сохранить модель в другом формате или скопировать ее в другое хранилище, вы должны изменить свой код для этого. Например, чтобы сохранить в Google Cloud Storage, замените from_disk.copy_from_disk_to_s3 на from_disk.copy_from_disk_to_gcs.

3. Пример через контейнеры

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

Контейнеры - это просто легкие классы, которые позволяют вам получить доступ к различным аналогичным поставщикам из одного места. Например, к использованной выше функции model_saving.save_keras_hdf5 также можно получить доступ через контейнер как ModelSavers.save_hdf5. Используя функцию getattr, к нему также можно получить доступ как getattr (ModelSavers, «save_hdf5»), что позволяет нам легко параметризовать это в конфигурации.

from mercury_ml.keras.containers import ModelSavers
from mercury_ml.common.containers import ArtifactCopiers
import os
config = {
    "save_model": "save_hdf5",
    "copy_model": "copy_from_disk_to_s3"
}
save_model = getattr(ModelSavers, config["save_model"])
copy_from_local_to_remote = getattr(
    ArtifactCopiers, 
    config["copy_model"]
)
# save model
path = save_model(
    model=model,
    filename=filename,
    local_dir=local_dir,
    extension=extension
)
# copy to s3
copy_from_local_to_remote(
    source_dir=local_dir,
    target_dir=remote_dir,
    filename=os.path.basename(path)
)

Хотите вместо этого сохранить модель в виде графика тензорного потока? И хотите вместо этого сохранить его в Google Cloud Storage? Просто измените конфиг:

config = {
    "save_model": "save_tensorflow_graph",
    "copy_model": "copy_from_disk_to_gcs"
}

4. Пример с помощью задач (в сочетании с контейнерами)

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

from mercury_ml.keras.containers import ModelSaversfrom mercury_ml.common.containers import ArtifactCopiers
from mercury_ml.common.tasks import store_model
save_model = getattr(ModelSavers, config["save_model"])
copy_from_local_to_remote = getattr(
    ArtifactCopiers, 
    config["copy_model"]
)
# save model and copy to s3
store_model(
    save_model=save_model,
    copy_from_local_to_remote=copy_from_local_to_remote,
    model=model,
    filename=filename,
    local_dir=local_dir,
    remote_dir=local_dir,
    extension=extension
)

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

Узнать больше

Выше приведен лишь небольшой пример. Полноценные примеры рабочих процессов можно найти здесь.

Ключевой компонент того, как Mercury-ML может упростить рабочие процессы, также связан с тем, как он обрабатывает данные по мере их прохождения через различные фазы конвейера машинного обучения. Mercury-ML оборачивает данные в общие объекты DataWrapper (например, функции и цели) и упорядочивает их в наборы данных (например, обучение, действительный и тестовый) и, в конечном итоге, в блоки данных. Более подробную информацию о том, как это сделать, можно найти здесь.

Станьте соавтором!

Это также является открытым приглашением для всех разработчиков, заинтересованных в использовании Mercury-ML. Сообщите нам, какие функции вам нужны, и дайте нам знать, что не работает, или внесите свои изменения или дополнения!