1. Tổng quan
Trong phòng thí nghiệm này, bạn sẽ tìm hiểu cách sử dụng Vertex AI để điều chỉnh siêu tham số và huấn luyện phân tán. Mặc dù phòng thí nghiệm 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 được cho các khung ML 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 cách sử dụng quy trình huấn luyện phân tán trên một vùng chứa tuỳ chỉnh
- Chạy nhiều thử nghiệm về mã huấn luyện để tự động điều chỉnh siêu tham số
Tổng chi phí để chạy bài tập này trên Google Cloud là khoảng 6 USD.
2. Giới thiệu về Vertex AI
Phòng thí nghiệm này sử dụng sản phẩm AI mới nhất hiện có trên Google Cloud. Vertex AI tích hợp các sản phẩm ML trên Google Cloud thành 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à các mô hình tuỳ chỉnh có thể truy cập thông qua các dịch vụ riêng biệt. Sản phẩm mới này 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 truy cập trang hỗ trợ.
Vertex AI có nhiều sản phẩm để hỗ trợ quy trình làm việc ML toàn diện. Phòng thí nghiệm này sẽ tập trung vào Đào tạo và Workbench.

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 quy trình điều 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 về 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 siêu tham số bằng Vertex AI Training hoạt động bằng cách chạy nhiều thử nghiệm cho ứng dụng huấn luyện của bạn với các giá trị cho siêu tham số đã chọn, được đặt trong giới hạn mà bạn chỉ định. Vertex AI theo dõi kết quả của từng 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 siêu tham số bằng Vertex AI Training, bạn cần thực hiện 2 thay đổi đối với mã huấn luyện:
- Xác định một đối số dòng lệnh trong mô-đun huấn luyện chính cho từng siêu tham số mà bạn muốn điều chỉnh.
- Sử dụng giá trị được truyền trong các đối số đó để đặt siêu tham số tương ứng trong mã của ứng dụng.
Huấn luyện 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 phải làm gì thêm. Tuy nhiên, nếu muốn tăng hiệu suất hơn nữa 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 một phép tính trên nhiều thiết bị.
Lớp học này sử dụng tf.distribute.MirroredStrategy. Bạn chỉ cần thay đổi một chút mã là có thể thêm tf.distribute.MirroredStrategy vào các ứng dụng huấn luyện của mình. 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 bản cập nhật độ dốc tiếp theo sẽ diễn ra theo cách đồng bộ. Điều này có nghĩa là mỗi GPU sẽ tính toán các lượt truyền xuôi và ngược thông qua mô hình trên một phần 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 sẽ được tổng hợp trên tất cả các GPU và được tính trung bình trong một quy trình được gọi là giảm tất cả. Các thông số mô hình được cập nhật bằng cách sử dụng các độ dốc trung bình này.
Bạn không cần nắm rõ chi tiết để hoàn thành lớp học này, nhưng nếu muốn tìm hiểu thêm về cách hoạt động của quy trình huấn luyện phân tán trong TensorFlow, hãy xem video bên dưới:
4. Thiết lập môi trường
Bạn cần có một dự án trê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 một dự án, hãy làm theo hướng dẫn tại đây.
Bước 1: Bật Compute Engine API
Chuyển đến Compute Engine rồi chọn Bật nếu bạn chưa bật.
Bước 2: Bật Container Registry API
Chuyển đến Container Registry rồi chọn Bật nếu bạn chưa bật. Bạn 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 Vertex AI API
Chuyển đến mục Vertex AI trong Bảng điều khiển Cloud rồi nhấp vào Bật Vertex AI API.

Bước 4: Tạo một phiên bản Vertex AI Workbench
Trong phần Vertex AI của Cloud Console, hãy nhấp vào Workbench:

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

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

Sau đó, chọn SỔ TAY MỚI.

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

Trong phần Cài đặt nâng cao, hãy bật chế độ tắt khi không hoạt động và đặt số phút thành 60. Điều này có nghĩa là sổ 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.

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.

Bạn có thể giữ nguyên tất cả các chế độ cài đặt nâng cao khác.
Tiếp theo, hãy nhấp vào Tạo. Thực thể sẽ mất vài phút để được cấp phép.
Sau khi tạo phiên bản, hãy chọn Mở JupyterLab.

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

5. Viết mã huấn luyện
Để bắt đầu, từ trình đơn Trình chạy, hãy mở cửa sổ dòng lệnh trong phiên bản sổ tay của bạn:

Tạo một thư mục mới có tên là vertex-codelab rồi chuyển đến thư mục đó.
mkdir vertex-codelab
cd vertex-codelab
Chạy lệnh sau để tạo một 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 rồi 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 xem xét kỹ hơn mã này và kiểm tra các thành phần dành riêng cho hoạt động huấn luyện phân tán và điều chỉnh siêu tham số.
Huấn luyện phân tán
- Trong hàm
main(), đối tượngMirroredStrategyđược tạo. Tiếp theo, bạn sẽ bao bọc quá trình 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. - Kích thước lô được tăng lên theo
num_replicas_in_sync. Chuyển tỉ lệ kích thước lô là một phương pháp hay nhất khi sử dụng các chiến lược song song hoá 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ố
- 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 rằng mình đã cài đặt thư viện này. - Hàm
get_args()xác định một đối số dòng lệnh cho từng siêu tham số mà bạn muốn điều chỉnh. Trong ví dụ này, các siêu tham số 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. Tuy nhiên, bạn có thể thử nghiệm với các siêu tham số khác. Sau đó, giá trị được truyền trong các đối số đó sẽ được dùng để đặt siêu tham số tương ứng trong mã (ví dụ: đặtlearning_rate = args.learning_rate) - Ở cuối hàm
main(), thư việnhypertuneđược dùng để xác định chỉ số mà bạn muốn tối ưu hoá. Trong TensorFlow, phương thứcmodel.fitcủa Keras sẽ trả về một đối tượngHistory. Thuộc tínhHistory.historylà một bản ghi các giá trị tổn thất khi huấn luyện và các giá trị chỉ số ở các giai đoạn liên tiếp. Nếu bạn truyền dữ liệu xác thực đếnmodel.fit, thuộc tínhHistory.historycũng sẽ bao gồm các giá trị chỉ số và tổn thất xác thực. Ví dụ: nếu bạn huấn luyện một mô hình cho 3 giai đoạn với dữ liệu xác thực và cung cấpaccuracylàm chỉ số, thì thuộc tínhHistory.historysẽ có dạng 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 bạn muốn dịch vụ điều chỉnh siêu tham số 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, 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 phiên bản của HyperTune. Bạn có thể chọn bất kỳ chuỗi nào bạn thích cho hyperparameter_metric_tag, nhưng bạn sẽ cần sử dụng lại chuỗi này sau khi bắt đầu công việc điều chỉnh siêu tham số.
6. Chứa mã
Bước đầu tiên trong việc chứa mã của bạn là tạo một Dockerfile. Trong Dockerfile, bạn sẽ đưa tất cả các lệnh cần thiết để chạy hình ảnh. Thao tác này sẽ cài đặt tất cả cá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 ở trong 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 rồi sao chép nội dung sau vào đó:
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 này sử dụng Hình ảnh Docker GPU TensorFlow Enterprise 2.7 của Deep Learning Container. Deep Learning Containers 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ã huấn luyện.
Bước 2: Tạo vùng chứa
Trong Terminal, hãy chạy lệnh sau để xác định một biến môi trường cho dự án của bạn, nhớ thay thế your-cloud-project bằng mã 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ừ gốc của thư mục vertex-codelab:
docker build ./ -t $IMAGE_URI
Cuối cùng, hãy đẩy nó vào Google Container Registry:
docker push $IMAGE_URI
Bước 3: Tạo một bộ chứa Cloud Storage
Trong quy trình huấn luyện, chúng ta sẽ truyền đường dẫn đến một vùng lưu trữ tạm thời.
Chạy lệnh sau trong Terminal để tạo một nhóm mới trong dự án của bạn.
BUCKET_NAME="gs://${PROJECT_ID}-hptune-bucket"
gsutil mb -l us-central1 $BUCKET_NAME
7. Chạy quy trình điều chỉnh siêu tham số
Bước 1: Tạo quy trình huấn luyện tuỳ chỉnh bằng tính năng điều chỉnh siêu tham số
Trên trình chạy, hãy mở một Sổ tay TensorFlow 2 mới.

Nhập Vertex AI Python SDK.
from google.cloud import aiplatform
from google.cloud.aiplatform import hyperparameter_tuning as hpt
Để chạy quy trình điều chỉnh siêu tham số, trước tiên, bạn cần xác định worker_pool_specs, trong đó chỉ định loại máy và hình ảnh Docker. Quy cách sau đây xác định một máy có 2 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 của từng siêu tham số và giá trị từ điển là quy cách tham số.
Đối với mỗi siêu tham số, bạn cần xác định Loại cũng như ranh giới 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 Double, Integer, Categorical hoặc Discrete. 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. Nếu chọn Categorical (Phân loại) hoặc Discrete (Rời rạc), bạn sẽ 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. Bạn có thể tìm hiểu thêm về cách chọn tỷ lệ 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ã xử lý ứ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ố kỹ thuật, bạn sẽ tạo một CustomJob. Đây là thông số kỹ thuật chung sẽ được dùng để chạy công việc của bạn trên từng thử nghiệm điều chỉnh siêu tham số.
Bạn cần thay thế {YOUR_BUCKET} bằng nhóm 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()
Sau đây là một số lập luận cần lưu ý:
- max_trial_count: Bạn cần đặt một giới hạn trên cho số lần thử mà dịch vụ sẽ chạy. Thông thường, càng nhiều lượt thử nghiệm thì kết quả càng tốt, nhưng sẽ có một điểm lợi nhuận giảm dần, sau đó các lượt 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á. Bạn nên bắt đầu với một số ít thời gian dùng thử và nắm được mức độ tác động của các siêu tham số đã chọn trước khi chuyển tỉ lệ.
- parallel_trial_count: Nếu bạn sử dụng các 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 thử nghiệm song song sẽ giảm thời gian chạy của quy trình điều chỉnh siêu tham số; tuy nhiên, điều này có thể làm giảm hiệu quả tổng thể của quy trình. Đ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ó). Lựa chọn mặc định áp dụng phương pháp tối ưu hoá Bayes để tìm kiếm không gian của các giá trị siêu tham số có thể 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 trên thẻ CÔNG VIỆC ĐIỀU CHỈNH SIÊU THAM SỐ.

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

🎉 Xin chúc mừng! 🎉
Bạn đã tìm hiểu cách sử dụng Vertex AI để:
- Chạy một lệnh điều chỉnh siêu tham số bằng tính năng 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 sổ 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 phiên bản. 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á hoàn toàn sổ tay, hãy nhấp vào nút Xoá.

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