Обучение и настройка гиперпараметров модели PyTorch на платформе Cloud AI

1. Обзор

В этой лабораторной работе вы пройдете полный рабочий процесс обучения машинному обучению в Google Cloud, используя PyTorch для построения модели. В среде Cloud AI Platform Notebooks вы узнаете, как упаковать задание по обучению для его запуска на платформе AI Platform Training с настройкой гиперпараметров.

Что вы узнаете

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

  • Создайте экземпляр блокнотов AI Platform.
  • Создайте модель PyTorch
  • Обучите свою модель с помощью настройки гиперпараметров на платформе AI Platform Training.

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

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

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

Шаг 1. Включите API моделей облачной платформы искусственного интеллекта.

Перейдите в раздел «Модели платформы AI» в облачной консоли и нажмите «Включить», если он еще не включен.

d0d38662851c6af3.png

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

Перейдите к Compute Engine и выберите «Включить» , если он еще не включен. Это понадобится вам для создания экземпляра блокнота.

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

Перейдите в раздел «Блокноты AI Platform» в облачной консоли и нажмите «Новый экземпляр» . Затем выберите последний тип экземпляра PyTorch (без графических процессоров):

892b7588f940d145.png

Используйте параметры по умолчанию или, если хотите, присвойте ему собственное имя, а затем нажмите «Создать» . После создания экземпляра выберите «Открыть JupyterLab» :

63d2cf44801c2df5.png

Затем откройте экземпляр Python 3 Notebook из панели запуска:

de4c86c6c7f9438f.png

Вы готовы начать!

Шаг 5. Импортируйте пакеты Python

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

import datetime
import numpy as np
import os
import pandas as pd
import time

Вы заметите, что здесь мы не импортируем PyTorch. Это связано с тем, что мы выполняем задание по обучению на платформе AI, а не на нашем экземпляре Notebook.

3. Создайте пакет для учебного задания.

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

Шаг 1. Создайте корзину Cloud Storage для нашей модели.

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

# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'

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

Запустите эту команду gsutil из своего блокнота, чтобы создать корзину:

!gsutil mb $BUCKET_URL

Шаг 2. Создайте исходные файлы для нашего пакета Python.

Чтобы запустить учебное задание на платформе AI, нам нужно настроить наш код как пакет Python. Он состоит из файла setup.py в нашем корневом каталоге, в котором указаны все внешние зависимости пакета, подкаталога с именем нашего пакета (здесь мы назовем его trainer/ ) и пустого файла __init__.py в этом подкаталоге.

Сначала давайте напишем наш файл setup.py. Мы используем магию iPython %%writefile, чтобы сохранить файл в нашем экземпляре. Здесь мы указали три внешние библиотеки, которые будем использовать в нашем обучающем коде: PyTorch, Scikit-learn и Pandas:

%%writefile setup.py
from setuptools import find_packages
from setuptools import setup

REQUIRED_PACKAGES = ['torch>=1.5', 'scikit-learn>=0.20', 'pandas>=1.0']

setup(
    name='trainer',
    version='0.1',
    install_requires=REQUIRED_PACKAGES,
    packages=find_packages(),
    include_package_data=True,
    description='My training application package.'
)

Далее давайте создадим каталог Trainer/ и пустой файл init .py внутри него. Python использует этот файл, чтобы распознать, что это пакет:

!mkdir trainer
!touch trainer/__init__.py

Теперь мы готовы приступить к созданию нашей обучающей работы.

4. Предварительный просмотр набора данных

Основное внимание в этой лабораторной работе уделяется инструментам для обучения моделей, но давайте кратко рассмотрим набор данных, который мы будем использовать для обучения нашей модели пониманию. Мы будем использовать набор данных о рождаемости, доступный в BigQuery. Здесь содержатся данные о рождении в США за несколько десятилетий. Мы будем использовать несколько столбцов из набора данных, чтобы предсказать вес ребенка при рождении. Исходный набор данных довольно большой, и мы будем использовать его подмножество, которое мы предоставили вам в сегменте облачного хранилища.

Шаг 1. Загрузите набор данных о рождаемости BigQuery.

Давайте загрузим версию набора данных, которую мы предоставили вам в облачном хранилище, в Pandas DataFrame и просмотрим ее.

natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()

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

5. Определите задание обучения с настройкой гиперпараметров.

Мы запишем наш сценарий обучения в файл с именем model.py в подкаталоге Trainer/, который мы создали ранее. Наша учебная работа будет выполняться на платформе AI Platform Training, а также будет использоваться служба настройки гиперпараметров AI Platform для поиска оптимальных гиперпараметров для нашей модели с использованием байесовской оптимизации.

Шаг 1. Создайте сценарий обучения

Сначала давайте создадим файл Python с нашим обучающим скриптом. Потом разберем, что в нем происходит. Выполнение этой команды %%writefile запишет код модели в локальный файл Python:

%%writefile trainer/model.py
import argparse
import hypertune
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim

from sklearn.utils import shuffle
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import normalize

def get_args():
    """Argument parser.
    Returns:
        Dictionary of arguments.
    """
    parser = argparse.ArgumentParser(description='PyTorch MNIST')
    parser.add_argument('--job-dir',  # handled automatically by AI Platform
                        help='GCS location to write checkpoints and export ' \
                             'models')
    parser.add_argument('--lr',  # Specified in the config file
                        type=float,
                        default=0.01,
                        help='learning rate (default: 0.01)')
    parser.add_argument('--momentum',  # Specified in the config file
                        type=float,
                        default=0.5,
                        help='SGD momentum (default: 0.5)')
    parser.add_argument('--hidden-layer-size',  # Specified in the config file
                        type=int,
                        default=8,
                        help='hidden layer size')
    args = parser.parse_args()
    return args

def train_model(args):
    # Get the data
    natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
    natality = natality.dropna()
    natality = shuffle(natality, random_state = 2)
    natality.head()

    natality_labels = natality['weight_pounds']
    natality = natality.drop(columns=['weight_pounds'])


    train_size = int(len(natality) * 0.8)
    traindata_natality = natality[:train_size]
    trainlabels_natality = natality_labels[:train_size]

    testdata_natality = natality[train_size:]
    testlabels_natality = natality_labels[train_size:]

    # Normalize and convert to PT tensors
    normalized_train = normalize(np.array(traindata_natality.values), axis=0)
    normalized_test = normalize(np.array(testdata_natality.values), axis=0)

    train_x = torch.Tensor(normalized_train)
    train_y = torch.Tensor(np.array(trainlabels_natality))

    test_x = torch.Tensor(normalized_test)
    test_y = torch.Tensor(np.array(testlabels_natality))

    # Define our data loaders
    train_dataset = torch.utils.data.TensorDataset(train_x, train_y)
    train_dataloader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True)

    test_dataset = torch.utils.data.TensorDataset(test_x, test_y)
    test_dataloader = torch.utils.data.DataLoader(test_dataset, batch_size=128, shuffle=False)

    # Define the model, while tuning the size of our hidden layer
    model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                          nn.ReLU(),
                          nn.Linear(args.hidden_layer_size, 1))
    criterion = nn.MSELoss()

    # Tune hyperparameters in our optimizer
    optimizer = optim.SGD(model.parameters(), lr=args.lr, momentum=args.momentum)
    epochs = 20
    for e in range(epochs):
        for batch_id, (data, label) in enumerate(train_dataloader):
            optimizer.zero_grad()
            y_pred = model(data)
            label = label.view(-1,1)
            loss = criterion(y_pred, label)
            
            loss.backward()
            optimizer.step()


    val_mse = 0
    num_batches = 0
    # Evaluate accuracy on our test set
    with torch.no_grad():
        for i, (data, label) in enumerate(test_dataloader):
            num_batches += 1
            y_pred = model(data)
            mse = criterion(y_pred, label.view(-1,1))
            val_mse += mse.item()


    avg_val_mse = (val_mse / num_batches)

    # Report the metric we're optimizing for to AI Platform's HyperTune service
    # In this example, we're mimizing error on our test set
    hpt = hypertune.HyperTune()
    hpt.report_hyperparameter_tuning_metric(
        hyperparameter_metric_tag='val_mse',
        metric_value=avg_val_mse,
        global_step=epochs        
    )

def main():
    args = get_args()
    print('in main', args)
    train_model(args)

if __name__ == '__main__':
    main()

Работа по обучению состоит из двух функций, на которые приходится основная часть работы.

  • get_args() : анализирует аргументы командной строки, которые мы передадим при создании нашего учебного задания, а также гиперпараметры, которые мы хотим оптимизировать AI Platform. В этом примере наш список аргументов включает только те гиперпараметры, которые мы будем оптимизировать — скорость обучения нашей модели, импульс и количество нейронов в нашем скрытом слое.
  • train_model() : здесь мы загружаем данные в DataFrame Pandas, нормализуем их, преобразуем в тензоры PyTorch, а затем определяем нашу модель. Для построения нашей модели мы используем PyTorch nn.Sequential API, который позволяет нам определить нашу модель как стек слоев:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
                      nn.ReLU(),
                      nn.Linear(args.hidden_layer_size, 1))

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

Шаг 2. Использование службы настройки гиперпараметров AI Platform.

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

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

Затем создайте этот файл конфигурации локально:

%%writefile config.yaml
trainingInput:
  hyperparameters:
    goal: MINIMIZE
    maxTrials: 10
    maxParallelTrials: 5
    hyperparameterMetricTag: val_mse
    enableTrialEarlyStopping: TRUE
    params:
    - parameterName: lr
      type: DOUBLE
      minValue: 0.0001
      maxValue: 0.1
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: momentum
      type: DOUBLE
      minValue: 0.0
      maxValue: 1.0
      scaleType: UNIT_LINEAR_SCALE
    - parameterName: hidden-layer-size
      type: INTEGER
      minValue: 8
      maxValue: 32
      scaleType: UNIT_LINEAR_SCALE

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

В начале работы мы также указываем метрику, которую оптимизируем. Обратите внимание, что в конце нашей функции train_model() указанной выше, мы сообщаем эту метрику платформе AI каждый раз, когда пробная версия завершается. Здесь мы минимизируем среднеквадратическую ошибку нашей модели и поэтому хотим использовать гиперпараметры, которые приводят к наименьшей среднеквадратической ошибке для нашей модели. Имя этой метрики ( val_mse ) совпадает с именем, которое мы используем для отчета о ней, когда вызываем report_hyperparameter_tuning_metric() в конце пробного периода.

6. Запустите обучение на платформе AI.

В этом разделе мы начнем нашу работу по обучению модели с настройки гиперпараметров на платформе AI.

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

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

MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"

Каждое учебное задание на платформе AI должно иметь уникальное имя. Выполните следующую команду, чтобы определить переменную для имени вашего задания с использованием метки времени:

timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))

Шаг 2. Приступайте к обучению

Мы создадим учебное задание с помощью gcloud, Google Cloud CLI. Мы можем запустить эту команду прямо в нашем блокноте, ссылаясь на переменные, которые мы определили выше:

!gcloud ai-platform jobs submit training $JOB_NAME \
        --scale-tier basic \
        --package-path $TRAIN_DIR \
        --module-name $MAIN_TRAINER_MODULE \
        --job-dir $JOB_DIR \
        --region $REGION \
        --runtime-version 2.1 \
        --python-version 3.7 \
        --config config.yaml

Если ваше задание было создано правильно, перейдите в раздел «Задания» консоли AI Platform, чтобы просмотреть журналы.

Шаг 3. Контролируйте свою работу

Перейдя в раздел «Вакансии» консоли, нажмите на задание, которое вы только что начали, чтобы просмотреть подробности:

c184167641bb7ed7.png

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

787c053ef9110e6b.png

По завершении испытаний результирующее значение вашей метрики оптимизации (в данном случае val_mse ) будет записываться здесь. Выполнение задания должно занять 15–20 минут, а после завершения задания панель мониторинга будет выглядеть примерно так (точные значения могут различаться):

47ef6b9b4ecb532c.png

Чтобы устранить потенциальные проблемы и более детально отслеживать выполнение задания, нажмите «Просмотреть журналы» на странице сведений о задании:

18c32dcd36351930.png

Здесь будет отображаться каждый оператор print() в коде обучения вашей модели. Если у вас возникли проблемы, попробуйте добавить больше операторов печати и начать новое задание обучения.

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

7. Очистка

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

879147427150b6c7.png

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

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