
Подобно тому, как в мире разработки многокомпонентных систем применяются подходы для управления и мониторинга микросервисами на основе инструментов DevOps (для запуска и восстановления сервисов, передачи данных, наблюдения за распределенными операциями, выполнение замеров и получение операционных метрик), так же и для моделей машинного обучения становится важным обеспечить возможность их развертывания, обновления и наблюдения за метриками (точность модели, время выполнения прямого прохождения нейронной сети и другими). В обобщенном виде такие решения получили названия MLOps и в этой статье мы рассмотрим возможности платформы Hydrosphere 3.0.
Hydrosphere поддерживает разные фреймворки для описания нейронных сетей (в том числе, Tensorflow/Keras, PyTorch, fastai и другие) и обеспечивает полный цикл управления моделью, включая контроль обучения, версионирование, развертывание и наблюдение за операционными метриками, а также позволяет обнаруживать деградацию сети и потерю производительности и точности (из-за переобучения или некачественных данных, выбранных для обучения) на ранних этапах. Hydrosphere также предоставляет возможность интерпретации процесса вывода результата и визуализации работы модели машинного обучения для определения причины неправильного вывода.
Hydrosphere использует для развертывания моделей Kubeflow (исполнение моделей машинного обучения в подах Kubernetes) или Apache AirFlow (инструмент для управления любыми конвейнерными операциями). Для управления Hydrosphere используется веб-интерфейс, а также API (REST или gRPC) для внешних приложений. Для развертывания моделей используются OCI-контейнеры с gRPC-интерфейсом, который оборачивает реальный код исполнения модели (на любом языке программирования) и позволяет обобщить способ передачи входного вектора в модель и получения результата исполнения модели. Модели могут версионироваться (каждая версия — отдельный образ контейнера) и объединяться в конвейеры обработки в концепции приложения (Application), при этом на каждой стадии конвейера может использоваться одна или несколько версий модели, выводы которых объединяются с учетом весов. Модель и конвейер описываются в виде yaml-файлов, которые описывают входы и выходы модели (тип и размерность массива или категоризированные значения, также поддерживаются типы для текстов, изображений, звука и видео), при развертывании модели сохраняются во внутреннем реестре.
Hydrosphere выполняет функции маршрутизации внешних запросов (Gateway), управления запущенными моделями (Manager), получения операционных метрик (Sonar, также может отправлять метрики в Prometheus) и автоматического обнаружения выбросов (Auto OD) и создания отчетов о статистическом распределении в обучающем наборе и реальных данных (Drift Report). Также Hydrosphere содержит два компонента для объяснения выводов модели (Explanation) и визуализации выводов на многомерных массивах (Data Projection).
Для установки Hydrosphere можно использовать готовый стек на Docker Compose или Kubernetes (через Helm) и утилиту командной строки (pip install hs), которая позволяет управлять приложениями и моделями, а также конфигурировать кластер Hydrosphere. В нашем примере будем использовать Docker Compose (про установку в Kubernetes можно почитать на этой странице):
export HYDROSPHERE_RELEASE=3.0.0 wget -O hydro-serving-${HYDROSPHERE_RELEASE}.tar.gz https://github.com/Hydrospheredata/hydro-serving/archive/${HYDROSPHERE_RELEASE}.tar.gz tar -xvf hydro-serving-${HYDROSPHERE_RELEASE}.tar.gz cd hydro-serving-${HYDROSPHERE_RELEASE} docker-compose up -d
После запуска мы можем увидеть контейнеры для всех подсистем Hydrosphere(ui, visualization, gateway, auto-od, sonar, serving-manager), дополнительные контейнера для хранения данных (mongodb, postgres, minio), alertmanager для оповещения о деградации моделей. Веб-интерфейс публикуется на порт 80. Для внешнего доступа (через Python SDK) будет использовать gRPC-интерфейс на порте 9090.
Для развертывания модели прежде всего необходимо сконфигурировать новый кластер:
pip install hs hs cluster add --name=demo --server=http://localhost/ hs cluster use demo git clone https://github.com/Hydrospheredata/hydro-serving-example.git cd hydro-serving-example/examples/custom_metrics/census/models/model hs apply -f serving.yaml
При выполнении apply будет выполнена сборка контейнера для поддержки модели и его развертывание в кластер. Рассмотрим более подробно структуру проекта с моделью ML и yaml-файл для описания развертывания:
kind: Model name: "census" payload: - "src/" - "requirements.txt" - "model.joblib" - "encoders.joblib" runtime: "hydrosphere/serving-runtime-python-3.7:3.0.0-alpha.1" install-command: "pip install -r requirements.txt" training-data: "../../data/train.csv" metadata: documentation: "https://docs.hydrosphere.io/quickstart/tutorials/train-and-deploy-census-income-classification-model" contract: name: "predict" inputs: age: shape: scalar type: int64 profile: numerical hours-per-week: shape: scalar type: int64 profile: categorical //...другие поля... native-country: shape: scalar type: string profile: categorical outputs: income: shape: scalar type: string profile: categorical
Модель определяет правила сборки контейнера — базовый образ (runtime), расположение тестовых данных в проекте, список дополнительных файлов для добавления в контейнер — payload, название модели, команда для конфигурирования собираемого контейнера (здесь используется установка зависимостей из requirements.txt, но может быть выполнен запуск сценария, но нужно при этом не забыть добавить его через payload). Взаимодействие с моделью описывается через contract, который содержит набор входов (inputs) и выходов (модели), каждый из которых определяется формой матрицы (может быть в формате массива размерностей или scalar для скалярных величин), типом значения (int64, float, string и другие, подробно список типов можно посмотреть здесь), профилем значения (numerical, categorical, image, text).
На текущий момент доступны две среды исполнения — hydrosphere/serving-runtime-python-3.7 и hydrosphere/serving-runtime-python-3.8, но может использовать любой образ, который создает совместимый grpc-сервис.
Сам проект должен включать в себя необходимые для запуска модели зависимости (устанавливаются через install-command), описание конвейеров или обученные веса для нейронных сетей (также должны добавлять в payload), а также код с экспортируемой функцией predict или любую другую, название указывается в описании модели в contract.name (принимает входные значения как **kwargs) и возвращает dict с выходными значениями. При запуске код должен создать необходимые объекты для представления ML-модели, загрузить веса или описания конвейеров, выполнить все необходимые операции для дальнейшего использования модели.
Для развертывания приложения используются другой тип yaml-файлов (kind: Application), в которых перечисляются стадии исполнения в pipeline, при этом внутри стадии может использоваться одна или несколько моделей (при указании модели дополнительно можно уточнять номер версии):
kind: Application name: demo pipeline: - - model: "census:1" weight: 100
Для установки приложения также используется hs apply application.yaml. Также приложение может быть создано через веб-интерфейс. Перейдем на страницу http://localhost/applications/demo и попробуем проверить исполнение приложения (кнопка Test):

Здесь необходимо заполнить категориальные данные корректными значениями, либо обратиться к кластеру программно и передать данные, загруженные из тестового набора:
from hydrosdk import Cluster, Application cluster = Cluster("http://localhost", grpc_address="localhost:9090") app = Application.find(cluster, "demo") predictor = app.predictor() # load data and call predictor.predict(data), where data is a dictionary
Попробуем создать простую модель на основе keras для детектирования цифр (обучена на наборе данных MNIST. Создадим новый пустой каталог и внутри него, в src/train.py сохраним сценарий для обучения нейронной сети на наборе данных MNIST. Результат обучения сохраним в файл .h5 (HDF5):
import numpy as np from keras.datasets import mnist from keras.models import Sequential from keras.layers.core import Dense, Dropout, Activation from keras.utils import np_utils nb_classes = 10 (X_train, y_train), (X_test, y_test) = mnist.load_data() X_train = X_train.reshape(60000, 784) X_test = X_test.reshape(10000, 784) X_train = X_train.astype('float32') X_test = X_test.astype('float32') X_train /= 255 X_test /= 255 Y_train = np_utils.to_categorical(y_train, nb_classes) Y_test = np_utils.to_categorical(y_test, nb_classes) model = Sequential() model.add(Dense(512, input_shape=(784,))) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(Dense(512)) model.add(Activation('relu')) model.add(Dropout(0.2)) model.add(Dense(10)) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam') model.fit(X_train, Y_train, batch_size=128, epochs=4, validation_data=(X_test, Y_test)) model.save('trained.h5')
Запустим обучение:
python3 src/train.py
Теперь создадим реализацию модели для использования в hydrosphere:
import tensorflow as tf import numpy as np model = tf.keras.models.load_model('trained.h5') def predict(data): predictions = model.predict(data['image']) return {'result':np.argmax(predictions)} # simulate digit "1" digit_one = [1.0 if d%28==14 else 0.0 for d in range(0,28*28)] data = {'image': np.array(digit_one, dtype=np.float32).reshape([1,-1])} assert predict(data)['result']==1
Здесь в модели добавлен тест, который симулирует изображение цифры “1” (вертикальная черта) и проверяет вывод сети на корректность.
Для публикации модели необходимо создать файл с определением контракта и метаданных:
kind: Model name: "digit" payload: - "src/model.py" - "trained.h5" runtime: "hydrosphere/serving-runtime-python-3.7:3.0.0-alpha.1" install-command: "pip install tensorflow keras numpy" contract: name: "predict" inputs: image: shape: [1,784] type: float32 profile: numerical outputs: result: shape: scalar type: int32 profile: categorical
И также подготовим развертывание приложения:
kind: Application name: digits pipeline: - - model: digit:1
Установим модель и приложение в Hydrosphere:
hs apply -f model.yaml hs apply -f application.yaml
И подключимся к нему из внешнего приложения:
from hydrosdk import Cluster, Application cluster = Cluster("http://localhost", grpc_address="localhost:9090") app = Application.find(cluster, "digits") predictor = app.predictor() digit_one = [1.0 if d%28==14 else 0.0 for d in range(0,28*28)] print(predictor.predict(digit_one))
Аналогично может быть сделана сложная обработка с объединением нескольких моделей, в этом случае вывод предыдущей модели будет передаваться на ввод моделей следующей стадии.
Таким образом, использование Hydrosphere позволяет интегрировать управление моделями и ML-приложениями в CI/CD-конвейер доставки других компонентов системы, а также обеспечивает механизм обнаружения и исполнения ML-приложений и мониторинга их функционирования.
В заключение приглашаю всех на бесплатный урок по теме: «MLFlow и переобучение ML-моделей». Зарегистрироваться на урок можно по ссылке ниже.
ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/710060/
Добавить комментарий