Этот пост посвящен использованию конвейеров Kubeflow для объединения моделей машинного обучения из нескольких модальностей функций, и это первая часть в серии «MLOpsing мультимодальной архитектуры». Короче говоря, я предполагаю, что, используя надежные инструменты MLOps, модель ансамбля может быть гораздо менее сложной, чем предполагает ее репутация. Первая часть поста будет посвящена введению в серию в целом, а вторая часть будет посвящена конвейерам Kubeflow.

Часть 1: Сериал

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

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

Мари-Жан-Антуан-Николя де Карита (1743–1794) впервые представила теорему Кондорсе о жюри в 1785 году. Теория относится к группе экспертов, которым поручено определить бинарный исход. Если предположить, что каждый эксперт имеет большую вероятность успеха, чем случайность, то чем больше экспертов, тем выше точность.

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

Соревнование

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

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

млн операций в секунду

MLOps или Machine Learning Operations — это программная парадигма для операционализации машинного обучения. Подобно DevOps, он фокусируется на автоматизированных рабочих процессах, чтобы сделать шаги процесса воспроизводимыми и управляемыми. В случае машинного обучения — экспериментальный процесс. Я не буду вдаваться в подробности о MLOps в этой серии, потому что информации по этой теме очень много, но вот полезный источник информации.

Трубопроводы Kubeflow

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

Kubeflow Pipelines — это платформа для создания и развертывания переносимых, масштабируемых рабочих процессов машинного обучения (ML) на основе контейнеров Docker в кластерах Kubernetes.

Отличительной особенностью KFP является то, что он основан на контейнерах Docker. Это означает, что каждый шаг конвейера содержится в контейнере. На мой взгляд, это очень логичное разделение экспериментального процесса, которое прекрасно поддается ансамблевой модели. Каждая модель компонентов может быть контейнеризирована, что отделяет их соответствующие зависимости. В то время как общие утилиты, такие как прием и оценка данных, могут быть объединены в контейнерах, которые повторно используются в конвейере.

KFP развертывает контейнерные шаги в кластере Kubernetes, который управляет имеющейся в его распоряжении вычислительной инфраструктурой. Затем эксперимент может определить требуемые вычислительные ресурсы, такие как память, ядра ЦП или графический процессор. Kubernetes предоставит контейнеру соответствующий узел. Положительным моментом является то, что дорогостоящие вычислительные ресурсы, такие как графические процессоры, могут быть ограничены процессами, для которых они требуются, без дополнительного управления CUDA.

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

Конвейерная архитектура

Существует несколько способов реализации ансамблевой архитектуры в рамках KFP. Два наиболее распространенных шаблона проектирования: во-первых, рассматривать каждую компонентную модель как единый конвейер, управляемый всеобъемлющим конвейером; во-вторых, один конвейер может содержать все модели компонентов и шаги ансамбля.

В этом посте я сосредоточусь на последнем, потому что он использует больше всего преимуществ KFP, но у первого есть свои преимущества. Например, несколько конвейеров упрощают изолированную разработку отдельных (под)экспериментов и лучше подходят для повторного использования. Основным недостатком является то, что вся система будет содержать n моделей + 1 конвейер, и само управление этими конвейерами может стать неэффективным.

Решение с одним конвейером поместит все модели компонентов и ансамбль в один конвейер. Это максимально использует преимущества функций KFP, таких как кэширование и совместное использование компонентов, и для большинства архитектур по-прежнему допускает несвязанную разработку.

Ключевые концепции конвейеров Kubeflow

Компоненты

В Kubeflow Pipelines компонент — это автономная часть рабочего процесса машинного обучения, например сценарий обучения или сценарий оценки. Компоненты можно использовать для создания более сложных конвейеров машинного обучения, их можно совместно использовать и повторно использовать в разных проектах и ​​командах. Компоненты обычно определяются с помощью пакета SDK Kubeflow Pipelines, который предоставляет набор инструментов и библиотек для создания, развертывания и управления компонентами и конвейерами.

Компоненты — это немного запутанный выбор именования при обсуждении ансамблей. В машинном обучении подмодели ансамбля называются его «компонентными моделями». В то время как в Kubeflow Pipelines этапы конвейера используют программное обеспечение, определяемое как «компоненты». Например, конвейер может иметь «компонент приема» и «компонент обучения».

Компоненты используют контейнеры для выполнения своего кода в качестве операторов. На практике в большинстве конвейеров используется несколько контейнеров из общедоступных и пользовательских реестров контейнеров. Например, конвейер может использовать пользовательский контейнер на основе python:3.9 для приема данных, пользовательский контейнер на основе NVIDIA для обучения, а затем общедоступный контейнер TFServing для развертывания. Кроме того, все модели компонентов могут совместно использовать контейнеры для приема и обучения или могут быть разделены платформой машинного обучения. См. ниже:

Скриншот структуры каталогов

Существует три общих шаблона для реализации бизнес-логики каждого компонента; custom_component, использующий выполнение сценария, определенное в YAML, container_component, который выполняет команду, и облегченный функциональный компонент, который определяет логику в оформленной функции Python. Недавно обновленная Документация KFP ясно объясняет эти три шаблона, поэтому я сосредоточусь на их применении по отношению к ансамблям и ключевым факторам принятия решений, с которыми я столкнулся.

Пользовательский компонент

KFP может выполнять скрипт Python в контейнере на основе определения в файле YAML. См. ниже:

name: train model
description: This component trains the an XGBoost model.
inputs:
  - name: dataset_path
    type: Dataset
outputs:
  - name: predictions_path
    type: Dataset
  - name: model_dir
    type: Artifact
implementation:
  container:
    image: mycontainer.registy.io/myproject/xgboost:latest
    command:
      [
        python,
        train.py,
        --data_path,
        { inputpath: dataset_path },
        --model_dir,
        { outputPath: model_dir },
        --predictions_path,
        { outputPath: predictions_path },
      ]

Ключевым преимуществом такого подхода является его постоянство. Один и тот же код можно запускать локально и отлаживать в очень знакомом формате. Простой подход также требует нулевых KFP-зависимостей внутри контейнера, поэтому в значительной степени это контейнеризированный эксперимент. Основным недостатком являются дополнительные слои определения. Для каждого компонента требуется сигнатура функции, определение YAML и интерфейс скрипта, такой как анализатор параметров argparse. Для простых компонентов это становится чрезмерным.

Компонент контейнера

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

@container_component
def create_dataset(text: str, output_gcs: Output[Dataset]):
    return ContainerSpec(
        image='alpine',
        command=[
            'sh',oy
            '-c',
            'mkdir --parents $(dirname "$1") && echo "$0" > "$1"',
        ],
        args=[text, output_gcs.path])

Легкий функциональный компонент

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

@component(
    packages_to_install=["sklearn", "pandas", "plotly_express"],
    base_image="python:3.9",
)
def confusion_matrix_op(
    predictions: Input[Dataset],
    confusion_matrix_output: Output[HTML],
):
    import pandas as pd
    import plotly.express as px
    from sklearn.metrics import confusion_matrix

    df = pd.read_json(predictions.path, lines=True)
    fig = px.imshow(confusion_matrix(df.true, df.pred))
    fig.write_html(confusion_matrix_output.path)

Артефакты

Артефакты — это постоянные ресурсы, такие как данные, модели и визуализации, которые создаются и используются в ходе эксперимента. Управление артефактами является ключевой задачей ансамблевых архитектур. KFP использует классы Artefact для этих типов, каждый из которых имеет атрибуты для путей и метрик. Это означает, что артефакты можно отслеживать и визуализировать в пользовательском интерфейсе, а также сравнивать между запусками конвейера или экспериментами.

Метрики

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

Объемы

Как и любой экземпляр контейнера, контейнеры KFP могут монтировать тома. Они несколько касаются артефактов и не должны использоваться для ключевых артефактов эксперимента, таких как наборы данных. В мультимодальном контексте тома — полезный способ подключения файлов образов к контейнерам с определенными атрибутами хранения.

Перекрестная проверка

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

В KFP перекрестная проверка может выполняться как ParallelForLoop, где каждая складка представлена ​​как подэксперимент, в котором используются контейнеры компонентов, распределенные по кластеру. Это позволяет в полной мере использовать преимущества масштабирования и кэширования кластера.

with dsl.ParallelFor(dataset_dict_task.outputs['splits']) as split_name:
    trained_model = train_model_op(
        dataset_path=ingest_data.outputs['dataset_path'],
        split_name=split_name,
    )

Заключение

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