Vertex AI: ضبط المعلَمة الفائقة الموزَّعة

1. نظرة عامة

في هذا التمرين المعملي، ستتعلم كيفية استخدام Vertex AI لضبط معلَمة فائقة والتدريب الموزَّع. يستخدم هذا التمرين المعملي TensorFlow لرمز النموذج، غير أنّ المفاهيم تنطبق على أطر عمل أخرى لتعلُّم الآلة أيضًا.

ما ستتعرّف عليه

ستتعرّف على كيفية:

  • تدريب نموذج باستخدام التدريب الموزّع على حاوية مخصّصة
  • إطلاق تجارب متعددة لرمز التدريب من أجل ضبط المَعلمات الفائقة بشكل آلي

تبلغ التكلفة الإجمالية لتنفيذ هذا البرنامج التدريبي على Google Cloud حوالي 6 دولار أمريكي.

2. مقدمة عن Vertex AI

يستخدم هذا البرنامج أحدث منتجات الذكاء الاصطناعي المتوفّرة على Google Cloud. تدمج Vertex AI عروض تعلُّم الآلة في Google Cloud في تجربة تطوير سلسة. في السابق، كان الوصول إلى النماذج المدرَّبة باستخدام AutoML والنماذج المخصّصة ممكنًا من خلال خدمات منفصلة. ويجمع العرض الجديد بين الاثنين في واجهة برمجة تطبيقات واحدة، إلى جانب منتجات جديدة أخرى. يمكنك أيضًا نقل المشاريع الحالية إلى Vertex AI. إذا كانت لديك أي ملاحظات، يُرجى الانتقال إلى صفحة الدعم.

تتضمّن Vertex AI العديد من المنتجات المختلفة لدعم سير عمل تعلُّم الآلة من البداية إلى النهاية. سيركّز هذا التمرين المعملي على التدريب وطاولة العمل.

نظرة عامة على منتجات Vertex

3- نظرة عامة على حالة الاستخدام

في هذا التمرين المعملي، ستستخدم ضبط المعلَمة الفائقة لاكتشاف المَعلَمات المثلى لنموذج تصنيف الصور المُدرَّب على مجموعة بيانات الخيول أو البشر من مجموعات بيانات TensorFlow.

ضبط المَعلمات الفائقة

تعمل ميزة ضبط المَعلمات الفائقة باستخدام أداة "تدريب Vertex AI" من خلال إجراء تجارب متعدّدة لتطبيق التدريب باستخدام قيم للمَعلمات الفائقة التي اخترتها، ويتم ضبطها ضمن الحدود التي تحدّدها. يتتبّع Vertex AI نتائج كل تجربة ويُجري التعديلات اللازمة على المحاولات اللاحقة.

لاستخدام ميزة ضبط المَعلمات الفائقة مع ميزة "تدريب Vertex AI"، عليك إجراء تغييرَين على رمز التدريب:

  1. حدِّد مَعلمة سطر أوامر في وحدة التدريب الرئيسية لكل مَعلمة متغيرة فائقة تريد ضبطها.
  2. استخدِم القيمة التي تم تمريرها في هذه الوسيطات لضبط المَعلمة الفائقة المقابلة في رمز تطبيقك.

التدريب الموزَّع

إذا كان لديك وحدة معالجة رسومات واحدة، سيستخدم TensorFlow هذا المُسرِّع لتسريع تدريب النموذج بدون أي جهد إضافي من جانبك. ومع ذلك، إذا كنت تريد الحصول على تحسين إضافي من خلال استخدام وحدات معالجة رسومات متعددة، عليك استخدام tf.distribute، وهي وحدة TensorFlow لتشغيل عملية حسابية على أجهزة متعددة.

تستخدِم هذه الميزة الاختبارية tf.distribute.MirroredStrategy، ويمكنك إضافتها إلى تطبيقات التدريب من خلال إجراء بعض التغييرات على الرمز فقط. تنشئ هذه الاستراتيجية نسخة من النموذج على كل وحدة معالجة رسومات في جهازك. وسيتم إجراء تعديلات التدرج اللوني اللاحقة بشكل متزامن. وهذا يعني أن كل وحدة معالجة رسومات تحسب التمرير للأمام والخلف عبر النموذج على شريحة مختلفة من بيانات الإدخال. بعد ذلك، يتم تجميع المشتقات المحسوبة من كل شريحة من هذه الشرائح على مستوى جميع وحدات معالجة الرسومات ويتم احتساب متوسطها في عملية تُعرف باسم all-reduce. ويتم تعديل مَعلمات النموذج باستخدام هذه التدرّجات المعدَّلة.

لست بحاجة إلى معرفة التفاصيل لإكمال هذه التجربة، ولكن إذا كنت تريد معرفة المزيد عن آلية عمل التدريب الموزّع في TensorFlow، يمكنك الاطّلاع على الفيديو أدناه:

4. إعداد البيئة

ستحتاج إلى مشروع على Google Cloud Platform تم تفعيل ميزة الفوترة فيه لتشغيل هذا الدليل التعليمي. لإنشاء مشروع، اتّبِع التعليمات الواردة هنا.

الخطوة 1: تفعيل واجهة برمجة تطبيقات Compute Engine

انتقِل إلى Compute Engine (محرك الحوسبة) واختَر تفعيل إذا لم يكن مفعّلاً.

الخطوة 2: تفعيل واجهة برمجة التطبيقات Container Registry API

انتقِل إلى مستودع الحِزم واختَر تفعيل إذا لم يكن مفعّلاً. ستستخدم هذا الإجراء لإنشاء حاوية لمهمة التدريب المخصّصة.

الخطوة 3: تفعيل واجهة برمجة التطبيقات Vertex AI API

انتقِل إلى قسم Vertex AI في Cloud Console وانقر على تفعيل Vertex AI API.

لوحة بيانات Vertex AI

الخطوة 4: إنشاء مثيل Vertex AI Workbench

من قسم Vertex AI في Cloud Console، انقر على Workbench:

قائمة Vertex AI

فعِّل واجهة برمجة التطبيقات Notebooks API إذا لم تكن مفعَّلة.

Notebook_api

بعد تفعيل هذه الميزة، انقر على دفاتر الملاحظات المُدارة:

Notebooks_UI

بعد ذلك، اختَر دفتر ملاحظات جديد.

new_notebook

أدخِل اسمًا لدفتر الملاحظات، ثم انقر على الإعدادات المتقدّمة.

create_notebook

ضمن "الإعدادات المتقدّمة"، فعِّل ميزة "إيقاف الجهاز في حال عدم النشاط" واضبط عدد الدقائق على 60. وهذا يعني أنه سيتم إيقاف تشغيل دفتر الملاحظات تلقائيًا عندما لا يتم استخدامه، وبذلك لن تتحمل أي تكاليف غير ضرورية.

idle_timeout

ضمن "الأمان"، اختَر "تفعيل وحدة التحكّم" إذا لم تكن مفعّلة.

enable-terminal

يمكنك ترك جميع الإعدادات المتقدّمة الأخرى كما هي.

بعد ذلك، انقر على إنشاء. ستستغرق عملية توفير المثيل بضع دقائق.

بعد إنشاء المثيل، اختَر فتح JupyterLab.

open_jupyterlab

في المرة الأولى التي تستخدم فيها مثيلًا جديدًا، سيُطلب منك المصادقة. اتّبِع الخطوات الواردة في واجهة المستخدم لإجراء ذلك.

مصادقة

5- كتابة رمز التدريب

للبدء، افتح نافذة Terminal (المحطة الطرفية) في مثيل دفتر ملاحظاتك من قائمة Launcher (المشغِّل):

launcher_terminal

أنشئ دليلاً جديدًا باسم vertex-codelab وانتقِل إليه باستخدام الأمر cd.

mkdir vertex-codelab
cd vertex-codelab

شغِّل ما يلي لإنشاء دليل لرمز التدريب وملف Python الذي ستضيف إليه الرمز:

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 بالمتغيّرات التي يجب نسخها على وحدات معالجة الرسومات.
  2. يتم زيادة حجم الدُفعة باستخدام num_replicas_in_sync. يُعدّ تغيير حجم الحزمة من أفضل الممارسات عند استخدام استراتيجيات التوازي المتزامن للبيانات في TensorFlow. يمكنك الاطّلاع على مزيد من المعلومات هنا.

ضبط المَعلمات الفائقة

  1. يستورد النص البرمجي مكتبة hypertune. في وقت لاحق عند إنشاء صورة الحاوية، سنحتاج إلى التأكّد من تثبيت هذه المكتبة.
  2. تحدّد الدالة get_args() وسيطة سطر أوامر لكل معلَمة فائقة تريد ضبطها. في هذا المثال، المَعلمات الفائقة التي سيتم ضبطها هي معدّل التعلّم وقيمة الزخم في أداة التحسين وعدد الوحدات في الطبقة المخفية الأخيرة من النموذج، ولكن يمكنك تجربة مَعلمات أخرى. بعد ذلك، يتم استخدام القيمة التي تم تمريرها في هذه الوسيطات لضبط المَعلمة الفائقة المقابلة في الرمز البرمجي (مثل set 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، ولكنك ستحتاج إلى استخدام السلسلة مرة أخرى لاحقًا عند بدء مهمة ضبط المعلَمة الفائقة.

6- تجميع الرمز في حاوية

الخطوة الأولى في احتواء التعليمة البرمجية هي إنشاء ملف Dockerfile. في الملف الشامل ستضمّن جميع الأوامر اللازمة لتشغيل الصورة. سيتم تثبيت جميع المكتبات اللازمة وإعداد نقطة الدخول لرمز التدريب.

الخطوة 1: كتابة Dockerfile

من تطبيق Terminal، تأكَّد من أنّك في الدليل vertex-codelab وأنشِئ ملفًا Dock فارغًا:

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 هذا صورة Docker لوحدة معالجة الرسومات Deep Learning Container TensorFlow Enterprise 2.7. تأتي حاويات تعلُّم الآلة العميقة على Google Cloud مع العديد من إطارات عمل تعلُّم الآلة وعلم البيانات الشائعة المثبَّتة مسبقًا. بعد تنزيل تلك الصورة، يُعِدّ هذا الملف الشامل نقطة الدخول لرمز التدريب.

الخطوة 2: إنشاء الحاوية

من Terminal، نفِّذ ما يلي لتحديد متغيّر env لمشروعك، مع الحرص على استبدال your-cloud-project بمعرّف مشروعك:

PROJECT_ID='your-cloud-project'

حدِّد متغيّرًا باستخدام معرّف الموارد المنتظم لصورة الحاوية في 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: إنشاء حزمة في Cloud Storage

في وظيفة التدريب، سنُدخل المسار إلى حزمة الاختبار.

شغِّل ما يلي في Terminal لإنشاء حزمة جديدة في مشروعك.

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

7- تشغيل مهمة ضبط المَعلمات الفائقة

الخطوة 1: إنشاء وظيفة تدريب مخصّصة من خلال ضبط المَعلمات الفائقة

افتح ورقة ملاحظات TensorFlow 2 جديدة من مشغِّل التطبيقات.

new_notebook

استورِد حزمة تطوير البرامج (SDK) لـ Vertex AI Python.

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

لبدء مهمة ضبط المَعلمات الفائقة، عليك أولاً تحديد 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 أو Categorical أو Discrete. إذا حددت النوع مزدوج أو عدد صحيح، فستحتاج إلى تقديم حد أدنى وحد أقصى للقيمة. وإذا اخترت "فئوية" أو "متقطّعة"، عليك تقديم القيم. بالنسبة إلى نوعَي 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: عليك وضع حدّ أقصى لعدد التجارب التي ستُجريها الخدمة. يؤدي إجراء المزيد من التجارب بشكل عام إلى تحقيق نتائج أفضل، ولكن سيكون هناك نقطة تحقّق فيها عائدات متضائلة، وبعدها لن يكون للتجارب الإضافية تأثير يذكر أو أي تأثير على المقياس الذي تحاول تحسينه. من أفضل الممارسات البدء بعدد صغير من التجارب والتعرّف على مدى تأثير المَعلمات الفائقة الاختيار قبل توسيع نطاقها.
  • الموازي_trial_count: إذا كنت تستخدم فترات تجريبية متوازية، توفِّر الخدمة مجموعات معالجة تدريب متعددة. تؤدي زيادة عدد التجارب الموازية إلى تقليل الوقت الذي تستغرقه مهمة ضبط المَعلمات الفائقة، ولكن يمكن أن تقلّل من فعالية المهمة بشكل عام. ويعود السبب في ذلك إلى أنّ استراتيجية الضبط التلقائية تستخدِم نتائج التجارب السابقة لتحديد القيم في التجارب اللاحقة.
  • خوارزمية البحث: يمكنك ضبط خوارزمية البحث على عرض شبكي أو عشوائي أو تلقائي (بدون). يطبّق الخيار التلقائي تحسين بايز للبحث في مساحة قيم المَعلمات الفائقة المحتمَلة، وهو الخوارزمية المُقترَحة. يمكنك الاطّلاع على مزيد من المعلومات حول هذه الخوارزمية هنا.

بعد بدء المهمة، ستتمكّن من تتبُّع الحالة في واجهة المستخدم ضمن علامة التبويب مهام ضبط المَعلمات الفائقة.

HP_job

بعد اكتمال المهمة، يمكنك عرض نتائج تجاربك وترتيبها لاكتشاف أفضل مجموعة من قيم المَعلمات الفائقة.

HP_results

🎉 تهانينا. 🎉

لقد تعلّمت كيفية استخدام Vertex AI لتنفيذ ما يلي:

  • تنفيذ مهمة ضبط المَعلمات الفائقة باستخدام التدريب الموزّع

لمزيد من المعلومات عن الأجزاء المختلفة من Vertex AI، اطّلِع على المستندات.

8. تنظيف

لأنّنا ضبطنا ورقة الملاحظات على انتهاء مهلة الحاسب بعد 60 دقيقة من عدم النشاط، لا داعي للقلق بشأن إيقاف تشغيل المثيل. إذا أردت إيقاف المثيل يدويًا، انقر على زر "إيقاف" في قسم Vertex AI Workbench من وحدة التحكّم. إذا أردت حذف دفتر الملاحظات بالكامل، انقر على الزر "حذف".

حذف

لحذف "حزمة التخزين"، باستخدام قائمة التنقّل في Cloud Console، انتقِل إلى "مساحة التخزين" واختَر الحزمة وانقر على "حذف":

حذف مساحة التخزين