Vertex AI: تنظیم فراپارامتر توزیع شده

1. بررسی اجمالی

در این آزمایشگاه، نحوه استفاده از Vertex AI برای تنظیم هایپرپارامتر و آموزش توزیع شده را خواهید آموخت. در حالی که این آزمایشگاه از TensorFlow برای کد مدل استفاده می کند، این مفاهیم برای سایر چارچوب های ML نیز قابل اجرا هستند.

چیزی که یاد می گیرید

شما یاد خواهید گرفت که چگونه:

  • یک مدل را با استفاده از آموزش توزیع شده در یک ظرف سفارشی آموزش دهید
  • چندین آزمایش کد آموزشی خود را برای تنظیم خودکار فراپارامتر راه اندازی کنید

هزینه کل اجرای این آزمایشگاه در Google Cloud حدود 6 دلار آمریکا است.

2. مقدمه ای بر Vertex AI

این آزمایشگاه از جدیدترین محصول هوش مصنوعی موجود در Google Cloud استفاده می کند. Vertex AI پیشنهادات ML را در سراسر Google Cloud در یک تجربه توسعه یکپارچه ادغام می کند. پیش از این، مدل‌های آموزش دیده با AutoML و مدل‌های سفارشی از طریق سرویس‌های جداگانه قابل دسترسی بودند. پیشنهاد جدید هر دو را به همراه سایر محصولات جدید در یک API واحد ترکیب می کند. همچنین می توانید پروژه های موجود را به Vertex AI منتقل کنید. اگر بازخوردی دارید، لطفاً صفحه پشتیبانی را ببینید.

Vertex AI شامل بسیاری از محصولات مختلف برای پشتیبانی از گردش کار ML سرتاسر است. این آزمایشگاه بر روی Training و Workbench تمرکز خواهد کرد.

نمای کلی محصول Vertex

3. از Case Overview استفاده کنید

در این آزمایشگاه، از تنظیم هایپرپارامتر برای کشف پارامترهای بهینه برای یک مدل طبقه بندی تصویر آموزش داده شده بر روی مجموعه داده های اسب یا انسان از TensorFlow Datasets استفاده خواهید کرد.

تنظیم فراپارامتر

تنظیم Hyperparameter با Vertex AI Training با اجرای آزمایش‌های متعدد برنامه آموزشی شما با مقادیری برای هایپرپارامترهای انتخابی شما، در محدوده‌هایی که شما تعیین می‌کنید، کار می‌کند. Vertex AI نتایج هر آزمایش را ردیابی می کند و برای آزمایش های بعدی تنظیمات را انجام می دهد.

برای استفاده از تنظیم هایپرپارامتر با Vertex AI Training، باید دو تغییر در کد آموزشی خود ایجاد کنید:

  1. برای هر هایپرپارامتری که می خواهید تنظیم کنید، یک آرگومان خط فرمان را در ماژول آموزشی اصلی خود تعریف کنید.
  2. از مقدار ارسال شده در آن آرگومان ها برای تنظیم هایپرپارامتر مربوطه در کد برنامه خود استفاده کنید.

آموزش توزیع شده

اگر یک واحد پردازش گرافیکی دارید، TensorFlow از این شتاب دهنده برای سرعت بخشیدن به آموزش مدل ها بدون هیچ کار اضافی از جانب شما استفاده می کند. با این حال، اگر می‌خواهید با استفاده از چندین GPU تقویت بیشتری دریافت کنید، باید از tf.distribute استفاده کنید، که ماژول TensorFlow برای اجرای محاسبات در چندین دستگاه است.

این آزمایشگاه از tf.distribute.MirroredStrategy استفاده می کند که می توانید تنها با چند تغییر کد به برنامه های آموزشی خود اضافه کنید. این استراتژی یک کپی از مدل را در هر پردازنده گرافیکی در دستگاه شما ایجاد می کند. به روز رسانی های گرادیان بعدی به صورت همزمان اتفاق می افتد. این به این معنی است که هر GPU گذرهای رو به جلو و عقب را از طریق مدل در بخش متفاوتی از داده های ورودی محاسبه می کند. سپس گرادیان‌های محاسبه‌شده از هر یک از این برش‌ها در تمام پردازنده‌های گرافیکی جمع‌آوری می‌شوند و در فرآیندی به نام all-reduce میانگین‌گیری می‌شوند. پارامترهای مدل با استفاده از این گرادیان های متوسط ​​به روز می شوند.

برای تکمیل این آزمایشگاه نیازی به دانستن جزئیات نیست، اما اگر می‌خواهید درباره نحوه عملکرد آموزش توزیع‌شده در TensorFlow اطلاعات بیشتری کسب کنید، ویدیوی زیر را ببینید:

4. محیط خود را تنظیم کنید

برای اجرای این کد لبه به یک پروژه Google Cloud Platform با فعال بودن صورتحساب نیاز دارید. برای ایجاد یک پروژه، دستورالعمل های اینجا را دنبال کنید.

مرحله 1: Compute Engine API را فعال کنید

به Compute Engine بروید و اگر قبلاً فعال نشده است Enable را انتخاب کنید.

مرحله 2: Container Registry API را فعال کنید

به رجیستری کانتینر بروید و اگر قبلاً وجود ندارد، Enable را انتخاب کنید. شما از این برای ایجاد یک ظرف برای کار آموزشی سفارشی خود استفاده خواهید کرد.

مرحله 3: Vertex AI API را فعال کنید

به بخش Vertex AI در Cloud Console خود بروید و روی Enable Vertex AI API کلیک کنید.

داشبورد Vertex AI

مرحله 4: یک نمونه Vertex AI Workbench ایجاد کنید

از بخش Vertex AI در Cloud Console خود، روی Workbench کلیک کنید:

منوی Vertex AI

اگر قبلاً API Notebooks وجود ندارد، آن را فعال کنید.

Notebook_api

پس از فعال شدن، روی دفترچه یادداشت مدیریت شده کلیک کنید:

Notebooks_UI

سپس NEW NOTEBOOK را انتخاب کنید.

نوت بوک

نوت بوک خود را نامی بگذارید و سپس روی تنظیمات پیشرفته کلیک کنید.

create_notebook

در قسمت تنظیمات پیشرفته، خاموش شدن بی‌حرکت را فعال کنید و تعداد دقیقه‌ها را روی 60 دقیقه تنظیم کنید. این بدان معناست که نوت بوک شما در صورت عدم استفاده به طور خودکار خاموش می‌شود تا هزینه‌های غیرضروری متحمل نشوید.

idle_timeout

اگر قبلاً فعال نشده است، در قسمت Security، "Enable terminal" را انتخاب کنید.

فعال-ترمینال

شما می توانید تمام تنظیمات پیشرفته دیگر را به همین صورت رها کنید.

بعد، روی ایجاد کلیک کنید. ارائه نمونه چند دقیقه طول می کشد.

پس از ایجاد نمونه، Open JupyterLab را انتخاب کنید.

open_jupyterlab

اولین باری که از یک نمونه جدید استفاده می کنید، از شما خواسته می شود که احراز هویت کنید. برای انجام این کار مراحل موجود در UI را دنبال کنید.

تصدیق کردن

5. کد آموزشی را بنویسید

برای شروع، از منوی Launcher، یک پنجره ترمینال را در نمونه نوت بوک خود باز کنید:

لانچر_ترمینال

یک دایرکتوری جدید به نام vertex-codelab و cd در آن ایجاد کنید.

mkdir vertex-codelab
cd vertex-codelab

برای ایجاد یک دایرکتوری برای کد آموزشی و یک فایل پایتون که در آن کد را اضافه می کنید، موارد زیر را اجرا کنید:

mkdir trainer
touch trainer/task.py

اکنون باید موارد زیر را در دایرکتوری vertex-codelab خود داشته باشید:

+ trainer/
    + task.py

در مرحله بعد، فایل task.py را که ایجاد کرده اید باز کنید و تمام کدهای زیر را در آن جایگذاری کنید.

import tensorflow as tf
import tensorflow_datasets as tfds
import argparse
import hypertune
import os

NUM_EPOCHS = 10
BATCH_SIZE = 64

def get_args():
  '''Parses args. Must include all hyperparameters you want to tune.'''

  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--learning_rate',
      required=True,
      type=float,
      help='learning rate')
  parser.add_argument(
      '--momentum',
      required=True,
      type=float,
      help='SGD momentum value')
  parser.add_argument(
      '--num_units',
      required=True,
      type=int,
      help='number of units in last hidden layer')
  args = parser.parse_args()
  return args


def preprocess_data(image, label):
  '''Resizes and scales images.'''

  image = tf.image.resize(image, (150,150))
  return tf.cast(image, tf.float32) / 255., label


def create_dataset(batch_size):
  '''Loads Horses Or Humans dataset and preprocesses data.'''

  data, info = tfds.load(name='horses_or_humans', as_supervised=True, with_info=True)

  # Create train dataset
  train_data = data['train'].map(preprocess_data)
  train_data  = train_data.shuffle(1000)
  train_data  = train_data.batch(batch_size)

  # Create validation dataset
  validation_data = data['test'].map(preprocess_data)
  validation_data  = validation_data.batch(batch_size)

  return train_data, validation_data


def create_model(num_units, learning_rate, momentum):
  '''Defines and compiles model.'''

  inputs = tf.keras.Input(shape=(150, 150, 3))
  x = tf.keras.layers.Conv2D(16, (3, 3), activation='relu')(inputs)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(32, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Conv2D(64, (3, 3), activation='relu')(x)
  x = tf.keras.layers.MaxPooling2D((2, 2))(x)
  x = tf.keras.layers.Flatten()(x)
  x = tf.keras.layers.Dense(num_units, activation='relu')(x)
  outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)
  model = tf.keras.Model(inputs, outputs)
  model.compile(
      loss='binary_crossentropy',
      optimizer=tf.keras.optimizers.SGD(learning_rate=learning_rate, momentum=momentum),
      metrics=['accuracy'])
  return model


def main():
  args = get_args()

  # Create distribution strategy
  strategy = tf.distribute.MirroredStrategy()

  # Get data
  GLOBAL_BATCH_SIZE = BATCH_SIZE * strategy.num_replicas_in_sync
  train_data, validation_data = create_dataset(GLOBAL_BATCH_SIZE)

  # Wrap variable creation within strategy scope
  with strategy.scope():
    model = create_model(args.num_units, args.learning_rate, args.momentum)

  # Train model
  history = model.fit(train_data, epochs=NUM_EPOCHS, validation_data=validation_data)

  # Define metric
  hp_metric = history.history['val_accuracy'][-1]

  hpt = hypertune.HyperTune()
  hpt.report_hyperparameter_tuning_metric(
      hyperparameter_metric_tag='accuracy',
      metric_value=hp_metric,
      global_step=NUM_EPOCHS)


if __name__ == "__main__":
    main()

بیایید نگاهی عمیق‌تر به کد بیندازیم و مؤلفه‌های مخصوص آموزش توزیع‌شده و تنظیم هایپرپارامتر را بررسی کنیم.

آموزش توزیع شده

  1. در تابع main() شی MirroredStrategy ایجاد می شود. سپس، ایجاد متغیرهای مدل خود را در محدوده استراتژی قرار می دهید. این مرحله به TensorFlow می گوید که کدام متغیرها باید در سراسر GPU ها منعکس شوند.
  2. اندازه دسته با num_replicas_in_sync بزرگ شده است. مقیاس بندی اندازه دسته بهترین روش هنگام استفاده از استراتژی های موازی داده های همزمان در TensorFlow است. شما می توانید اینجا بیشتر بیاموزید.

تنظیم فراپارامتر

  1. اسکریپت کتابخانه hypertune را وارد می کند. بعداً وقتی تصویر ظرف را می‌سازیم، باید مطمئن شویم که این کتابخانه را نصب کرده‌ایم.
  2. تابع get_args() یک آرگومان خط فرمان برای هر هایپرپارامتری که می خواهید تنظیم کنید تعریف می کند. در این مثال، فراپارامترهایی که تنظیم خواهند شد عبارتند از نرخ یادگیری، مقدار تکانه در بهینه ساز و تعداد واحدها در آخرین لایه پنهان مدل، اما با خیال راحت با دیگران آزمایش کنید. مقدار ارسال شده در آن آرگومان ها سپس برای تنظیم هایپرپارامتر مربوطه در کد استفاده می شود (به عنوان مثال، تنظیم learning_rate = args.learning_rate )
  3. در انتهای تابع main() از کتابخانه hypertune برای تعریف متریکی که می خواهید بهینه کنید استفاده می شود. در TensorFlow، متد Keras model.fit یک شی History برمی‌گرداند. ویژگی History.history رکوردی از مقادیر از دست دادن آموزش و مقادیر معیارها در دوره های متوالی است. اگر داده‌های اعتبارسنجی را به model.fit ارسال کنید، ویژگی History.history شامل از دست دادن اعتبار و مقادیر معیارها نیز می‌شود. برای مثال، اگر مدلی را برای سه دوره با داده های اعتبار سنجی آموزش دهید و accuracy به عنوان یک متریک ارائه کنید، ویژگی History.history شبیه فرهنگ لغت زیر خواهد بود.
{
 "accuracy": [
   0.7795261740684509,
   0.9471358060836792,
   0.9870933294296265
 ],
 "loss": [
   0.6340447664260864,
   0.16712145507335663,
   0.04546636343002319
 ],
 "val_accuracy": [
   0.3795261740684509,
   0.4471358060836792,
   0.4870933294296265
 ],
 "val_loss": [
   2.044623374938965,
   4.100203514099121,
   3.0728273391723633
 ]

اگر می‌خواهید سرویس تنظیم فراپارامتر مقادیری را که دقت اعتبارسنجی مدل را به حداکثر می‌رسانند کشف کند، متریک را به عنوان آخرین ورودی (یا NUM_EPOCS - 1 ) از لیست val_accuracy تعریف می‌کنید. سپس، این معیار را به یک نمونه از HyperTune ارسال کنید. می‌توانید هر رشته‌ای را که دوست دارید برای hyperparameter_metric_tag انتخاب کنید، اما بعداً وقتی کار تنظیم hyperparameter را شروع کردید، باید دوباره از رشته استفاده کنید.

6. کد ظرف

اولین گام در کانتینر کردن کد شما ایجاد یک Dockerfile است. در Dockerfile شما تمام دستورات مورد نیاز برای اجرای تصویر را درج خواهید کرد. تمام کتابخانه‌های لازم را نصب می‌کند و نقطه ورودی کد آموزشی را تنظیم می‌کند.

مرحله 1: Dockerfile را بنویسید

از ترمینال خود، مطمئن شوید که در فهرست vertex-codelab هستید و یک Dockerfile خالی ایجاد کنید:

touch Dockerfile

اکنون باید موارد زیر را در دایرکتوری vertex-codelab خود داشته باشید:

+ Dockerfile
+ trainer/
    + task.py

Dockerfile را باز کنید و موارد زیر را در آن کپی کنید:

FROM gcr.io/deeplearning-platform-release/tf2-gpu.2-7

WORKDIR /

# Installs hypertune library
RUN pip install cloudml-hypertune

# Copies the trainer code to the docker image.
COPY trainer /trainer

# Sets up the entry point to invoke the trainer.
ENTRYPOINT ["python", "-m", "trainer.task"]

این Dockerfile از تصویر Deep Learning Container TensorFlow Enterprise 2.7 GPU Docker استفاده می کند. Deep Learning Containers در Google Cloud با بسیاری از چارچوب‌های رایج ML و علم داده از پیش نصب شده عرضه می‌شود. پس از دانلود آن تصویر، این Dockerfile نقطه ورودی کد آموزشی را تنظیم می کند.

مرحله 2: ظرف را بسازید

از ترمینال خود، موارد زیر را اجرا کنید تا یک متغیر env برای پروژه خود تعریف کنید و مطمئن شوید که your-cloud-project با ID پروژه خود جایگزین کنید:

PROJECT_ID='your-cloud-project'

یک متغیر با URI تصویر کانتینر خود در Google Container Registry تعریف کنید:

IMAGE_URI="gcr.io/$PROJECT_ID/horse-human-codelab:latest"

Docker را پیکربندی کنید

gcloud auth configure-docker

سپس، با اجرای موارد زیر از ریشه دایرکتوری vertex-codelab خود، کانتینر را بسازید:

docker build ./ -t $IMAGE_URI

در نهایت، آن را به Google Container Registry فشار دهید:

docker push $IMAGE_URI

مرحله 3: یک سطل ذخیره سازی ابری ایجاد کنید

در کار آموزشی خود، از مسیری به سطل صحنه گذر خواهیم کرد.

موارد زیر را در ترمینال خود اجرا کنید تا یک سطل جدید در پروژه خود ایجاد کنید.

BUCKET_NAME="gs://${PROJECT_ID}-hptune-bucket"
gsutil mb -l us-central1 $BUCKET_NAME

7. کار تنظیم hyperparameter را راه اندازی کنید

مرحله 1: کار آموزشی سفارشی با تنظیم هایپرپارامتر ایجاد کنید

از لانچر، یک نوت بوک جدید TensorFlow 2 باز کنید.

نوت بوک

Vertex AI Python SDK را وارد کنید.

from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt

برای راه اندازی کار تنظیم hyperparameter، ابتدا باید worker_pool_specs را تعریف کنید که نوع ماشین و تصویر Docker را مشخص می کند. مشخصات زیر یک دستگاه را با دو پردازنده گرافیکی NVIDIA Tesla V100 تعریف می کند.

شما باید پروژه خود را جایگزین {PROJECT_ID} در image_uri کنید.

# The spec of the worker pools including machine type and Docker image
# Be sure to replace PROJECT_ID in the "image_uri" with your project.

worker_pool_specs = [{
    "machine_spec": {
        "machine_type": "n1-standard-4",
        "accelerator_type": "NVIDIA_TESLA_V100",
        "accelerator_count": 2
    },
    "replica_count": 1,
    "container_spec": {
        "image_uri": "gcr.io/{PROJECT_ID}/horse-human-codelab:latest"
    }
}]

در مرحله بعد، parameter_spec را تعریف کنید، که یک فرهنگ لغت است که پارامترهایی را که می خواهید بهینه کنید، مشخص می کند. کلید دیکشنری رشته ای است که برای هر هایپرپارامتر به آرگومان خط فرمان اختصاص داده اید و مقدار دیکشنری مشخصات پارامتر است.

برای هر هایپرپارامتر، باید نوع و همچنین مرزهایی را برای مقادیری که سرویس تنظیم امتحان می کند، تعریف کنید. هایپرپارامترها می توانند از نوع Double، Integer، Category یا Discrete باشند. اگر نوع Double یا Integer را انتخاب کنید، باید حداقل و حداکثر مقدار را ارائه دهید. و اگر دسته بندی یا گسسته را انتخاب کنید، باید مقادیر را ارائه دهید. برای انواع Double و Integer، باید مقدار Scaling را نیز ارائه دهید. در این ویدیو می‌توانید درباره نحوه انتخاب بهترین مقیاس بیشتر بدانید.

# Dictionary representing parameters to optimize.
# The dictionary key is the parameter_id, which is passed into your training
# job as a command line argument,
# And the dictionary value is the parameter specification of the metric.
parameter_spec = {
    "learning_rate": hpt.DoubleParameterSpec(min=0.001, max=1, scale="log"),
    "momentum": hpt.DoubleParameterSpec(min=0, max=1, scale="linear"),
    "num_units": hpt.DiscreteParameterSpec(values=[64, 128, 512], scale=None)
}

مشخصات نهایی که باید تعریف شود metric_spec است، که یک فرهنگ لغت نشان دهنده متریک برای بهینه سازی است. کلید واژه نامه hyperparameter_metric_tag است که در کد برنامه آموزشی خود تنظیم کرده اید و مقدار آن هدف بهینه سازی است.

# Dicionary representing metrics to optimize.
# The dictionary key is the metric_id, which is reported by your training job,
# And the dictionary value is the optimization goal of the metric.
metric_spec={'accuracy':'maximize'}

هنگامی که مشخصات تعریف شد، یک CustomJob ایجاد خواهید کرد، که مشخصات رایجی است که برای اجرای کار شما در هر یک از آزمایش های تنظیم هایپرپارامتر استفاده می شود.

باید {YOUR_BUCKET} با سطلی که قبلا ایجاد کردید جایگزین کنید.

# Replace YOUR_BUCKET
my_custom_job = aiplatform.CustomJob(display_name='horses-humans',
                              worker_pool_specs=worker_pool_specs,
                              staging_bucket='gs://{YOUR_BUCKET}')

سپس HyperparameterTuningJob ایجاد و اجرا کنید.

hp_job = aiplatform.HyperparameterTuningJob(
    display_name='horses-humans',
    custom_job=my_custom_job,
    metric_spec=metric_spec,
    parameter_spec=parameter_spec,
    max_trial_count=6,
    parallel_trial_count=2,
    search_algorithm=None)

hp_job.run()

چند استدلال قابل ذکر است:

  • max_trial_count: شما باید یک کران بالایی برای تعداد آزمایش‌هایی که سرویس اجرا می‌کند قرار دهید. آزمایش‌های بیشتر معمولاً به نتایج بهتری منجر می‌شود، اما بازدهی کاهش می‌یابد، که پس از آن آزمایش‌های اضافی تأثیر کمی بر معیاری که می‌خواهید بهینه‌سازی کنید، ندارد. بهترین روش این است که با تعداد کمتری آزمایش شروع کنید و قبل از افزایش مقیاس، درک کنید که فراپارامترهای انتخابی شما چقدر تأثیرگذار هستند.
  • parallel_trial_count: اگر از آزمایش‌های موازی استفاده می‌کنید، سرویس چندین کلاستر پردازش آموزشی را ارائه می‌کند. افزایش تعداد آزمایش‌های موازی، مدت زمان اجرای کار تنظیم فراپارامتر را کاهش می‌دهد. با این حال، می تواند اثربخشی کار را به طور کلی کاهش دهد. این به این دلیل است که استراتژی تنظیم پیش‌فرض از نتایج آزمایش‌های قبلی برای اطلاع از تخصیص مقادیر در آزمایش‌های بعدی استفاده می‌کند.
  • search_algorithm: می‌توانید الگوریتم جستجو را به صورت شبکه‌ای، تصادفی یا پیش‌فرض (هیچ‌کدام) تنظیم کنید. گزینه پیش فرض بهینه سازی بیزی را برای جستجوی فضای مقادیر فراپارامتر ممکن اعمال می کند و الگوریتم پیشنهادی است. در اینجا می توانید با این الگوریتم بیشتر آشنا شوید.

پس از شروع کار، می‌توانید وضعیت را در رابط کاربری زیر برگه HYPERPARAMETER TUNING JOBS ردیابی کنید.

HP_job

پس از اتمام کار، می‌توانید نتایج آزمایش‌های خود را مشاهده و مرتب کنید تا بهترین ترکیب مقادیر فراپارامتر را کشف کنید.

HP_نتایج

🎉 تبریک می گویم! 🎉

شما یاد گرفته اید که چگونه از Vertex AI برای موارد زیر استفاده کنید:

  • یک کار تنظیم فراپارامتر با آموزش توزیع شده اجرا کنید

برای کسب اطلاعات بیشتر در مورد بخش‌های مختلف Vertex AI، مستندات را بررسی کنید.

8. پاکسازی

از آنجایی که ما نوت بوک را طوری پیکربندی کرده‌ایم که پس از 60 دقیقه بی‌حرکت، زمان آن تمام شود، نیازی نیست نگران خاموش کردن نمونه باشیم. اگر می خواهید نمونه را به صورت دستی خاموش کنید، روی دکمه Stop در بخش Vertex AI Workbench کنسول کلیک کنید. اگر می خواهید نوت بوک را به طور کامل حذف کنید، روی دکمه Delete کلیک کنید.

حذف

برای حذف Storage Bucket، با استفاده از منوی Navigation در Cloud Console خود، به Storage بروید، سطل خود را انتخاب کنید و روی Delete کلیک کنید:

ذخیره سازی را حذف کنید