1. Tổng quan
Trong phòng thí nghiệm này, bạn sẽ thực hiện quy trình huấn luyện học máy hoàn chỉnh trên Google Cloud, sử dụng PyTorch để xây dựng mô hình của mì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 để chạy công việc đó trên Nền tảng Trí tuệ nhân tạo Training bằng 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 phiên bản AI Platform Notebooks
- Tạo mô hình PyTorch
- Huấn luyện mô hình bằng cách đ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 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 Cloud AI Platform Models API
Chuyển đến phần Mô hình Nền tảng Trí tuệ nhân tạo của bảng điều khiển Cloud rồi nhấp vào Enable (Bật) nếu bạn chưa bật.

Bước 2: 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ạn sẽ cần thông tin này để tạo phiên bản sổ tay.
Bước 3: Tạo một phiên bản AI Platform Notebooks
Chuyển đến mục AI Platform Notebooks của bảng điều khiển Cloud rồi nhấp vào New Instance (Phiên bản mới). Sau đó, hãy chọn loại phiên bản 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 Tạo. Sau khi tạo phiên bản, hãy chọn Open JupyterLab (Mở JupyterLab):

Tiếp theo, hãy mở một phiên bản Sổ tay Python 3 trong 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ổ tay, hãy thêm các mục nhập sau và chạy ô. Bạn có thể kích hoạt lệnh này bằng cách nhấn nút mũi tên phải trong trình đơn trên cùng hoặc nhấn tổ hợp phím command-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 ở đây. Lý do là chúng ta đang chạy quy trình huấn luyện trên AI Platform Training, chứ không phải từ phiên bản Notebook.
3. Tạo một gói cho công việc huấn luyện
Để chạy quy trình huấn luyện trên Nền tảng Trí tuệ nhân tạo Training, chúng ta sẽ cần mã huấn luyện được đóng gói cục bộ trong phiên bản Notebooks và một vùng lưu trữ Cloud Storage để lưu trữ các thành phần cho quy trình. 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 tài khoản.
Bước 1: Tạo một bộ chứa Cloud Storage cho mô hình của chúng ta
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. Điền các giá trị bên dưới bằng tên dự án trên đám mây của bạn trên Google Cloud và tên của bộ nhớ trên đám mây 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 vùng lưu trữ. Chúng ta sẽ chỉ định vùng lưu trữ này khi bắt đầu công việc huấn luyện.
Chạy lệnh gsutil này trong sổ tay để tạo một nhóm:
!gsutil mb $BUCKET_URL
Bước 2: Tạo các tệp ban đầu cho gói Python
Để chạy một lệnh 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 một gói Python. Thư mục 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 sẽ sử dụng các lệnh %%writefile của iPython để lưu tệp vào phiên bản của mình. Ở đâ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 biết rằng đây là một gói:
!mkdir trainer
!touch trainer/__init__.py
Giờ thì 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
Lớp học này tập trung vào các công cụ để huấn luyện mô hình. Tuy nhiên, hãy xem nhanh tập dữ liệu mà chúng ta sẽ dùng để huấn luyện mô hình nhằm tìm hiểu. 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ề ngày sinh ở Hoa Kỳ trong nhiều thập kỷ. Chúng ta sẽ sử dụng một số cột trong tập dữ liệu để dự đoán cân nặng của trẻ sơ sinh khi chào đời. Tập dữ liệu ban đầu 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 vùng lưu trữ trên đám mây.
Bước 1: Tải tập dữ liệu về tỷ lệ sinh của 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 rồi 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ó gầ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 khi chào đời: độ tuổi của mẹ và bố, số tuần mang 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 giá trị boolean).
5. Xác định quy trình huấn luyện bằng cách điều chỉnh siêu tham số
Chúng ta sẽ ghi 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 đó. Tác vụ huấn luyện của chúng ta sẽ chạy trên AI Platform Training và cũng sẽ sử dụng dịch vụ điều chỉnh siêu tham số của AI Platform để tìm ra các siêu tham số tối ưu cho mô hình của chúng ta bằng cách sử dụng phương pháp tối ưu hoá Bayesian.
Bước 1: Tạo kịch bản đào tạo
Trước tiên, hãy tạo tệp Python bằng tập lệnh huấn luyện của chúng ta. Sau đó, chúng ta sẽ phân tích những gì đang diễn ra trong đó. Khi chạy lệnh %%writefile này, mã mô hình sẽ được ghi 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()
Tác vụ huấn luyện bao gồm 2 hàm, trong đó phần lớn công việc diễn ra.
get_args(): Thao tác 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(): Ở đâ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 Tensor, rồi xác định mô hình của mình. Để tạo mô hình, chúng ta sẽ dùng APInn.Sequentialcủa PyTorch. API này 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))
Xin lưu ý rằng thay vì mã hoá cứng kích thước của lớp ẩn trong mô hình, chúng ta sẽ biến kích thước 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. Chúng ta sẽ nói thêm 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 AI Platform
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 AI trên đám mây. 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 phương pháp tối ưu hoá Bayesian để tìm ra 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 thử nghiệm duy nhất bao gồm một lần chạy huấn luyện mô hình của chúng tôi 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 tôi 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 thành để 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 quy trình đ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à quy mô để tăng giá trị trên nhiều thử nghiệm.
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á. Xin 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 sai số 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 sai số bình phương trung bình thấp nhất cho mô hình của mình. Tên của chỉ số này (val_mse) trùng với tên mà chúng tôi dùng để báo cáo chỉ số đó khi gọi report_hyperparameter_tuning_metric() vào cuối thời gian dùng thử.
6. Chạy một quy trình 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 cách đ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ẽ 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 AI Platform đều 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ủa 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 ngay trong sổ tay của mình, 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 bạn đã tạo công việc đúng cách, hãy chuyển đến mục 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 của bạn
Sau khi bạn chuyển đến 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 bắt đầu vòng thử nghiệm đầu tiên, bạn sẽ có thể xem các giá trị siêu tham số được chọn cho từng thử nghiệm:

Khi các thử nghiệm hoàn tất, giá trị thu được 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 này sẽ mất từ 15 đến 20 phút để chạy và trang tổng quan sẽ có dạ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 đề có thể xảy ra và theo dõi công việc của bạn một cách chi tiết hơn, hãy nhấp vào 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 của bạn sẽ xuất hiện ở đâ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 quy trình huấn luyện mới.
Sau khi quá trình 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 giá trị 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 giá trị này làm hướng dẫn để bắt đầu một quy trình 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 muốn tiếp tục sử dụng sổ tay này, bạn nên tắt sổ tay khi không dùng. Trong giao diện người dùng Notebooks của Cloud Console, hãy chọn sổ tay rồi chọn Dừng:

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