Vertex AI: Điều chỉnh siêu tham số phân tán

1. Tổng quan

Trong lớp học này, bạn sẽ tìm hiểu cách sử dụng Vertex AI để điều chỉnh tham số siêu dữ liệu và huấn luyện phân tán. Mặc dù lớp học lập trình này sử dụng TensorFlow cho mã mô hình, nhưng các khái niệm này cũng áp dụng cho các khung máy học khác.

Kiến thức bạn sẽ học được

Bạn sẽ tìm hiểu cách:

  • Huấn luyện mô hình bằng phương pháp huấn luyện phân tán trên vùng chứa tuỳ chỉnh
  • Khởi chạy nhiều bản dùng thử cho mã huấn luyện của bạn để điều chỉnh siêu tham số tự động

Tổng chi phí để chạy lớp học này trên Google Cloud là khoảng 6 USD.

2. Giới thiệu về Vertex AI

Lớp học này sử dụng sản phẩm AI mới nhất có trên Google Cloud. Vertex AI tích hợp các dịch vụ học máy trên Google Cloud vào một trải nghiệm phát triển liền mạch. Trước đây, các mô hình được huấn luyện bằng AutoML và mô hình tuỳ chỉnh có thể truy cập được thông qua các dịch vụ riêng biệt. Sản phẩm mới kết hợp cả hai thành một API duy nhất, cùng với các sản phẩm mới khác. Bạn cũng có thể di chuyển các dự án hiện có sang Vertex AI. Nếu bạn có ý kiến phản hồi, vui lòng xem trang hỗ trợ.

Vertex AI bao gồm nhiều sản phẩm để hỗ trợ quy trình làm việc toàn diện về máy học. Lớp học này sẽ tập trung vào phần Hướng dẫnBảng điều khiển.

Tổng quan về sản phẩm Vertex

3. Tổng quan về trường hợp sử dụng

Trong phòng thí nghiệm này, bạn sẽ sử dụng tính năng tinh chỉnh siêu tham số để khám phá các tham số tối ưu cho một mô hình phân loại hình ảnh được huấn luyện trên tập dữ liệu ngựa hoặc người từ Tập dữ liệu TensorFlow.

Điều chỉnh siêu tham số

Tính năng Điều chỉnh tham số siêu dữ liệu bằng tính năng Huấn luyện AI của Vertex hoạt động bằng cách chạy nhiều thử nghiệm của ứng dụng huấn luyện với các giá trị cho tham số siêu dữ liệu đã chọn, được đặt trong giới hạn mà bạn chỉ định. Vertex AI theo dõi kết quả của mỗi thử nghiệm và điều chỉnh cho các thử nghiệm tiếp theo.

Để sử dụng tính năng điều chỉnh tham số siêu dữ liệu bằng tính năng Huấn luyện AI của Vertex, bạn cần thực hiện 2 thay đổi đối với mã huấn luyện:

  1. Xác định đối số dòng lệnh trong mô-đun huấn luyện chính cho từng tham số siêu dữ liệu mà bạn muốn điều chỉnh.
  2. Sử dụng giá trị được truyền trong các đối số đó để đặt tham số siêu dữ liệu tương ứng trong mã của ứng dụng.

Đào tạo phân tán

Nếu bạn có một GPU, TensorFlow sẽ sử dụng trình tăng tốc này để tăng tốc quá trình huấn luyện mô hình mà bạn không cần làm gì thêm. Tuy nhiên, nếu muốn tăng hiệu suất bằng cách sử dụng nhiều GPU, bạn cần sử dụng tf.distribute. Đây là mô-đun của TensorFlow để chạy phép tính trên nhiều thiết bị.

Phòng thí nghiệm này sử dụng tf.distribute.MirroredStrategy mà bạn có thể thêm vào các ứng dụng huấn luyện chỉ bằng một vài lần thay đổi mã. Chiến lược này tạo một bản sao của mô hình trên mỗi GPU trên máy của bạn. Các lần cập nhật độ dốc tiếp theo sẽ diễn ra một cách đồng bộ. Điều này có nghĩa là mỗi GPU tính toán các lượt truyền tới và lui thông qua mô hình trên một lát cắt khác của dữ liệu đầu vào. Sau đó, các độ dốc được tính toán từ mỗi lát cắt này được tổng hợp trên tất cả GPU và được tính trung bình trong một quy trình được gọi là tất cả giảm. Các tham số của mô hình được cập nhật bằng các độ dốc trung bình này.

Bạn không cần phải biết thông tin chi tiết để hoàn thành phòng thí nghiệm này, nhưng nếu bạn muốn tìm hiểu thêm về cách hoạt động của chương trình đào tạo phân tán trong TensorFlow, hãy xem video dưới đây:

4. Thiết lập môi trường

Bạn cần một dự án Google Cloud Platform đã bật tính năng thanh toán để chạy lớp học lập trình này. Để tạo dự án, hãy làm theo hướng dẫn tại đây.

Bước 1: Bật API Compute Engine

Chuyển đến Compute Engine rồi chọn Enable (Bật) nếu bạn chưa bật tính năng này.

Bước 2: Bật API Registry Container

Chuyển đến Container Registry (Cơ sở lưu trữ vùng chứa) rồi chọn Enable (Bật) nếu bạn chưa bật. Bạn sẽ sử dụng thông tin này để tạo một vùng chứa cho công việc huấn luyện tuỳ chỉnh.

Bước 3: Bật API Vertex AI

Chuyển đến mục Vertex AI trong Cloud Console rồi nhấp vào Bật API Vertex AI.

Trang tổng quan Vertex AI

Bước 4: Tạo một thực thể Vertex AI Workbench

Trong phần Vertex AI của Cloud Console, hãy nhấp vào Workbench (Bảng điều khiển):

Trình đơn Vertex AI

Bật Notebooks API nếu bạn chưa bật.

Notebook_api

Sau khi bật, hãy nhấp vào MANAGED NOTEBOOKS (SỔ ĐIỆN TỬ ĐƯỢC QUẢN LÝ):

Notebooks_UI

Sau đó, chọn NOTEBOOK MỚI.

new_notebook

Đặt tên cho sổ tay của bạn, sau đó nhấp vào Cài đặt nâng cao.

create_notebook

Trong phần Cài đặt nâng cao, hãy bật tính năng tắt khi không hoạt động và đặt số phút thành 60. Điều này có nghĩa là máy tính xách tay của bạn sẽ tự động tắt khi không sử dụng để bạn không phải chịu các chi phí không cần thiết.

idle_timeout

Trong phần Bảo mật, hãy chọn "Bật thiết bị đầu cuối" nếu bạn chưa bật.

enable-terminal

Bạn có thể giữ nguyên mọi chế độ cài đặt nâng cao khác.

Tiếp theo, hãy nhấp vào Tạo. Quá trình cấp phép thực thể sẽ mất vài phút.

Sau khi tạo thực thể, hãy chọn Open JupyterLab (Mở JupyterLab).

open_jupyterlab

Trong lần đầu tiên sử dụng một thực thể mới, bạn sẽ được yêu cầu xác thực. Hãy làm theo các bước trong giao diện người dùng để thực hiện việc này.

xác thực

5. Viết mã huấn luyện

Để bắt đầu, trên trình đơn Trình chạy, hãy mở cửa sổ dòng lệnh trong thực thể sổ tay của bạn:

launcher_terminal

Tạo một thư mục mới có tên là vertex-codelab rồi chuyển vào thư mục đó.

mkdir vertex-codelab
cd vertex-codelab

Chạy lệnh sau để tạo thư mục cho mã huấn luyện và một tệp Python nơi bạn sẽ thêm mã:

mkdir trainer
touch trainer/task.py

Bây giờ, bạn sẽ có những nội dung sau trong thư mục vertex-codelab:

+ trainer/
    + task.py

Tiếp theo, hãy mở tệp task.py bạn vừa tạo và dán tất cả mã bên dưới vào.

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()

Hãy cùng tìm hiểu kỹ hơn về mã và kiểm tra các thành phần dành riêng cho việc huấn luyện phân tán và điều chỉnh tham số siêu dữ liệu.

Đào tạo phân tán

  1. Trong hàm main(), đối tượng MirroredStrategy được tạo. Tiếp theo, bạn kết hợp việc tạo các biến mô hình trong phạm vi của chiến lược. Bước này cho TensorFlow biết những biến nào cần được phản chiếu trên các GPU.
  2. Kích thước lô được điều chỉnh theo tỷ lệ bằng num_replicas_in_sync. Điều chỉnh quy mô kích thước lô là phương pháp hay nhất khi sử dụng các chiến lược song song dữ liệu đồng bộ trong TensorFlow. Bạn có thể tìm hiểu thêm tại đây.

Điều chỉnh siêu tham số

  1. Tập lệnh này nhập thư viện hypertune. Sau này, khi tạo hình ảnh vùng chứa, chúng ta cần đảm bảo đã cài đặt thư viện này.
  2. Hàm get_args() xác định đối số dòng lệnh cho từng tham số siêu dữ liệu mà bạn muốn điều chỉnh. Trong ví dụ này, các tham số siêu dữ liệu sẽ được điều chỉnh là tốc độ học, giá trị động lượng trong trình tối ưu hoá và số lượng đơn vị trong lớp ẩn cuối cùng của mô hình, nhưng bạn có thể tự do thử nghiệm với các tham số khác. Sau đó, giá trị được truyền trong các đối số đó được dùng để đặt tham số siêu dữ liệu tương ứng trong mã (ví dụ: đặt learning_rate = args.learning_rate)
  3. Ở cuối hàm main(), thư viện hypertune được dùng để xác định chỉ số bạn muốn tối ưu hoá. Trong TensorFlow, phương thức model.fit của Keras trả về một đối tượng History. Thuộc tính History.history là bản ghi các giá trị tổn thất huấn luyện và giá trị chỉ số tại các thời gian liên tiếp. Nếu bạn chuyển dữ liệu xác thực đến model.fit, thuộc tính History.history cũng sẽ bao gồm tổn thất xác thực và các giá trị chỉ số. Ví dụ: nếu bạn huấn luyện một mô hình trong ba epoch bằng dữ liệu xác thực và cung cấp accuracy làm chỉ số, thì thuộc tính History.history sẽ tương tự như từ điển sau.
{
 "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
 ]

Nếu muốn dịch vụ điều chỉnh tham số siêu dữ liệu khám phá các giá trị giúp tối đa hoá độ chính xác xác thực của mô hình, bạn hãy xác định chỉ số này là mục cuối cùng (hoặc NUM_EPOCS - 1) của danh sách val_accuracy. Sau đó, hãy truyền chỉ số này đến một thực thể của HyperTune. Bạn có thể chọn bất kỳ chuỗi nào bạn muốn cho hyperparameter_metric_tag, nhưng sau này bạn sẽ cần sử dụng lại chuỗi đó khi bắt đầu công việc điều chỉnh tham số siêu dữ liệu.

6. Vùng chứa mã

Bước đầu tiên trong việc đóng gói mã là tạo một Dockerfile. Trong Dockerfile, bạn sẽ thêm tất cả các lệnh cần thiết để chạy hình ảnh. Công cụ này sẽ cài đặt tất cả thư viện cần thiết và thiết lập điểm truy cập cho mã huấn luyện.

Bước 1: Viết Dockerfile

Trong Terminal, hãy đảm bảo bạn đang ở thư mục vertex-codelab và tạo một Dockerfile trống:

touch Dockerfile

Bây giờ, bạn sẽ có những nội dung sau trong thư mục vertex-codelab:

+ Dockerfile
+ trainer/
    + task.py

Mở Dockerfile và sao chép nội dung sau vào tệp đó:

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"]

Tệp Dockerfile này sử dụng hình ảnh Docker GPU TensorFlow Enterprise 2.7 của Vùng chứa học sâu. Vùng chứa học sâu trên Google Cloud được cài đặt sẵn nhiều khung học máy và khoa học dữ liệu phổ biến. Sau khi tải hình ảnh đó xuống, Dockerfile này sẽ thiết lập điểm truy cập cho mã đào tạo.

Bước 2: Tạo vùng chứa

Trên Terminal, hãy chạy đoạn mã sau để xác định biến env cho dự án, nhớ thay thế your-cloud-project bằng mã nhận dạng của dự án:

PROJECT_ID='your-cloud-project'

Xác định một biến bằng URI của hình ảnh vùng chứa trong Google Container Registry:

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

Định cấu hình Docker

gcloud auth configure-docker

Sau đó, hãy tạo vùng chứa bằng cách chạy lệnh sau từ thư mục gốc vertex-codelab:

docker build ./ -t $IMAGE_URI

Cuối cùng, hãy đẩy địa chỉ email này đến Google Container Registry:

docker push $IMAGE_URI

Bước 3: Tạo một bộ chứa Cloud Storage

Trong công việc huấn luyện, chúng ta sẽ truyền vào đường dẫn đến một bộ chứa giai đoạn.

Chạy đoạn mã sau trong Terminal để tạo một bộ chứa mới trong dự án.

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

7. Khởi chạy công việc điều chỉnh siêu tham số

Bước 1: Tạo công việc huấn luyện tuỳ chỉnh bằng cách điều chỉnh tham số siêu dữ liệu

Trên trình chạy, hãy mở một Sổ tay TensorFlow 2 mới.

new_notebook

Nhập SDK Vertex AI Python.

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

Để chạy công việc điều chỉnh tham số siêu dữ liệu, trước tiên, bạn cần xác định worker_pool_specs. Tham số này chỉ định loại máy và hình ảnh Docker. Thông số kỹ thuật sau đây xác định một máy có hai GPU NVIDIA Tesla V100.

Bạn cần thay thế {PROJECT_ID} trong image_uri bằng dự án của mình.

# 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"
    }
}]

Tiếp theo, hãy xác định parameter_spec. Đây là một từ điển chỉ định các thông số mà bạn muốn tối ưu hoá. Khoá từ điển là chuỗi mà bạn chỉ định cho đối số dòng lệnh cho mỗi tham số siêu dữ liệu và giá trị từ điển là thông số kỹ thuật của tham số.

Đối với mỗi tham số siêu dữ liệu, bạn cần xác định Loại cũng như giới hạn cho các giá trị mà dịch vụ điều chỉnh sẽ thử. Siêu tham số có thể thuộc loại Kép, Số nguyên, Phân loại hoặc Rời rạc. Nếu chọn loại Double hoặc Integer, bạn cần cung cấp giá trị tối thiểu và tối đa. Còn nếu chọn Phân loại hoặc Rời rạc, bạn cần cung cấp các giá trị. Đối với các loại Double và Integer, bạn cũng cần cung cấp giá trị Scaling (Điều chỉnh theo tỷ lệ). Bạn có thể tìm hiểu thêm về cách chọn thang đo phù hợp nhất trong video này.

# 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)
}

Thông số cuối cùng cần xác định là metric_spec, đây là một từ điển đại diện cho chỉ số cần tối ưu hoá. Khoá từ điển là hyperparameter_metric_tag mà bạn đặt trong mã ứng dụng huấn luyện và giá trị là mục tiêu tối ưu hoá.

# 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'}

Sau khi xác định các thông số, bạn sẽ tạo một CustomJob. Đây là thông số phổ biến dùng để chạy công việc của bạn trong mỗi lượt thử điều chỉnh siêu tham số.

Bạn cần thay thế {YOUR_BUCKET} bằng bộ chứa mà bạn đã tạo trước đó.

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

Sau đó, hãy tạo và chạy 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()

Có một số đối số cần lưu ý:

  • max_trial_count: Bạn cần phải đặt giới hạn trên về số lượt dùng thử mà dịch vụ sẽ chạy. Thông thường, càng có nhiều thử nghiệm thì kết quả càng tốt, nhưng sẽ có một điểm lợi tức giảm dần, sau đó các thử nghiệm bổ sung sẽ ít hoặc không ảnh hưởng đến chỉ số mà bạn đang cố gắng tối ưu hoá. Tốt nhất là bạn nên bắt đầu với số lượng thử nghiệm ít hơn và nắm được mức độ tác động của các tham số siêu dữ liệu mà bạn đã chọn trước khi mở rộng quy mô.
  • parallel_trial_count: Nếu bạn sử dụng thử nghiệm song song, dịch vụ sẽ cung cấp nhiều cụm xử lý huấn luyện. Việc tăng số lượng phiên bản thử song song sẽ làm giảm thời gian cần để chạy công việc điều chỉnh siêu thông số. Tuy nhiên, điều này có thể làm giảm hiệu quả của toàn bộ công việc. Điều này là do chiến lược điều chỉnh mặc định sử dụng kết quả của các thử nghiệm trước đó để thông báo việc chỉ định giá trị trong các thử nghiệm tiếp theo.
  • search_algorithm: Bạn có thể đặt thuật toán tìm kiếm thành lưới, ngẫu nhiên hoặc mặc định (Không có). Tuỳ chọn mặc định áp dụng phương pháp tối ưu hoá Bayesian để tìm kiếm không gian của các giá trị tham số siêu dữ liệu có thể có và là thuật toán được đề xuất. Bạn có thể tìm hiểu thêm về thuật toán này tại đây.

Sau khi công việc bắt đầu, bạn có thể theo dõi trạng thái trong giao diện người dùng trong thẻ CÔNG VIỆC ĐIỀU CHỈNH THÔNG SỐ Siêu tham số.

HP_job

Sau khi công việc hoàn tất, bạn có thể xem và sắp xếp kết quả của các lượt thử để khám phá tổ hợp giá trị siêu tham số tốt nhất.

HP_results

🎉 Xin chúc mừng! 🎉

Bạn đã tìm hiểu cách sử dụng Vertex AI để:

  • Chạy công việc điều chỉnh tham số siêu dữ liệu bằng phương pháp huấn luyện phân tán

Để tìm hiểu thêm về các phần khác nhau của Vertex AI, hãy xem tài liệu.

8. Dọn dẹp

Vì chúng ta đã định cấu hình máy tính xách tay để hết thời gian chờ sau 60 phút không hoạt động, nên chúng ta không cần lo lắng về việc tắt thực thể. Nếu bạn muốn tắt thực thể theo cách thủ công, hãy nhấp vào nút Dừng trong phần Vertex AI Workbench của bảng điều khiển. Nếu bạn muốn xoá toàn bộ sổ tay, hãy nhấp vào nút Xoá.

xóa

Để xoá Bộ nhớ, hãy sử dụng trình đơn Điều hướng trong Cloud Console, chuyển đến Bộ nhớ, chọn bộ nhớ của bạn rồi nhấp vào Xoá:

Xoá bộ nhớ