Получите максимум от экспериментирования: управляйте экспериментами по машинному обучению с помощью Vertex AI

1. Обзор

В этой лабораторной работе вы будете использовать Vertex AI для создания конвейера, который обучает пользовательскую модель Keras в TensorFlow. Затем мы будем использовать новую функциональность, доступную в Vertex AI Experiments, для отслеживания и сравнения прогонов моделей, чтобы определить, какая комбинация гиперпараметров приводит к наилучшей производительности.

Что ты учишь

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

  • Обучите пользовательскую модель Keras для прогнозирования рейтингов игроков (например, регрессии)
  • Используйте Kubeflow Pipelines SDK для создания масштабируемых конвейеров машинного обучения.
  • Создайте и запустите пятиэтапный конвейер, который принимает данные из облачного хранилища, масштабирует данные, обучает модель, оценивает ее и сохраняет полученную модель обратно в облачное хранилище.
  • Используйте метаданные Vertex ML для сохранения артефактов модели, таких как модели и метрики модели.
  • Используйте Vertex AI Experiments для сравнения результатов различных запусков конвейера.

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

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

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

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

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

3. Обзор вариантов использования

Мы будем использовать популярный набор футбольных данных, полученный из серии видеоигр FIFA от EA Sports . Он включает в себя более 25 000 футбольных матчей и более 10 000 игроков за сезоны 2008–2016 годов. Данные были предварительно обработаны, поэтому вам будет легче приступить к делу. В ходе лабораторной работы вы будете использовать этот набор данных, который теперь можно найти в общедоступной корзине облачного хранилища. Позже в лаборатории кода мы предоставим более подробную информацию о том, как получить доступ к набору данных. Наша конечная цель — предсказать общий рейтинг игрока на основе различных игровых действий, таких как перехваты и пенальти.

Почему Vertex AI Experiments полезен для науки о данных?

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

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

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

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

Почему Vertex AI экспериментирует для игр?

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

4. Настройте свою среду

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

Шаг 1. Включите API Compute Engine.

Перейдите к Compute Engine и выберите «Включить» , если он еще не включен.

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

Перейдите в раздел Vertex AI в облачной консоли и нажмите «Включить Vertex AI API» .

Панель управления Vertex AI

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

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

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

Включите API ноутбуков, если это еще не сделано.

Notebook_api

После включения нажмите «УПРАВЛЯЕМЫЕ НОУТБУКЫ» :

Ноутбуки_UI

Затем выберите НОВЫЙ НОУТБУК .

новый_ноутбук

Дайте записной книжке имя и нажмите «Дополнительные настройки» .

create_notebook

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

Idle_timeout

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

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

open_jupyterlab

Шаг 5. Аутентификация (только в первый раз)

При первом использовании нового экземпляра вам будет предложено пройти аутентификацию. Для этого следуйте инструкциям в пользовательском интерфейсе.

аутентифицировать

Шаг 6: Выберите подходящее ядро

Управляемые ноутбуки предоставляют несколько ядер в одном пользовательском интерфейсе. Выберите ядро ​​для Tensorflow 2 (локальное).

tensorflow_kernel

5. Начальные шаги настройки в вашем ноутбуке

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

Шаг 1. Установите дополнительные пакеты

Нам потребуется установить дополнительные зависимости пакетов, которые в настоящее время не установлены в среде вашего ноутбука. Пример включает KFP SDK.

!pip3 install --user --force-reinstall 'google-cloud-aiplatform>=1.15' -q --no-warn-conflicts
!pip3 install --user kfp -q --no-warn-conflicts

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

# Automatically restart kernel after installs
import os

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

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

Шаг 2: Установите переменные

Мы хотим определить наш PROJECT_ID . Если вы не знаете свой Project_ID , вы можете получить свой PROJECT_ID с помощью gcloud.

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)

В противном случае укажите здесь свой PROJECT_ID .

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

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

  • Америка: us-central1
  • Европа: Европа-Запад4
  • Азиатско-Тихоокеанский регион: Asia-east1

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

#set your region 
REGION = "us-central1"  # @param {type: "string"}

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

#set timestamp to avoid collisions between multiple users

from datetime import datetime

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

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

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

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

#set cloud storage bucket 
BUCKET_NAME = "[insert bucket name here]"  # @param {type:"string"}
BUCKET_URI = f"gs://{BUCKET_NAME}"

Если ваша корзина еще НЕ существует, вы можете запустить следующую ячейку, чтобы создать корзину Cloud Storage.

! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI

Затем вы можете проверить доступ к вашему сегменту Cloud Storage, выполнив следующую ячейку.

#verify access 
! gsutil ls -al $BUCKET_URI

Шаг 4. Скопируйте наш набор игровых данных

Как упоминалось ранее, вы будете использовать популярный набор игровых данных из популярных видеоигр EA Sports — FIFA. Мы выполнили за вас работу по предварительной обработке, поэтому вам просто нужно скопировать набор данных из общедоступного хранилища и переместить его в тот, который вы создали.

# copy the data over to your cloud storage bucket
DATASET_URI = "gs://cloud-samples-data/vertex-ai/structured_data/player_data" 

!gsutil cp -r $DATASET_URI $BUCKET_URI

Шаг 5. Импортируйте библиотеки и определите дополнительные константы

Далее нам нужно импортировать наши библиотеки для Vertex AI, KFP и т. д.

import logging
import os
import time

logger = logging.getLogger("logger")
logging.basicConfig(level=logging.INFO)

import kfp.v2.compiler as compiler
# Pipeline Experiments
import kfp.v2.dsl as dsl
# Vertex AI
from google.cloud import aiplatform as vertex_ai
from kfp.v2.dsl import Artifact, Input, Metrics, Model, Output, component
from typing import NamedTuple

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

#import libraries and define constants
# Experiments

TASK = "regression"
MODEL_TYPE = "tensorflow"
EXPERIMENT_NAME = f"{PROJECT_ID}-{TASK}-{MODEL_TYPE}-{TIMESTAMP}"

# Pipeline
PIPELINE_URI = f"{BUCKET_URI}/pipelines"
TRAIN_URI = f"{BUCKET_URI}/player_data/data.csv"
LABEL_URI = f"{BUCKET_URI}/player_data/labels.csv"
MODEL_URI = f"{BUCKET_URI}/model"
DISPLAY_NAME = "experiments-demo-gaming-data"
BQ_DATASET = "player_data"
BQ_LOCATION = "US"  
VIEW_NAME = 'dataset_test'
PIPELINE_JSON_PKG_PATH = "experiments_demo_gaming_data.json"
PIPELINE_ROOT = f"gs://{BUCKET_URI}/pipeline_root"

6. Давайте построим наш конвейер

Теперь самое интересное, и мы можем начать использовать ИИ Vertex для создания конвейера обучения. Мы инициализируем Vertex AI SDK, настроим наше учебное задание как компонент конвейера, создадим наш конвейер, отправим запуски конвейера и будем использовать Vertex AI SDK для просмотра экспериментов и отслеживания их статуса.

Шаг 1. Инициализируйте Vertex AI SDK

Инициализируйте Vertex AI SDK, задав PROJECT_ID и BUCKET_URI .

#initialize vertex AI SDK 
vertex_ai.init(project=PROJECT_ID, staging_bucket=BUCKET_URI)

Шаг 2. Настройте наше учебное задание как компонент конвейера.

Чтобы начать проводить наши эксперименты, нам нужно будет указать нашу обучающую задачу, определив ее как компонент конвейера. Наш конвейер будет принимать обучающие данные и гиперпараметры (например, DROPOUT_RATE , LEARNING_RATE , EPOCHS ) в качестве входных и выходных показателей модели (например, MAE и RMSE ), а также артефакт модели.

@component(
    packages_to_install=[
        "numpy==1.21.0",
        "pandas==1.3.5", 
        "scikit-learn==1.0.2",
        "tensorflow==2.9.0",
    ]
)
def custom_trainer(
    train_uri: str,
    label_uri: str,
    dropout_rate: float,
    learning_rate: float,
    epochs: int,
    model_uri: str,
    metrics: Output[Metrics], 
    model_metadata: Output[Model], 
    

):

    # import libraries
    import logging
    import uuid
    from pathlib import Path as path

    import pandas as pd
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras.models import Sequential
    from tensorflow.keras.layers import Dense
    from tensorflow.keras.layers import Dropout
    from tensorflow.keras.metrics import Metric 
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import train_test_split
    from sklearn.preprocessing import StandardScaler
    from sklearn.metrics import mean_absolute_error
    import numpy as np
    from math import sqrt
    import os
    import tempfile

    # set variables and use gcsfuse to update prefixes
    gs_prefix = "gs://"
    gcsfuse_prefix = "/gcs/"
    train_path = train_uri.replace(gs_prefix, gcsfuse_prefix)
    label_path = label_uri.replace(gs_prefix, gcsfuse_prefix)
    model_path = model_uri.replace(gs_prefix, gcsfuse_prefix)

    def get_logger():

        logger = logging.getLogger(__name__)
        logger.setLevel(logging.INFO)
        handler = logging.StreamHandler()
        handler.setFormatter(
            logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
        )
        logger.addHandler(handler)
        return logger

    def get_data(
        train_path: str, 
        label_path: str
    ) -> (pd.DataFrame): 
        
        
        #load data into pandas dataframe
        data_0 = pd.read_csv(train_path)
        labels_0 = pd.read_csv(label_path)
        
        #drop unnecessary leading columns
        
        data = data_0.drop('Unnamed: 0', axis=1)
        labels = labels_0.drop('Unnamed: 0', axis=1)
        
        #save as numpy array for reshaping of data 
        
        labels = labels.values
        data = data.values
    
        # Split the data
        labels = labels.reshape((labels.size,))
        train_data, test_data, train_labels, test_labels = train_test_split(data, labels, test_size=0.2, shuffle=True, random_state=7)
    
        #Convert data back to pandas dataframe for scaling
        
        train_data = pd.DataFrame(train_data)
        test_data = pd.DataFrame(test_data)
        train_labels = pd.DataFrame(train_labels)
        test_labels = pd.DataFrame(test_labels)
        
        #Scale and normalize the training dataset
        
        scaler = StandardScaler()
        scaler.fit(train_data)
        train_data = pd.DataFrame(scaler.transform(train_data), index=train_data.index, columns=train_data.columns)
        test_data = pd.DataFrame(scaler.transform(test_data), index=test_data.index, columns=test_data.columns)
        
        return train_data,train_labels, test_data, test_labels 
    
        """ Train your Keras model passing in the training data and values for learning rate, dropout rate,and the number of epochs """

    def train_model(
        learning_rate: float, 
        dropout_rate: float,
        epochs: float,
        train_data: pd.DataFrame,
        train_labels: pd.DataFrame):
 
        # Train tensorflow model
        param = {"learning_rate": learning_rate, "dropout_rate": dropout_rate, "epochs": epochs}
        model = Sequential()
        model.add(Dense(500, input_dim=train_data.shape[1], activation= "relu"))
        model.add(Dropout(param['dropout_rate']))
        model.add(Dense(100, activation= "relu"))
        model.add(Dense(50, activation= "relu"))
        model.add(Dense(1))
            
        model.compile(
        tf.keras.optimizers.Adam(learning_rate= param['learning_rate']),
        loss='mse',
        metrics=[tf.keras.metrics.RootMeanSquaredError(),tf.keras.metrics.MeanAbsoluteError()])
        
        model.fit(train_data, train_labels, epochs= param['epochs'])
        
        return model

    # Get Predictions
    def get_predictions(model, test_data):

        dtest = pd.DataFrame(test_data)
        pred = model.predict(dtest)
        return pred

    # Evaluate predictions with MAE
    def evaluate_model_mae(pred, test_labels):
        
        mae = mean_absolute_error(test_labels, pred)
        return mae
    
    # Evaluate predictions with RMSE
    def evaluate_model_rmse(pred, test_labels):

        rmse = np.sqrt(np.mean((test_labels - pred)**2))
        return rmse    
 
    
    #Save your trained model in GCS     
    def save_model(model, model_path):

        model_id = str(uuid.uuid1())
        model_path = f"{model_path}/{model_id}"        
        path(model_path).parent.mkdir(parents=True, exist_ok=True)
        model.save(model_path + '/model_tensorflow')

        
    # Main ----------------------------------------------
    
    train_data, train_labels, test_data, test_labels = get_data(train_path, label_path)
    model = train_model(learning_rate, dropout_rate, epochs, train_data,train_labels )
    pred = get_predictions(model, test_data)
    mae = evaluate_model_mae(pred, test_labels)
    rmse = evaluate_model_rmse(pred, test_labels)
    save_model(model, model_path)

    # Metadata ------------------------------------------

    #convert numpy array to pandas series
    mae = pd.Series(mae)
    rmse = pd.Series(rmse)

    #log metrics and model artifacts with ML Metadata. Save metrics as a list. 
    metrics.log_metric("mae", mae.to_list()) 
    metrics.log_metric("rmse", rmse.to_list()) 
    model_metadata.uri = model_uri

Шаг 3: Создайте наш конвейер

Теперь мы настроим наш рабочий процесс с использованием Domain Specific Language (DSL) доступного в KFP, и скомпилируем наш конвейер в файл JSON .

# define our workflow

@dsl.pipeline(name="gaming-custom-training-pipeline")
def pipeline(
    train_uri: str,
    label_uri: str,
    dropout_rate: float,
    learning_rate: float,
    epochs: int,
    model_uri: str,
):

    custom_trainer(
        train_uri,label_uri, dropout_rate,learning_rate,epochs, model_uri
    )
#compile our pipeline
compiler.Compiler().compile(pipeline_func=pipeline, package_path="gaming_pipeline.json")

Шаг 4. Отправьте наши запуски конвейера

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

runs = [
    {"dropout_rate": 0.001, "learning_rate": 0.001,"epochs": 20},
    {"dropout_rate": 0.002, "learning_rate": 0.002,"epochs": 25},
    {"dropout_rate": 0.003, "learning_rate": 0.003,"epochs": 30},
    {"dropout_rate": 0.004, "learning_rate": 0.004,"epochs": 35},
    {"dropout_rate": 0.005, "learning_rate": 0.005,"epochs": 40},
]

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

for i, run in enumerate(runs):

    job = vertex_ai.PipelineJob(
        display_name=f"{EXPERIMENT_NAME}-pipeline-run-{i}",
        template_path="gaming_pipeline.json",
        pipeline_root=PIPELINE_URI,
        parameter_values={
            "train_uri": TRAIN_URI,
            "label_uri": LABEL_URI,
            "model_uri": MODEL_URI,
            **run,
        },
    )
    job.submit(experiment=EXPERIMENT_NAME)

Шаг 5. Используйте Vertex AI SDK для просмотра экспериментов

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

# see state/status of all the pipeline runs

vertex_ai.get_experiment_df(EXPERIMENT_NAME)

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

#check on current status
while True:
    pipeline_experiments_df = vertex_ai.get_experiment_df(EXPERIMENT_NAME)
    if all(
        pipeline_state != "COMPLETE" for pipeline_state in pipeline_experiments_df.state
    ):
        print("Pipeline runs are still running...")
        if any(
            pipeline_state == "FAILED"
            for pipeline_state in pipeline_experiments_df.state
        ):
            print("At least one Pipeline run failed")
            break
    else:
        print("Pipeline experiment runs have completed")
        break
    time.sleep(60)

Вы также можете вызывать определенные задания конвейера, используя run_name .

# Call the pipeline runs based on the experiment run name
pipeline_experiments_df = vertex_ai.get_experiment_df(EXPERIMENT_NAME)
job = vertex_ai.PipelineJob.get(pipeline_experiments_df.run_name[0])
print(job.resource_name)
print(job._dashboard_uri())

Наконец, вы можете обновлять состояние ваших запусков через определенные промежутки времени (например, каждые 60 секунд), чтобы видеть, как состояния меняются с RUNNING на FAILED или COMPLETE .

# wait 60 seconds and view state again
import time
time.sleep(60)
vertex_ai.get_experiment_df(EXPERIMENT_NAME)

7. Определите лучший результат

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

Окончательные результаты-снимок

И MAE, и RMSE являются мерами средней ошибки прогнозирования модели, поэтому в большинстве случаев желательно более низкое значение для обеих метрик. Основываясь на результатах Vertex AI Experiments, мы видим, что нашим самым успешным прогоном по обеим метрикам был финальный прогон с dropout_rate 0,001, learning_rate 0,001 и общим количеством epochs , равным 20. На основе этого эксперимента эти модели параметры в конечном итоге будут использоваться в производстве, поскольку это приводит к наилучшей производительности модели.

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

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

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

  • Обучите пользовательскую модель Keras для прогнозирования рейтингов игроков (например, регрессии)
  • Используйте Kubeflow Pipelines SDK для создания масштабируемых конвейеров машинного обучения.
  • Создайте и запустите пятиэтапный конвейер, который принимает данные из GCS, масштабирует данные, обучает модель, оценивает ее и сохраняет полученную модель обратно в GCS.
  • Используйте метаданные Vertex ML для сохранения артефактов модели, таких как модели и метрики модели.
  • Используйте Vertex AI Experiments для сравнения результатов различных запусков конвейера.

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

8. Очистка

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

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

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

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

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

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

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