Введение в вершинные конвейеры

1. Обзор

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

Что ты учишь

Вы узнаете, как:

  • Используйте Kubeflow Pipelines SDK для создания масштабируемых конвейеров машинного обучения.
  • Создайте и запустите трехэтапный вводный конвейер, который принимает ввод текста.
  • Создайте и запустите конвейер, который обучает, оценивает и развертывает модель классификации AutoML.
  • Используйте готовые компоненты для взаимодействия с сервисами Vertex AI, предоставляемыми через библиотеку google_cloud_pipeline_components
  • Запланируйте задание конвейера с помощью Cloud Scheduler

Общая стоимость запуска этой лаборатории в Google Cloud составляет около 25 долларов США .

2. Знакомство с Vertex AI

В этой лаборатории используются новейшие продукты искусственного интеллекта, доступные в Google Cloud. Vertex AI интегрирует предложения машинного обучения в Google Cloud в единый процесс разработки. Раньше модели, обученные с помощью AutoML, и пользовательские модели были доступны через отдельные сервисы. Новое предложение объединяет оба API в одном API, а также другие новые продукты. Вы также можете перенести существующие проекты на Vertex AI.

Помимо услуг по обучению и развертыванию моделей, Vertex AI также включает в себя множество продуктов MLOps, в том числе Vertex Pipelines (особое внимание в этой лабораторной работе), Model Monitoring, Feature Store и многое другое. Вы можете увидеть все предложения продуктов Vertex AI на диаграмме ниже.

Обзор продукта Vertex

Если у вас есть какие-либо отзывы, пожалуйста, посетите страницу поддержки .

Чем полезны конвейеры машинного обучения?

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

Конвейеры tl;dr : помогают автоматизировать и воспроизвести рабочий процесс машинного обучения.

3. Настройка облачной среды

Для запуска этой лаборатории кода вам понадобится проект Google Cloud Platform с включенной оплатой. Чтобы создать проект, следуйте инструкциям здесь .

Шаг 1. Запустите Cloud Shell

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

Авторизовать облачную оболочку

Активировать Cloud Shell

В правом верхнем углу Cloud Console нажмите кнопку ниже, чтобы активировать Cloud Shell :

Активировать Cloud Shell

Если вы никогда раньше не запускали Cloud Shell, вам будет представлен промежуточный экран (ниже сгиба) с описанием того, что это такое. В этом случае нажмите «Продолжить» (и вы больше никогда этого не увидите). Вот как выглядит этот одноразовый экран:

Настройка Cloud Shell

Подготовка и подключение к Cloud Shell займет всего несколько минут.

Инициализация Cloud Shell

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

После подключения к Cloud Shell вы увидите, что вы уже прошли аутентификацию и что для проекта уже установлен идентификатор вашего проекта.

Выполните следующую команду в Cloud Shell, чтобы подтвердить, что вы прошли аутентификацию:

gcloud auth list

В выводе команды вы должны увидеть что-то вроде этого:

Вывод Cloud Shell

Выполните следующую команду в Cloud Shell, чтобы убедиться, что команда gcloud знает о вашем проекте:

gcloud config list project

Вывод команды

[core]
project = <PROJECT_ID>

Если это не так, вы можете установить это с помощью этой команды:

gcloud config set project <PROJECT_ID>

Вывод команды

Updated property [core/project].

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

echo $GOOGLE_CLOUD_PROJECT

Шаг 2. Включите API

На последующих шагах вы увидите, где нужны эти службы (и почему), а пока запустите эту команду, чтобы предоставить вашему проекту доступ к службам Compute Engine, Container Registry и Vertex AI:

gcloud services enable compute.googleapis.com         \
                       containerregistry.googleapis.com  \
                       aiplatform.googleapis.com  \
                       cloudbuild.googleapis.com \
                       cloudfunctions.googleapis.com

Это должно привести к успешному сообщению, похожему на это:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

Шаг 3. Создайте сегмент облачного хранилища

Чтобы запустить задание обучения на Vertex AI, нам понадобится сегмент хранилища для хранения сохраненных ресурсов модели. Ведро должно быть региональным. Здесь мы используем us-central , но вы можете использовать другой регион (просто замените его в ходе этой лабораторной работы). Если у вас уже есть ведро, вы можете пропустить этот шаг.

Выполните следующие команды в терминале Cloud Shell, чтобы создать корзину:

BUCKET_NAME=gs://$GOOGLE_CLOUD_PROJECT-bucket
gsutil mb -l us-central1 $BUCKET_NAME

Далее мы предоставим нашей учетной записи вычислительной службы доступ к этому сегменту. Это гарантирует, что Vertex Pipelines имеет необходимые разрешения для записи файлов в эту корзину. Запустите следующую команду, чтобы добавить это разрешение:

gcloud projects describe $GOOGLE_CLOUD_PROJECT > project-info.txt
PROJECT_NUM=$(cat project-info.txt | sed -nre 's:.*projectNumber\: (.*):\1:p')
SVC_ACCOUNT="${PROJECT_NUM//\'/}-compute@developer.gserviceaccount.com"
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT --member serviceAccount:$SVC_ACCOUNT --role roles/storage.objectAdmin

Шаг 4. Создайте экземпляр Vertex AI Workbench.

В разделе Vertex AI облачной консоли нажмите Workbench:

Меню вершинного AI

Оттуда в блокнотах, управляемых пользователем , нажмите «Новый блокнот» :

Создать новый блокнот

Затем выберите тип экземпляра TensorFlow Enterprise 2.3 (с LTS) без графических процессоров :

Экземпляр TFE

Используйте параметры по умолчанию и нажмите «Создать» .

Шаг 5. Откройте свой блокнот

После создания экземпляра выберите «Открыть JupyterLab» :

Открыть блокнот

4. Настройка вершинных конвейеров

Чтобы использовать Vertex Pipelines, нам необходимо установить несколько дополнительных библиотек:

  • Kubeflow Pipelines : это SDK, который мы будем использовать для создания нашего конвейера. Vertex Pipelines поддерживает запуск конвейеров, созданных с помощью Kubeflow Pipelines или TFX.
  • Компоненты Google Cloud Pipeline : эта библиотека предоставляет предварительно созданные компоненты, которые упрощают взаимодействие с сервисами Vertex AI на этапах вашего конвейера.

Шаг 1. Создайте блокнот Python и установите библиотеки.

Сначала в меню запуска экземпляра ноутбука создайте блокнот, выбрав Python 3 :

Создать блокнот Python3

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

Чтобы установить обе службы, которые мы будем использовать в этой лабораторной работе, сначала установите пользовательский флаг в ячейке блокнота:

USER_FLAG = "--user"

Затем запустите из своего блокнота следующее:

!pip3 install {USER_FLAG} google-cloud-aiplatform==1.7.0 --upgrade
!pip3 install {USER_FLAG} kfp==1.8.9 google-cloud-pipeline-components==0.2.0

После установки этих пакетов вам необходимо перезапустить ядро:

import os

if not os.getenv("IS_TESTING"):
    # Automatically restart kernel after installs
    import IPython

    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)

Наконец, проверьте, правильно ли вы установили пакеты. Версия KFP SDK должна быть >=1,8:

!python3 -c "import kfp; print('KFP SDK version: {}'.format(kfp.__version__))"
!python3 -c "import google_cloud_pipeline_components; print('google_cloud_pipeline_components version: {}'.format(google_cloud_pipeline_components.__version__))"

Шаг 2. Установите идентификатор проекта и сегмент.

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

Если вы не знаете идентификатор своего проекта, вы можете получить его, выполнив следующую команду:

import os
PROJECT_ID = ""

# Get your Google Cloud project ID from gcloud
if not os.getenv("IS_TESTING"):
    shell_output=!gcloud config list --format 'value(core.project)' 2>/dev/null
    PROJECT_ID = shell_output[0]
    print("Project ID: ", PROJECT_ID)

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

if PROJECT_ID == "" or PROJECT_ID is None:
    PROJECT_ID = "your-project-id"  # @param {type:"string"}

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

BUCKET_NAME="gs://" + PROJECT_ID + "-bucket"

Шаг 3. Импортируйте библиотеки

Добавьте следующее, чтобы импортировать библиотеки, которые мы будем использовать в этой лаборатории кода:

import kfp

from kfp.v2 import compiler, dsl
from kfp.v2.dsl import component, pipeline, Artifact, ClassificationMetrics, Input, Output, Model, Metrics

from google.cloud import aiplatform
from google_cloud_pipeline_components import aiplatform as gcc_aip
from typing import NamedTuple

Шаг 4. Определите константы

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

PATH=%env PATH
%env PATH={PATH}:/home/jupyter/.local/bin
REGION="us-central1"

PIPELINE_ROOT = f"{BUCKET_NAME}/pipeline_root/"
PIPELINE_ROOT

После запуска приведенного выше кода вы должны увидеть напечатанный корневой каталог вашего конвейера. Это место в облачном хранилище, куда будут записываться артефакты из вашего конвейера. Он будет в формате gs://YOUR-BUCKET-NAME/pipeline_root/

5. Создание вашего первого конвейера

Чтобы ознакомиться с тем, как работают Vertex Pipelines, сначала создадим короткий конвейер с помощью KFP SDK. Этот конвейер не делает ничего, связанного с машинным обучением (не волнуйтесь, мы доберемся до цели!), мы используем его, чтобы научить вас:

  • Как создавать пользовательские компоненты в KFP SDK
  • Как запустить и контролировать конвейер в Vertex Pipelines

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

  • product_name : этот компонент будет принимать название продукта (или любое существительное, которое вам действительно нужно) в качестве входных данных и возвращать эту строку в качестве выходных данных.
  • emoji : этот компонент возьмет текстовое описание смайлика и преобразует его в смайлик. Например, текстовый код ✨ — «блестки». Этот компонент использует библиотеку эмодзи, чтобы показать вам, как управлять внешними зависимостями в вашем конвейере.
  • build_sentence : этот последний компонент будет использовать выходные данные двух предыдущих для построения предложения, в котором используется смайлик. Например, результатом может быть «Вершинные конвейеры — это ✨».

Давайте начнем кодировать!

Шаг 1. Создайте компонент на основе функций Python

Используя KFP SDK, мы можем создавать компоненты на основе функций Python. Мы будем использовать это для трех компонентов в нашем первом конвейере. Сначала мы создадим компонент product_name , который просто принимает строку в качестве входных данных и возвращает эту строку. Добавьте в свой блокнот следующее:

@component(base_image="python:3.9", output_component_file="first-component.yaml")
def product_name(text: str) -> str:
    return text

Давайте подробнее рассмотрим синтаксис здесь:

  • Декоратор @component компилирует эту функцию в компонент при запуске конвейера. Вы будете использовать это каждый раз, когда будете писать собственный компонент.
  • Параметр base_image указывает образ контейнера, который будет использовать этот компонент.
  • Параметр output_component_file является необязательным и указывает файл yaml, в который будет записываться скомпилированный компонент. После запуска ячейки вы должны увидеть этот файл, записанный в экземпляр вашего блокнота. Если вы хотите поделиться этим компонентом с кем-то, вы можете отправить ему сгенерированный файл yaml и попросить загрузить его со следующим:
product_name_component = kfp.components.load_component_from_file('./first-component.yaml')
  • -> str после определения функции указывает тип вывода для этого компонента.

Шаг 2. Создайте два дополнительных компонента.

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

@component(packages_to_install=["emoji"])
def emoji(
    text: str,
) -> NamedTuple(
    "Outputs",
    [
        ("emoji_text", str),  # Return parameters
        ("emoji", str),
    ],
):
    import emoji

    emoji_text = text
    emoji_str = emoji.emojize(':' + emoji_text + ':', language='alias')
    print("output one: {}; output_two: {}".format(emoji_text, emoji_str))
    return (emoji_text, emoji_str)

Этот компонент немного сложнее предыдущего. Давайте разберем, что нового:

  • Параметр packages_to_install сообщает компоненту о любых зависимостях внешней библиотеки для этого контейнера. В данном случае мы используем библиотеку emoji .
  • Этот компонент возвращает NamedTuple с именем Outputs . Обратите внимание, что каждая строка в этом кортеже имеет ключи: emoji_text и emoji . Мы будем использовать их в нашем следующем компоненте для доступа к выходным данным.

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

@component
def build_sentence(
    product: str,
    emoji: str,
    emojitext: str
) -> str:
    print("We completed the pipeline, hooray!")
    end_str = product + " is "
    if len(emoji) > 0:
        end_str += emoji
    else:
        end_str += emojitext
    return(end_str)

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

Шаг 3. Объединение компонентов в конвейер

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

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

  • product_task принимает в качестве входных данных название продукта. Здесь мы передаем «Vertex Pipelines», но вы можете изменить это на все, что захотите.
  • emoji_task принимает на вход текстовый код смайлика. Вы также можете изменить это на все, что захотите. Например, «party_face» относится к смайлику 🥳. Обратите внимание: поскольку и этот компонент, и компонент product_task не содержат никаких шагов, передающих в них входные данные, мы вручную указываем для них входные данные при определении нашего конвейера.
  • Последний шаг в нашем конвейере — consumer_task имеет три входных параметра:
    • Вывод product_task . Поскольку на этом шаге создается только один результат, мы можем ссылаться на него через product_task.output .
    • Результат emoji нашего шага emoji_task . См. компонент emoji , определенный выше, где мы назвали выходные параметры.
    • Аналогично, emoji_text именует выходные данные компонента emoji . Если в наш конвейер передается текст, который не соответствует смайлику, он будет использовать этот текст для построения предложения.
@pipeline(
    name="hello-world",
    description="An intro pipeline",
    pipeline_root=PIPELINE_ROOT,
)

# You can change the `text` and `emoji_str` parameters here to update the pipeline output
def intro_pipeline(text: str = "Vertex Pipelines", emoji_str: str = "sparkles"):
    product_task = product_name(text)
    emoji_task = emoji(emoji_str)
    consumer_task = build_sentence(
        product_task.output,
        emoji_task.outputs["emoji"],
        emoji_task.outputs["emoji_text"],
    )

Шаг 4. Скомпилируйте и запустите конвейер.

Определив конвейер, вы готовы его скомпилировать. Следующее действие создаст файл JSON, который вы будете использовать для запуска конвейера:

compiler.Compiler().compile(
    pipeline_func=intro_pipeline, package_path="intro_pipeline_job.json"
)

Затем создайте переменную TIMESTAMP . Мы будем использовать это в нашем идентификаторе задания:

from datetime import datetime

TIMESTAMP = datetime.now().strftime("%Y%m%d%H%M%S")

Затем определите задание конвейера:

job = aiplatform.PipelineJob(
    display_name="hello-world-pipeline",
    template_path="intro_pipeline_job.json",
    job_id="hello-world-pipeline-{0}".format(TIMESTAMP),
    enable_caching=True
)

Наконец, запустите задание, чтобы создать новый конвейер выполнения:

job.submit()

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

Журналы заданий конвейера

Перейдите по этой ссылке. После завершения ваш конвейер должен выглядеть так:

Завершен вводный конвейер

Запуск этого конвейера займет 5-6 минут . По завершении вы можете щелкнуть компонент build-sentence , чтобы увидеть окончательный результат:

Вывод вводного конвейера

Теперь, когда вы знакомы с тем, как работают KFP SDK и Vertex Pipelines, вы готовы создать конвейер, который создает и развертывает модель машинного обучения с использованием других сервисов Vertex AI. Давайте погрузимся!

6. Создание сквозного конвейера машинного обучения

Пришло время построить свой первый конвейер машинного обучения. В этом конвейере мы будем использовать набор данных UCI Machine Learning Dry Beans из: KOKLU, M. и OZKAN, IA, (2020), «Многоклассовая классификация сухих бобов с использованием методов компьютерного зрения и машинного обучения». В «Компьютерах и электронике в сельском хозяйстве», 174, 105507. DOI .

Это табличный набор данных, и в нашем конвейере мы будем использовать этот набор данных для обучения, оценки и развертывания модели AutoML, которая классифицирует bean-компоненты по одному из 7 типов на основе их характеристик.

Этот трубопровод будет:

  • Создайте набор данных в
  • Обучение табличной модели классификации с помощью AutoML
  • Получите показатели оценки этой модели
  • На основе метрик оценки решите, следует ли развертывать модель с использованием условной логики в Vertex Pipelines.
  • Разверните модель в конечной точке с помощью прогнозирования вершин.

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

Шаг 1. Пользовательский компонент для оценки модели.

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

  • Получите показатели оценки из обученной модели классификации AutoML.
  • Анализируйте метрики и визуализируйте их в пользовательском интерфейсе Vertex Pipelines.
  • Сравните показатели с пороговым значением, чтобы определить, следует ли развертывать модель.

Прежде чем определить компонент, давайте разберемся с его входными и выходными параметрами. В качестве входных данных этот конвейер принимает некоторые метаданные нашего облачного проекта, полученную обученную модель (мы определим этот компонент позже), метрики оценки модели и thresholds_dict_str . thresholds_dict_str — это то, что мы определим при запуске нашего конвейера. В случае этой модели классификации это будет область под значением кривой ROC, для которой нам следует развернуть модель. Например, если мы передаем значение 0,95, это означает, что мы хотим, чтобы наш конвейер развертывал модель только в том случае, если этот показатель превышает 95%.

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

@component(
    base_image="gcr.io/deeplearning-platform-release/tf2-cpu.2-3:latest",
    output_component_file="tabular_eval_component.yaml",
    packages_to_install=["google-cloud-aiplatform"],
)
def classification_model_eval_metrics(
    project: str,
    location: str,  # "us-central1",
    api_endpoint: str,  # "us-central1-aiplatform.googleapis.com",
    thresholds_dict_str: str,
    model: Input[Artifact],
    metrics: Output[Metrics],
    metricsc: Output[ClassificationMetrics],
) -> NamedTuple("Outputs", [("dep_decision", str)]):  # Return parameter.

    import json
    import logging

    from google.cloud import aiplatform as aip

    # Fetch model eval info
    def get_eval_info(client, model_name):
        from google.protobuf.json_format import MessageToDict

        response = client.list_model_evaluations(parent=model_name)
        metrics_list = []
        metrics_string_list = []
        for evaluation in response:
            print("model_evaluation")
            print(" name:", evaluation.name)
            print(" metrics_schema_uri:", evaluation.metrics_schema_uri)
            metrics = MessageToDict(evaluation._pb.metrics)
            for metric in metrics.keys():
                logging.info("metric: %s, value: %s", metric, metrics[metric])
            metrics_str = json.dumps(metrics)
            metrics_list.append(metrics)
            metrics_string_list.append(metrics_str)

        return (
            evaluation.name,
            metrics_list,
            metrics_string_list,
        )

    # Use the given metrics threshold(s) to determine whether the model is
    # accurate enough to deploy.
    def classification_thresholds_check(metrics_dict, thresholds_dict):
        for k, v in thresholds_dict.items():
            logging.info("k {}, v {}".format(k, v))
            if k in ["auRoc", "auPrc"]:  # higher is better
                if metrics_dict[k] < v:  # if under threshold, don't deploy
                    logging.info("{} < {}; returning False".format(metrics_dict[k], v))
                    return False
        logging.info("threshold checks passed.")
        return True

    def log_metrics(metrics_list, metricsc):
        test_confusion_matrix = metrics_list[0]["confusionMatrix"]
        logging.info("rows: %s", test_confusion_matrix["rows"])

        # log the ROC curve
        fpr = []
        tpr = []
        thresholds = []
        for item in metrics_list[0]["confidenceMetrics"]:
            fpr.append(item.get("falsePositiveRate", 0.0))
            tpr.append(item.get("recall", 0.0))
            thresholds.append(item.get("confidenceThreshold", 0.0))
        print(f"fpr: {fpr}")
        print(f"tpr: {tpr}")
        print(f"thresholds: {thresholds}")
        metricsc.log_roc_curve(fpr, tpr, thresholds)

        # log the confusion matrix
        annotations = []
        for item in test_confusion_matrix["annotationSpecs"]:
            annotations.append(item["displayName"])
        logging.info("confusion matrix annotations: %s", annotations)
        metricsc.log_confusion_matrix(
            annotations,
            test_confusion_matrix["rows"],
        )

        # log textual metrics info as well
        for metric in metrics_list[0].keys():
            if metric != "confidenceMetrics":
                val_string = json.dumps(metrics_list[0][metric])
                metrics.log_metric(metric, val_string)
        # metrics.metadata["model_type"] = "AutoML Tabular classification"

    logging.getLogger().setLevel(logging.INFO)
    aip.init(project=project)
    # extract the model resource name from the input Model Artifact
    model_resource_path = model.metadata["resourceName"]
    logging.info("model path: %s", model_resource_path)

    client_options = {"api_endpoint": api_endpoint}
    # Initialize client that will be used to create and send requests.
    client = aip.gapic.ModelServiceClient(client_options=client_options)
    eval_name, metrics_list, metrics_str_list = get_eval_info(
        client, model_resource_path
    )
    logging.info("got evaluation name: %s", eval_name)
    logging.info("got metrics list: %s", metrics_list)
    log_metrics(metrics_list, metricsc)

    thresholds_dict = json.loads(thresholds_dict_str)
    deploy = classification_thresholds_check(metrics_list[0], thresholds_dict)
    if deploy:
        dep_decision = "true"
    else:
        dep_decision = "false"
    logging.info("deployment decision is %s", dep_decision)

    return (dep_decision,)

Шаг 2. Добавление готовых компонентов Google Cloud

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

import time
DISPLAY_NAME = 'automl-beans{}'.format(str(int(time.time())))
print(DISPLAY_NAME)

Затем скопируйте следующее в новую ячейку блокнота:

@pipeline(name="automl-tab-beans-training-v2",
                  pipeline_root=PIPELINE_ROOT)
def pipeline(
    bq_source: str = "bq://aju-dev-demos.beans.beans1",
    display_name: str = DISPLAY_NAME,
    project: str = PROJECT_ID,
    gcp_region: str = "us-central1",
    api_endpoint: str = "us-central1-aiplatform.googleapis.com",
    thresholds_dict_str: str = '{"auRoc": 0.95}',
):
    dataset_create_op = gcc_aip.TabularDatasetCreateOp(
        project=project, display_name=display_name, bq_source=bq_source
    )

    training_op = gcc_aip.AutoMLTabularTrainingJobRunOp(
        project=project,
        display_name=display_name,
        optimization_prediction_type="classification",
        budget_milli_node_hours=1000,
        column_transformations=[
            {"numeric": {"column_name": "Area"}},
            {"numeric": {"column_name": "Perimeter"}},
            {"numeric": {"column_name": "MajorAxisLength"}},
            {"numeric": {"column_name": "MinorAxisLength"}},
            {"numeric": {"column_name": "AspectRation"}},
            {"numeric": {"column_name": "Eccentricity"}},
            {"numeric": {"column_name": "ConvexArea"}},
            {"numeric": {"column_name": "EquivDiameter"}},
            {"numeric": {"column_name": "Extent"}},
            {"numeric": {"column_name": "Solidity"}},
            {"numeric": {"column_name": "roundness"}},
            {"numeric": {"column_name": "Compactness"}},
            {"numeric": {"column_name": "ShapeFactor1"}},
            {"numeric": {"column_name": "ShapeFactor2"}},
            {"numeric": {"column_name": "ShapeFactor3"}},
            {"numeric": {"column_name": "ShapeFactor4"}},
            {"categorical": {"column_name": "Class"}},
        ],
        dataset=dataset_create_op.outputs["dataset"],
        target_column="Class",
    )
    model_eval_task = classification_model_eval_metrics(
        project,
        gcp_region,
        api_endpoint,
        thresholds_dict_str,
        training_op.outputs["model"],
    )

    with dsl.Condition(
        model_eval_task.outputs["dep_decision"] == "true",
        name="deploy_decision",
    ):

        endpoint_op = gcc_aip.EndpointCreateOp(
            project=project,
            location=gcp_region,
            display_name="train-automl-beans",
        )

        gcc_aip.ModelDeployOp(
            model=training_op.outputs["model"],
            endpoint=endpoint_op.outputs["endpoint"],
            dedicated_resources_min_replica_count=1,
            dedicated_resources_max_replica_count=1,
            dedicated_resources_machine_type="n1-standard-4",
        )

Давайте посмотрим, что происходит в этом коде:

  • Сначала, как и в предыдущем конвейере, мы определяем входные параметры, которые принимает этот конвейер. Нам нужно установить их вручную, поскольку они не зависят от результатов других шагов конвейера.
  • Остальная часть конвейера использует несколько предварительно созданных компонентов для взаимодействия с сервисами Vertex AI:
    • TabularDatasetCreateOp создает табличный набор данных в Vertex AI с учетом источника набора данных в Cloud Storage или BigQuery. В этом конвейере мы передаем данные через URL-адрес таблицы BigQuery.
    • AutoMLTabularTrainingJobRunOp запускает задание обучения AutoML для набора табличных данных. Мы передаем этому компоненту несколько параметров конфигурации, включая тип модели (в данном случае классификацию), некоторые данные о столбцах, продолжительность обучения и указатель на набор данных. Обратите внимание: чтобы передать набор данных этому компоненту, мы предоставляем выходные данные предыдущего компонента через dataset_create_op.outputs["dataset"]
    • EndpointCreateOp создает конечную точку в Vertex AI. Конечная точка, созданная на этом этапе, будет передана в качестве входных данных следующему компоненту.
    • ModelDeployOp развертывает заданную модель в конечной точке в Vertex AI. В этом случае мы используем конечную точку, созданную на предыдущем шаге. Доступны дополнительные параметры конфигурации, но здесь мы указываем тип и модель конечной машины, которую мы хотим развернуть. Мы передаем модель, получая доступ к результатам этапа обучения в нашем конвейере.
  • Этот конвейер также использует условную логику — функцию Vertex Pipelines, которая позволяет вам определять условие, а также различные ветки на основе результата этого условия. Помните, что когда мы определяли наш конвейер, мы передали параметр thresholds_dict_str . Это порог точности, который мы используем, чтобы определить, следует ли развертывать нашу модель в конечной точке. Для реализации этого мы используем класс Condition из KFP SDK. Условие, которое мы передаем, — это выходные данные пользовательского компонента eval, который мы определили ранее в этой лаборатории кода. Если это условие истинно, конвейер продолжит выполнение компонента deploy_op . Если точность не соответствует нашему предопределенному порогу, конвейер остановится на этом этапе и не сможет развернуть модель.

Шаг 3. Скомпилируйте и запустите сквозной конвейер машинного обучения.

Когда наш полный конвейер определен, пришло время его скомпилировать:

compiler.Compiler().compile(
    pipeline_func=pipeline, package_path="tab_classif_pipeline.json"
)

Далее определите задание:

ml_pipeline_job = aiplatform.PipelineJob(
    display_name="automl-tab-beans-training",
    template_path="tab_classif_pipeline.json",
    pipeline_root=PIPELINE_ROOT,
    parameter_values={"project": PROJECT_ID, "display_name": DISPLAY_NAME},
    enable_caching=True
)

И, наконец, запустите задание:

ml_pipeline_job.submit()

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

Завершенный конвейер AutoML

Если вы переключите кнопку «Развернуть артефакты» вверху, вы сможете увидеть подробную информацию о различных артефактах, созданных из вашего конвейера. Например, если вы щелкнете по артефакту dataset , вы увидите подробную информацию о созданном наборе данных Vertex AI. Вы можете щелкнуть ссылку здесь, чтобы перейти на страницу этого набора данных:

Набор данных трубопровода

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

Визуализация метрик

Чтобы просмотреть модель и конечную точку, созданные в результате этого запуска конвейера, перейдите в раздел моделей и щелкните модель с именем automl-beans . Там вы должны увидеть эту модель, развернутую на конечной точке:

Модель-конечная точка

Вы также можете получить доступ к этой странице, щелкнув артефакт конечной точки на графике конвейера.

Помимо просмотра графика конвейера в консоли, вы также можете использовать Vertex Pipelines для отслеживания происхождения . Под отслеживанием происхождения мы подразумеваем отслеживание артефактов, созданных на протяжении всего вашего конвейера. Это может помочь нам понять, где были созданы артефакты и как они используются в рабочем процессе ML. Например, чтобы просмотреть отслеживание происхождения набора данных, созданного в этом конвейере, щелкните артефакт набора данных, а затем выберите «Просмотреть происхождение» :

Посмотреть родословную

Это показывает нам все места, где используется этот артефакт:

Детали происхождения

Шаг 4. Сравнение метрик по всем запускам конвейера

Если вы запускаете этот конвейер несколько раз, возможно, вам захочется сравнить показатели между запусками. Вы можете использовать метод aiplatform.get_pipeline_df() для доступа к метаданным запуска. Здесь мы получим метаданные для всех запусков этого конвейера и загрузим их в DataFrame Pandas:

pipeline_df = aiplatform.get_pipeline_df(pipeline="automl-tab-beans-training-v2")
small_pipeline_df = pipeline_df.head(2)
small_pipeline_df

На этом вы закончили лабораторию!

🎉Поздравляем! 🎉

Вы узнали, как использовать Vertex AI, чтобы:

  • Используйте Kubeflow Pipelines SDK для создания комплексных конвейеров с использованием пользовательских компонентов.
  • Запускайте свои конвейеры на Vertex Pipelines и запускайте запуск конвейеров с помощью SDK.
  • Просмотр и анализ графика Vertex Pipelines в консоли.
  • Используйте готовые компоненты конвейера для добавления сервисов Vertex AI в свой конвейер.
  • Планирование повторяющихся заданий конвейера

Чтобы узнать больше о различных частях Vertex, ознакомьтесь с документацией .

7. Очистка

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

Шаг 1. Остановите или удалите экземпляр Notebooks

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

Остановить экземпляр

Шаг 2. Удалите конечную точку

Чтобы удалить развернутую конечную точку, перейдите в раздел «Конечные точки» консоли Vertex AI и щелкните значок удаления:

Удалить конечную точку

Затем нажмите «Отменить развертывание» в следующем окне:

Отменить развертывание модели

Наконец, перейдите в раздел «Модели» консоли, найдите эту модель и в трехточечном меню справа нажмите « Удалить модель» :

Удалить модель

Шаг 3. Удалите корзину Cloud Storage.

Чтобы удалить сегмент хранилища, в меню навигации облачной консоли перейдите к разделу «Хранилище», выберите сегмент и нажмите «Удалить»:

Удалить хранилище