1. Tổng quan
Trong bài tập thực hành này, bạn sẽ thực hiện quy trình huấn luyện mô hình học máy hoàn chỉnh trên Google Cloud bằng cách sử dụng PyTorch để xây dựng mô hình. Trong môi trường Cloud AI Platform Notebooks, bạn sẽ tìm hiểu cách đóng gói công việc huấn luyện để kích hoạt công việc đó trên AI Platform Training (Huấn luyện trên Nền tảng Trí tuệ nhân tạo) với tính năng điều chỉnh siêu tham số.
Kiến thức bạn sẽ học được
Bạn sẽ tìm hiểu cách:
- Tạo một thực thể Nền tảng Trí tuệ nhân tạo Notebooks
- Tạo mô hình PyTorch
- Huấn luyện mô hình bằng tính năng điều chỉnh siêu tham số trên Nền tảng Trí tuệ nhân tạo Training
Tổng chi phí để chạy bài tập thực hành này trên Google Cloud là khoảng 1 USD.
2. 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 API Mô hình Nền tảng Trí tuệ nhân tạo Cloud
Chuyển đến phần Mô hình Nền tảng Trí tuệ nhân tạo trong Cloud Console (Bảng điều khiển Cloud) rồi nhấp vào Bật nếu chưa bật.

Bước 2: Bật API Compute Engine
Chuyển đến Compute Engine rồi chọn Bật nếu chưa bật. Bạn cần bật API này để tạo thực thể sổ ghi chú.
Bước 3: Tạo một thực thể Nền tảng Trí tuệ nhân tạo Notebooks
Chuyển đến phần Sổ tay Nền tảng Trí tuệ nhân tạo trong bảng điều khiển Cloud rồi nhấp vào Thực thể mới. Sau đó, hãy chọn loại thực thể PyTorch mới nhất (không có GPU):

Sử dụng các lựa chọn mặc định hoặc đặt tên tuỳ chỉnh nếu muốn, rồi nhấp vào Create (Tạo). Sau khi tạo thực thể, hãy chọn Open JupyterLab (Mở JupyterLab):

Tiếp theo, hãy mở một thực thể Python 3 Notebook từ trình chạy:

Bạn đã sẵn sàng bắt đầu!
Bước 5: Nhập các gói Python
Trong ô đầu tiên của sổ ghi chú, hãy thêm các mục nhập sau rồi chạy ô. Bạn có thể kích hoạt bằng cách nhấn vào nút mũi tên phải trong trình đơn trên cùng hoặc nhấn vào lệnh-enter:
import datetime
import numpy as np
import os
import pandas as pd
import time
Bạn sẽ nhận thấy rằng chúng ta không nhập PyTorch tại đây. Lý do là vì chúng ta đang chạy công việc huấn luyện trên AI Platform Training (Huấn luyện trên Nền tảng Trí tuệ nhân tạo), chứ không phải từ thực thể Notebook.
3. Tạo một gói cho công việc huấn luyện
Để chạy công việc huấn luyện trên AI Platform Training (Huấn luyện trên Nền tảng Trí tuệ nhân tạo), chúng ta cần đóng gói mã huấn luyện cục bộ trong thực thể Notebooks và một vùng chứa Cloud Storage để lưu trữ tài sản cho công việc. Trước tiên, chúng ta sẽ tạo một bộ chứa lưu trữ. Bạn có thể bỏ qua bước này nếu đã có một vùng chứa.
Bước 1: Tạo một vùng chứa Cloud Storage cho mô hình
Trước tiên, hãy xác định một số biến môi trường mà chúng ta sẽ sử dụng trong phần còn lại của lớp học lập trình này. Điền các giá trị bên dưới bằng tên dự án trên đám mây Google Cloud và tên bộ chứa Cloud Storage mà bạn muốn tạo (phải là duy nhất trên toàn cầu):
# Update these to your own GCP project, model, and version names
GCP_PROJECT = 'your-gcp-project'
BOCKET_URL = 'gs://storage_bucket_name'
Giờ đây, chúng ta đã sẵn sàng tạo một bộ chứa lưu trữ mà chúng ta sẽ trỏ đến khi bắt đầu công việc huấn luyện.
Chạy lệnh gsutil này trong sổ ghi chú để tạo một vùng chứa:
!gsutil mb $BUCKET_URL
Bước 2: Tạo các tệp ban đầu cho gói Python
Để chạy công việc huấn luyện trên Nền tảng Trí tuệ nhân tạo, chúng ta cần định cấu hình mã dưới dạng gói Python. Gói này bao gồm một tệp setup.py trong thư mục gốc chỉ định mọi phần phụ thuộc của gói bên ngoài, một thư mục con có tên gói của chúng ta (ở đây, chúng ta sẽ gọi là trainer/) và một tệp __init__.py trống trong thư mục con này.
Trước tiên, hãy viết tệp setup.py. Chúng ta đang sử dụng iPython %%writefile magics để lưu tệp vào thực thể. Ở đây, chúng ta đã chỉ định 3 thư viện bên ngoài mà chúng ta sẽ sử dụng trong mã huấn luyện: PyTorch, Scikit-learn và 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.'
)
Tiếp theo, hãy tạo thư mục trainer/ và tệp init.py trống trong thư mục đó. Python sử dụng tệp này để nhận ra rằng đây là một gói:
!mkdir trainer
!touch trainer/__init__.py
Giờ đây, chúng ta đã sẵn sàng bắt đầu tạo công việc huấn luyện.
4. Xem trước tập dữ liệu
Trọng tâm của bài tập thực hành này là các công cụ để huấn luyện mô hình tại đây, nhưng hãy xem nhanh tập dữ liệu mà chúng ta sẽ sử dụng để huấn luyện mô hình nhằm hiểu rõ hơn. Chúng ta sẽ sử dụng tập dữ liệu về tỷ lệ sinh có trong BigQuery. Tập dữ liệu này chứa dữ liệu về tỷ lệ sinh ở Hoa Kỳ trong vài thập kỷ. Chúng ta sẽ sử dụng một vài cột trong tập dữ liệu để dự đoán cân nặng của trẻ sơ sinh. Tập dữ liệu gốc khá lớn và chúng ta sẽ sử dụng một tập hợp con của tập dữ liệu đó mà chúng tôi đã cung cấp cho bạn trong một bộ chứa Cloud Storage.
Bước 1: Tải tập dữ liệu về tỷ lệ sinh BigQuery xuống
Hãy tải phiên bản tập dữ liệu mà chúng tôi đã cung cấp cho bạn trong Cloud Storage xuống một Pandas DataFrame và xem trước tập dữ liệu đó.
natality = pd.read_csv('https://storage.googleapis.com/ml-design-patterns/natality.csv')
natality.head()
Tập dữ liệu này có chưa đến 100.000 hàng. Chúng ta sẽ sử dụng 5 đặc điểm để dự đoán cân nặng của trẻ sơ sinh: tuổi của mẹ và cha, số tuần thai, cân nặng của mẹ tăng lên tính bằng pound và giới tính của trẻ sơ sinh được biểu thị dưới dạng boolean.
5. Xác định công việc huấn luyện bằng tính năng điều chỉnh siêu tham số
Chúng ta sẽ viết tập lệnh huấn luyện vào một tệp có tên là model.py trong thư mục con trainer/ mà chúng ta đã tạo trước đó. Công việc huấn luyện của chúng ta sẽ chạy trên AI Platform Training (Huấn luyện trên Nền tảng Trí tuệ nhân tạo) và cũng sẽ sử dụng dịch vụ điều chỉnh siêu tham số của Nền tảng Trí tuệ nhân tạo để tìm các siêu tham số tối ưu cho mô hình của chúng ta bằng cách tối ưu hoá Bayesian.
Bước 1: Tạo tập lệnh huấn luyện
Trước tiên, hãy tạo tệp Python bằng tập lệnh huấn luyện. Sau đó, chúng ta sẽ phân tích những gì đang diễn ra trong đó. Việc chạy lệnh %%writefile này sẽ ghi mã mô hình vào một tệp Python cục bộ:
%%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()
Công việc huấn luyện bao gồm 2 hàm nơi phần lớn công việc đang diễn ra.
get_args(): Hàm này phân tích cú pháp các đối số dòng lệnh mà chúng ta sẽ truyền khi tạo công việc huấn luyện, cùng với các siêu tham số mà chúng ta muốn Nền tảng Trí tuệ nhân tạo tối ưu hoá. Trong ví dụ này, danh sách đối số của chúng ta chỉ bao gồm các siêu tham số mà chúng ta sẽ tối ưu hoá – tốc độ học tập, động lượng của mô hình và số lượng nơ-ron trong lớp ẩn.train_model(): Tại đây, chúng ta tải dữ liệu xuống một Pandas DataFrame, chuẩn hoá dữ liệu đó, chuyển đổi thành PyTorch Tensors, rồi xác định mô hình. Để xây dựng mô hình, chúng ta đang sử dụng APInn.Sequentialcủa PyTorch, cho phép chúng ta xác định mô hình dưới dạng một ngăn xếp các lớp:
model = nn.Sequential(nn.Linear(len(train_x[0]), args.hidden_layer_size),
nn.ReLU(),
nn.Linear(args.hidden_layer_size, 1))
Lưu ý rằng thay vì mã hoá cứng kích thước của lớp ẩn của mô hình, chúng ta đang biến đây thành một siêu tham số mà Nền tảng Trí tuệ nhân tạo sẽ điều chỉnh cho chúng ta. Thông tin chi tiết hơn về vấn đề này trong phần tiếp theo.
Bước 2: Sử dụng dịch vụ điều chỉnh siêu tham số của Nền tảng Trí tuệ nhân tạo
Thay vì thử các giá trị siêu tham số khác nhau theo cách thủ công và huấn luyện lại mô hình mỗi lần, chúng ta sẽ sử dụng dịch vụ tối ưu hoá siêu tham số của Nền tảng Trí tuệ nhân tạo Cloud. Nếu chúng ta thiết lập công việc huấn luyện bằng các đối số siêu tham số, thì Nền tảng Trí tuệ nhân tạo sẽ sử dụng tính năng tối ưu hoá Bayesian để tìm các giá trị lý tưởng cho các siêu tham số mà chúng ta chỉ định.
Trong quá trình điều chỉnh siêu tham số, một lần thử duy nhất bao gồm một lần chạy huấn luyện mô hình của chúng ta với một tổ hợp cụ thể các giá trị siêu tham số. Tuỳ thuộc vào số lượng thử nghiệm mà chúng ta chạy, Nền tảng Trí tuệ nhân tạo sẽ sử dụng kết quả của các thử nghiệm đã hoàn tất để tối ưu hoá các siêu tham số mà nền tảng này chọn cho các thử nghiệm trong tương lai. Để định cấu hình tính năng điều chỉnh siêu tham số, chúng ta cần truyền một tệp cấu hình khi bắt đầu công việc huấn luyện bằng một số dữ liệu về từng siêu tham số mà chúng ta đang tối ưu hoá.
Tiếp theo, hãy tạo tệp cấu hình đó cục bộ:
%%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
Đối với mỗi siêu tham số, chúng ta chỉ định loại, phạm vi giá trị mà chúng ta muốn tìm kiếm và tỷ lệ tăng giá trị trên các thử nghiệm khác nhau.
Khi bắt đầu công việc, chúng ta cũng chỉ định chỉ số mà chúng ta đang tối ưu hoá. Lưu ý rằng ở cuối hàm train_model() ở trên, chúng ta báo cáo chỉ số này cho Nền tảng Trí tuệ nhân tạo mỗi khi một thử nghiệm hoàn tất. Ở đây, chúng ta đang giảm thiểu lỗi bình phương trung bình của mô hình, vì vậy, chúng ta muốn sử dụng các siêu tham số dẫn đến lỗi bình phương trung bình thấp nhất cho mô hình. Tên của chỉ số này (val_mse) khớp với tên mà chúng ta sử dụng để báo cáo chỉ số đó khi gọi report_hyperparameter_tuning_metric() ở cuối một thử nghiệm.
6. Chạy công việc huấn luyện trên Nền tảng Trí tuệ nhân tạo
Trong phần này, chúng ta sẽ bắt đầu công việc huấn luyện mô hình bằng tính năng điều chỉnh siêu tham số trên Nền tảng Trí tuệ nhân tạo.
Bước 1: Xác định một số biến môi trường
Trước tiên, hãy xác định một số biến môi trường mà chúng ta sẽ sử dụng để bắt đầu công việc huấn luyện. Nếu bạn muốn chạy công việc ở một khu vực khác, hãy cập nhật biến REGION bên dưới:
MAIN_TRAINER_MODULE = "trainer.model"
TRAIN_DIR = os.getcwd() + '/trainer'
JOB_DIR = BUCKET_URL + '/output'
REGION = "us-central1"
Mỗi công việc huấn luyện trên Nền tảng Trí tuệ nhân tạo phải có một tên riêng biệt. Chạy lệnh sau để xác định một biến cho tên công việc bằng cách sử dụng dấu thời gian:
timestamp = str(datetime.datetime.now().time())
JOB_NAME = 'caip_training_' + str(int(time.time()))
Bước 2: Bắt đầu công việc huấn luyện
Chúng ta sẽ tạo công việc huấn luyện bằng gcloud, Google Cloud CLI. Chúng ta có thể chạy lệnh này trực tiếp trong sổ ghi chú, tham chiếu đến các biến mà chúng ta đã xác định ở trên:
!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
Nếu công việc của bạn được tạo đúng cách, hãy chuyển đến phần Jobs (Công việc) của bảng điều khiển Nền tảng Trí tuệ nhân tạo để theo dõi nhật ký.
Bước 3: Theo dõi công việc
Sau khi bạn vào phần Jobs (Công việc) của bảng điều khiển, hãy nhấp vào công việc mà bạn vừa bắt đầu để xem thông tin chi tiết:

Khi vòng thử nghiệm đầu tiên bắt đầu, bạn sẽ có thể thấy các giá trị siêu tham số được chọn cho mỗi thử nghiệm:

Khi các thử nghiệm hoàn tất, giá trị kết quả của chỉ số tối ưu hoá (trong trường hợp này là val_mse) sẽ được ghi lại tại đây. Công việc sẽ mất 15 – 20 phút để chạy và trang tổng quan sẽ trông giống như sau khi công việc hoàn tất (các giá trị chính xác sẽ khác nhau):

Để gỡ lỗi các vấn đề tiềm ẩn và theo dõi công việc của bạn chi tiết hơn, hãy nhấp vào View Logs (Xem nhật ký) trên trang chi tiết công việc:

Mọi câu lệnh print() trong mã huấn luyện mô hình sẽ xuất hiện tại đây. Nếu bạn gặp vấn đề, hãy thử thêm nhiều câu lệnh in hơn và bắt đầu một công việc huấn luyện mới.
Sau khi công việc huấn luyện hoàn tất, hãy tìm các siêu tham số mang lại val_mse thấp nhất. Bạn có thể sử dụng các siêu tham số này để huấn luyện và xuất phiên bản cuối cùng của mô hình hoặc sử dụng các siêu tham số này làm hướng dẫn để bắt đầu một công việc huấn luyện khác với các thử nghiệm điều chỉnh siêu tham số bổ sung.
7. Dọn dẹp
Nếu bạn muốn tiếp tục sử dụng sổ ghi chú này, thì bạn nên tắt sổ ghi chú khi không sử dụng. Trên giao diện người dùng Notebooks trong Cloud Console (Bảng điều khiển Cloud), hãy chọn sổ ghi chú rồi chọn Stop (Dừng):

Nếu bạn muốn xoá tất cả các tài nguyên mà bạn đã tạo trong bài tập thực hành này, chỉ cần xoá thực thể sổ ghi chú thay vì dừng thực thể đó.
Sử dụng trình đơn Điều hướng trong Cloud Console (Bảng điều khiển Cloud), hãy duyệt đến Storage (Bộ nhớ) rồi xoá cả hai vùng chứa mà bạn đã tạo để lưu trữ tài sản mô hình.