1. Tổng quan
Trong phòng thí nghiệm này, bạn sẽ tìm hiểu cách tạo và chạy quy trình ML bằng Vertex Pipelines.
Kiến thức bạn sẽ học được
Bạn sẽ tìm hiểu cách:
- Sử dụng Kubeflow Pipelines SDK để tạo các quy trình học máy có thể mở rộng
- Tạo và chạy một quy trình giới thiệu gồm 3 bước để nhận dữ liệu đầu vào là văn bản
- Tạo và chạy một quy trình huấn luyện, đánh giá và triển khai mô hình phân loại AutoML
- Sử dụng các thành phần dựng sẵn để tương tác với các dịch vụ Vertex AI, được cung cấp thông qua thư viện
google_cloud_pipeline_components - Lên lịch cho một công việc trong quy trình bằng Cloud Scheduler
Tổng chi phí để chạy bài tập thực hành này trên Google Cloud là khoảng 25 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.
Ngoài các dịch vụ huấn luyện và triển khai mô hình, Vertex AI còn có nhiều sản phẩm MLOps, bao gồm Vertex Pipelines (trọng tâm của phòng thí nghiệm này), Model Monitoring, Feature Store và nhiều sản phẩm khác. Bạn có thể xem tất cả các sản phẩm/dịch vụ của Vertex AI trong sơ đồ bên dưới.

Nếu bạn có ý kiến phản hồi, vui lòng truy cập trang hỗ trợ.
Tại sao quy trình ML lại hữu ích?
Trước khi đi sâu vào vấn đề này, hãy cùng tìm hiểu lý do bạn nên sử dụng một pipeline. Hãy tưởng tượng bạn đang xây dựng một quy trình làm việc ML bao gồm xử lý dữ liệu, huấn luyện mô hình, điều chỉnh siêu tham số, đánh giá và triển khai mô hình. Mỗi bước trong số này có thể có các phần phụ thuộc khác nhau, có thể trở nên khó quản lý nếu bạn coi toàn bộ quy trình làm việc là một khối duy nhất. Khi bắt đầu mở rộng quy trình học máy, bạn có thể muốn chia sẻ quy trình học máy của mình với những người khác trong nhóm để họ có thể kích hoạt quy trình đó và đóng góp mã. Nếu không có quy trình đáng tin cậy và có thể tái tạo, việc này có thể trở nên khó khăn. Với quy trình, mỗi bước trong quy trình học máy đều là một vùng chứa riêng. Điều này cho phép bạn phát triển các bước một cách độc lập và theo dõi dữ liệu đầu vào và đầu ra của từng bước theo cách có thể tái tạo. Bạn cũng có thể lên lịch hoặc kích hoạt các lần chạy pipeline dựa trên những sự kiện khác trong môi trường đám mây của mình, chẳng hạn như bắt đầu một lần chạy pipeline khi có dữ liệu huấn luyện mới.
Tóm tắt: các quy trình giúp bạn tự động hoá và tái tạo quy trình làm việc về học máy.
3. Thiết lập môi trường đám mây
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: Khởi động Cloud Shell
Trong phòng thí nghiệm này, bạn sẽ làm việc trong một phiên Cloud Shell. Đây là một trình thông dịch lệnh do một máy ảo chạy trong đám mây của Google lưu trữ. Bạn có thể dễ dàng chạy phần này trên máy tính của mình, nhưng việc sử dụng Cloud Shell sẽ giúp mọi người có được trải nghiệm có thể tái tạo trong một môi trường nhất quán. Sau khi hoàn thành bài thực hành, bạn có thể thử lại phần này trên máy tính của mình.

Kích hoạt Cloud Shell
Ở trên cùng bên phải của Cloud Console, hãy nhấp vào nút bên dưới để Kích hoạt Cloud Shell:

Nếu chưa từng khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian (dưới màn hình đầu tiên) mô tả về Cloud Shell. Nếu vậy, hãy nhấp vào Tiếp tục (và bạn sẽ không bao giờ thấy màn hình này nữa). Sau đây là giao diện của màn hình xuất hiện một lần:

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc trong lớp học lập trình này chỉ bằng một trình duyệt hoặc Chromebook.
Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án đã được đặt thành mã dự án của bạn.
Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list
Bạn sẽ thấy nội dung tương tự như sau trong kết quả của lệnh:

Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project
Đầu ra của lệnh
[core] project = <PROJECT_ID>
Nếu không, bạn có thể đặt nó bằng lệnh sau:
gcloud config set project <PROJECT_ID>
Đầu ra của lệnh
Updated property [core/project].
Cloud Shell có một số biến môi trường, trong đó có GOOGLE_CLOUD_PROJECT chứa tên của dự án trên đám mây hiện tại. Chúng ta sẽ sử dụng thông tin này ở nhiều nơi trong lớp học này. Bạn có thể xem bằng cách chạy:
echo $GOOGLE_CLOUD_PROJECT
Bước 2: Bật API
Trong các bước sau, bạn sẽ thấy nơi cần đến các dịch vụ này (và lý do), nhưng hiện tại, hãy chạy lệnh này để cấp cho dự án của bạn quyền truy cập vào các dịch vụ Compute Engine, Container Registry và Vertex AI:
gcloud services enable compute.googleapis.com \
containerregistry.googleapis.com \
aiplatform.googleapis.com \
cloudbuild.googleapis.com \
cloudfunctions.googleapis.com
Thao tác này sẽ tạo ra một thông báo thành công tương tự như thông báo sau:
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
Bước 3: Tạo một bộ chứa trên Cloud Storage
Để chạy một quy trình huấn luyện trên Vertex AI, chúng ta cần một vùng lưu trữ để lưu trữ các thành phần mô hình đã lưu. Nhóm này cần phải theo khu vực. Chúng ta sẽ sử dụng us-central ở đây, nhưng bạn có thể sử dụng một khu vực khác (chỉ cần thay thế khu vực này trong toàn bộ phòng thí nghiệm). Nếu đã có một bộ chứa, bạn có thể bỏ qua bước này.
Chạy các lệnh sau trong thiết bị đầu cuối Cloud Shell để tạo một nhóm:
BUCKET_NAME=gs://$GOOGLE_CLOUD_PROJECT-bucket
gsutil mb -l us-central1 $BUCKET_NAME
Tiếp theo, chúng ta sẽ cấp quyền truy cập vào nhóm này cho tài khoản dịch vụ điện toán. Thao tác này sẽ đảm bảo rằng Vertex Pipelines có các quyền cần thiết để ghi tệp vào bộ chứa này. Chạy lệnh sau để thêm quyền này:
gcloud projects describe $GOOGLE_CLOUD_PROJECT > project-info.txt
PROJECT_NUM=$(cat project-info.txt | sed -nre 's:.*projectNumber\: (.*):\1:p')
SVC_ACCOUNT="${PROJECT_NUM//\'/}-compute@developer.gserviceaccount.com"
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT --member serviceAccount:$SVC_ACCOUNT --role roles/storage.objectAdmin
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:

Tại đó, trong phần Notebooks do người dùng quản lý, hãy nhấp vào New Notebook (Sổ tay mới):

Sau đó, hãy chọn loại phiên bản TensorFlow Enterprise 2.3 (có LTS) không có GPU:

Sử dụng các lựa chọn mặc định rồi nhấp vào Tạo.
Bước 5: Mở sổ tay
Sau khi tạo phiên bản, hãy chọn Open JupyterLab (Mở JupyterLab):

4. Thiết lập Vertex Pipelines
Bạn cần cài đặt thêm một số thư viện để sử dụng Vertex Pipelines:
- Kubeflow Pipelines: Đây là SDK mà chúng ta sẽ dùng để tạo pipeline. Vertex Pipelines hỗ trợ chạy các quy trình được tạo bằng cả Kubeflow Pipelines hoặc TFX.
- Thành phần trong quy trình của Google Cloud: Thư viện này cung cấp các thành phần được tạo sẵn để giúp bạn dễ dàng tương tác với các dịch vụ của Vertex AI từ các bước trong quy trình.
Bước 1: Tạo sổ tay Python và cài đặt thư viện
Trước tiên, trong trình đơn Trình chạy của thực thể Sổ tay, hãy tạo một sổ tay bằng cách chọn Python 3:

Bạn có thể truy cập vào trình đơn Trình chạy bằng cách nhấp vào dấu + ở trên cùng bên trái của phiên bản sổ tay.
Để cài đặt cả hai dịch vụ mà chúng ta sẽ sử dụng trong phòng thí nghiệm này, trước tiên, hãy đặt cờ người dùng trong một ô sổ tay:
USER_FLAG = "--user"
Sau đó, hãy chạy lệnh sau trong sổ tay của bạn:
!pip3 install {USER_FLAG} google-cloud-aiplatform==1.7.0 --upgrade
!pip3 install {USER_FLAG} kfp==1.8.9 google-cloud-pipeline-components==0.2.0
Sau khi cài đặt các gói này, bạn cần khởi động lại nhân:
import os
if not os.getenv("IS_TESTING"):
# Automatically restart kernel after installs
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)
Cuối cùng, hãy kiểm tra để đảm bảo bạn đã cài đặt các gói đúng cách. Phiên bản KFP SDK phải từ 1.8 trở lên:
!python3 -c "import kfp; print('KFP SDK version: {}'.format(kfp.__version__))"
!python3 -c "import google_cloud_pipeline_components; print('google_cloud_pipeline_components version: {}'.format(google_cloud_pipeline_components.__version__))"
Bước 2: Đặt mã dự án và nhóm
Trong suốt bài thực hành này, bạn sẽ tham chiếu đến mã dự án trên đám mây và bộ chứa mà bạn đã tạo trước đó. Tiếp theo, chúng ta sẽ tạo các biến cho từng biến đó.
Nếu không biết mã dự án, bạn có thể chạy lệnh sau để lấy mã dự án:
import os
PROJECT_ID = ""
# Get your Google Cloud project ID from gcloud
if not os.getenv("IS_TESTING"):
shell_output=!gcloud config list --format 'value(core.project)' 2>/dev/null
PROJECT_ID = shell_output[0]
print("Project ID: ", PROJECT_ID)
Nếu không, hãy thiết lập tại đây:
if PROJECT_ID == "" or PROJECT_ID is None:
PROJECT_ID = "your-project-id" # @param {type:"string"}
Sau đó, hãy tạo một biến để lưu trữ tên nhóm của bạn. Nếu bạn đã tạo nó trong lớp học này, thì những bước sau sẽ có hiệu quả. Nếu không, bạn sẽ phải đặt thông số này theo cách thủ công:
BUCKET_NAME="gs://" + PROJECT_ID + "-bucket"
Bước 3: Nhập thư viện
Thêm nội dung sau để nhập các thư viện mà chúng ta sẽ sử dụng trong suốt lớp học lập trình này:
import kfp
from kfp.v2 import compiler, dsl
from kfp.v2.dsl import component, pipeline, Artifact, ClassificationMetrics, Input, Output, Model, Metrics
from google.cloud import aiplatform
from google_cloud_pipeline_components import aiplatform as gcc_aip
from typing import NamedTuple
Bước 4: Xác định hằng số
Việc cuối cùng chúng ta cần làm trước khi xây dựng quy trình là xác định một số biến hằng số. PIPELINE_ROOT là đường dẫn Cloud Storage nơi các cấu phần phần mềm do quy trình của chúng ta tạo ra sẽ được ghi. Chúng ta đang sử dụng us-central1 làm khu vực ở đây, nhưng nếu bạn sử dụng một khu vực khác khi tạo vùng chứa, hãy cập nhật biến REGION trong mã bên dưới:
PATH=%env PATH
%env PATH={PATH}:/home/jupyter/.local/bin
REGION="us-central1"
PIPELINE_ROOT = f"{BUCKET_NAME}/pipeline_root/"
PIPELINE_ROOT
Sau khi chạy đoạn mã ở trên, bạn sẽ thấy thư mục gốc cho quy trình được in. Đây là vị trí trong Cloud Storage nơi các cấu phần phần mềm trong quy trình của bạn sẽ được ghi. Mã này sẽ có định dạng gs://YOUR-BUCKET-NAME/pipeline_root/
5. Tạo quy trình đầu tiên
Để làm quen với cách hoạt động của Vertex Pipelines, trước tiên, chúng ta sẽ tạo một quy trình ngắn bằng KFP SDK. Quy trình này không liên quan đến bất kỳ hoạt động nào về học máy (đừng lo lắng, chúng ta sẽ tìm hiểu về hoạt động này!), chúng ta sẽ sử dụng quy trình này để hướng dẫn bạn:
- Cách tạo thành phần tuỳ chỉnh trong KFP SDK
- Cách chạy và theo dõi quy trình trong Vertex Pipelines
Chúng ta sẽ tạo một quy trình in ra một câu bằng cách sử dụng 2 đầu ra: tên sản phẩm và nội dung mô tả bằng biểu tượng cảm xúc. Quy trình này sẽ bao gồm 3 thành phần:
product_name: Thành phần này sẽ lấy tên sản phẩm (hoặc bất kỳ danh từ nào bạn muốn) làm đầu vào và trả về chuỗi đó làm đầu raemoji: Thành phần này sẽ lấy nội dung mô tả bằng văn bản của một biểu tượng cảm xúc và chuyển đổi thành biểu tượng cảm xúc. Ví dụ: mã văn bản cho ✨ là "sparkles". Thành phần này sử dụng một thư viện biểu tượng cảm xúc để cho bạn biết cách quản lý các phần phụ thuộc bên ngoài trong quy trình của bạnbuild_sentence: Thành phần cuối cùng này sẽ sử dụng đầu ra của 2 thành phần trước đó để tạo một câu có sử dụng biểu tượng cảm xúc. Ví dụ: kết quả đầu ra có thể là "Vertex Pipelines is ✨".
Hãy bắt đầu lập trình!
Bước 1: Tạo một thành phần dựa trên hàm Python
Bằng cách sử dụng KFP SDK, chúng ta có thể tạo các thành phần dựa trên các hàm Python. Chúng ta sẽ dùng thành phần đó cho 3 thành phần trong quy trình đầu tiên. Trước tiên, chúng ta sẽ tạo thành phần product_name. Thành phần này chỉ cần lấy một chuỗi làm đầu vào và trả về chuỗi đó. Thêm nội dung sau vào sổ tay:
@component(base_image="python:3.9", output_component_file="first-component.yaml")
def product_name(text: str) -> str:
return text
Hãy xem xét kỹ hơn cú pháp tại đây:
- Trình trang trí
@componentbiên dịch hàm này thành một thành phần khi quy trình được chạy. Bạn sẽ sử dụng phương thức này bất cứ khi nào viết một thành phần tuỳ chỉnh. - Tham số
base_imagechỉ định hình ảnh vùng chứa mà thành phần này sẽ sử dụng. - Tham số
output_component_filelà không bắt buộc và chỉ định tệp yaml để ghi thành phần đã biên dịch vào. Sau khi chạy ô, bạn sẽ thấy tệp được ghi vào phiên bản sổ tay của mình. Nếu muốn chia sẻ thành phần này với người khác, bạn có thể gửi cho họ tệp yaml đã tạo và yêu cầu họ tải tệp đó bằng cách sử dụng lệnh sau:
product_name_component = kfp.components.load_component_from_file('./first-component.yaml')
-> strsau định nghĩa hàm chỉ định loại đầu ra cho thành phần này.
Bước 2: Tạo 2 thành phần bổ sung
Để hoàn tất quy trình, chúng ta sẽ tạo thêm 2 thành phần nữa. Hàm đầu tiên mà chúng ta sẽ xác định lấy một chuỗi làm đầu vào và chuyển đổi chuỗi này thành biểu tượng cảm xúc tương ứng (nếu có). Hàm này trả về một bộ gồm văn bản đầu vào đã truyền và biểu tượng cảm xúc kết quả:
@component(packages_to_install=["emoji"])
def emoji(
text: str,
) -> NamedTuple(
"Outputs",
[
("emoji_text", str), # Return parameters
("emoji", str),
],
):
import emoji
emoji_text = text
emoji_str = emoji.emojize(':' + emoji_text + ':', language='alias')
print("output one: {}; output_two: {}".format(emoji_text, emoji_str))
return (emoji_text, emoji_str)
Thành phần này phức tạp hơn một chút so với thành phần trước đó. Hãy cùng tìm hiểu những điểm mới:
- Tham số
packages_to_installcho biết mọi phần phụ thuộc thư viện bên ngoài của thành phần đối với vùng chứa này. Trong trường hợp này, chúng ta sẽ sử dụng một thư viện có tên là emoji. - Thành phần này trả về một
NamedTuplecó tên làOutputs. Xin lưu ý rằng mỗi chuỗi trong bộ dữ liệu này đều có các khoá:emoji_textvàemoji. Chúng ta sẽ dùng các thành phần này trong thành phần tiếp theo để truy cập vào đầu ra.
Thành phần cuối cùng trong quy trình này sẽ sử dụng đầu ra của 2 thành phần đầu tiên và kết hợp chúng để trả về một chuỗi:
@component
def build_sentence(
product: str,
emoji: str,
emojitext: str
) -> str:
print("We completed the pipeline, hooray!")
end_str = product + " is "
if len(emoji) > 0:
end_str += emoji
else:
end_str += emojitext
return(end_str)
Có thể bạn đang thắc mắc: làm cách nào để thành phần này biết cách sử dụng đầu ra từ các bước trước mà bạn đã xác định? Đây là một câu hỏi hay! Chúng ta sẽ kết hợp tất cả những điều này trong bước tiếp theo.
Bước 3: Kết hợp các thành phần thành một quy trình
Các định nghĩa thành phần mà chúng ta đã xác định ở trên sẽ tạo ra các hàm của nhà máy có thể được dùng trong định nghĩa quy trình để tạo các bước. Để thiết lập một quy trình, hãy sử dụng trình trang trí @pipeline, đặt tên và nội dung mô tả cho quy trình, đồng thời cung cấp đường dẫn gốc nơi các cấu phần phần mềm của quy trình sẽ được ghi. Bằng hiện vật, chúng tôi muốn nói đến mọi tệp đầu ra do quy trình của bạn tạo ra. Quy trình giới thiệu này không tạo ra bất kỳ quy trình nào, nhưng quy trình tiếp theo của chúng tôi sẽ tạo ra.
Trong khối mã tiếp theo, chúng ta sẽ xác định một hàm intro_pipeline. Đây là nơi chúng ta chỉ định các đầu vào cho các bước ban đầu của quy trình và cách các bước kết nối với nhau:
product_tasklấy tên sản phẩm làm dữ liệu đầu vào. Ở đây, chúng ta đang truyền "Vertex Pipelines" nhưng bạn có thể thay đổi thành bất cứ thứ gì bạn muốn.emoji_tasklấy mã văn bản của một biểu tượng cảm xúc làm dữ liệu đầu vào. Bạn cũng có thể thay đổi tên này thành tên bạn muốn. Ví dụ: "party_face" là tên gọi của biểu tượng cảm xúc 🥳. Xin lưu ý rằng vì cả thành phần này và thành phầnproduct_taskđều không có bước nào cung cấp thông tin đầu vào cho chúng, nên chúng ta sẽ chỉ định thông tin đầu vào cho các thành phần này theo cách thủ công khi xác định pipeline.- Bước cuối cùng trong quy trình của chúng ta –
consumer_taskcó 3 tham số đầu vào:- Đầu ra của
product_task. Vì bước này chỉ tạo ra một đầu ra, nên chúng ta có thể tham chiếu đầu ra đó thông quaproduct_task.output. - Đầu ra
emojicủa bướcemoji_task. Hãy xem thành phầnemojiđược xác định ở trên, nơi chúng ta đặt tên cho các tham số đầu ra. - Tương tự, đầu ra có tên
emoji_texttừ thành phầnemoji. Trong trường hợp quy trình của chúng ta được truyền văn bản không tương ứng với một biểu tượng cảm xúc, quy trình này sẽ sử dụng văn bản đó để tạo một câu.
- Đầu ra của
@pipeline(
name="hello-world",
description="An intro pipeline",
pipeline_root=PIPELINE_ROOT,
)
# You can change the `text` and `emoji_str` parameters here to update the pipeline output
def intro_pipeline(text: str = "Vertex Pipelines", emoji_str: str = "sparkles"):
product_task = product_name(text)
emoji_task = emoji(emoji_str)
consumer_task = build_sentence(
product_task.output,
emoji_task.outputs["emoji"],
emoji_task.outputs["emoji_text"],
)
Bước 4: Biên dịch và chạy quy trình
Sau khi xác định xong quy trình, bạn đã sẵn sàng biên dịch quy trình đó. Thao tác này sẽ tạo một tệp JSON mà bạn sẽ dùng để chạy quy trình:
compiler.Compiler().compile(
pipeline_func=intro_pipeline, package_path="intro_pipeline_job.json"
)
Tiếp theo, hãy tạo một biến TIMESTAMP. Chúng ta sẽ sử dụng mã này trong mã nhận dạng công việc:
from datetime import datetime
TIMESTAMP = datetime.now().strftime("%Y%m%d%H%M%S")
Sau đó, hãy xác định công việc trong quy trình của bạn:
job = aiplatform.PipelineJob(
display_name="hello-world-pipeline",
template_path="intro_pipeline_job.json",
job_id="hello-world-pipeline-{0}".format(TIMESTAMP),
enable_caching=True
)
Cuối cùng, hãy chạy công việc để tạo một lần thực thi quy trình mới:
job.submit()
Sau khi chạy ô này, bạn sẽ thấy nhật ký có đường liên kết để xem quá trình chạy quy trình trong bảng điều khiển:

Truy cập vào đường liên kết đó. Sau khi hoàn tất, quy trình của bạn sẽ có dạng như sau:

Quy trình này sẽ mất 5-6 phút để chạy. Khi hoàn tất, bạn có thể nhấp vào thành phần build-sentence để xem đầu ra cuối cùng:

Giờ đây, bạn đã quen với cách hoạt động của KFP SDK và Vertex Pipelines, bạn đã sẵn sàng xây dựng một quy trình tạo và triển khai mô hình học máy bằng các dịch vụ khác của Vertex AI. Hãy cùng tìm hiểu nhé!
6. Tạo một quy trình học máy toàn diện
Đã đến lúc bạn xây dựng quy trình học máy đầu tiên. Trong quy trình này, chúng ta sẽ sử dụng tập dữ liệu Đậu khô của UCI Machine Learning, từ: KOKLU, M. và OZKAN, I.A., (2020), "Phân loại nhiều lớp các loại đậu khô bằng kỹ thuật thị giác máy tính và học máy". Trong Computers and Electronics in Agriculture, 174, 105507. DOI.
Đây là một tập dữ liệu dạng bảng và trong quy trình của mình, chúng ta sẽ dùng tập dữ liệu này để huấn luyện, đánh giá và triển khai một mô hình AutoML phân loại các loại đậu thành một trong 7 loại dựa trên đặc điểm của chúng.
Quy trình này sẽ:
- Tạo Tập dữ liệu trong
- Huấn luyện mô hình phân loại dạng bảng bằng AutoML
- Nhận các chỉ số đánh giá về mô hình này
- Dựa trên các chỉ số đánh giá, hãy quyết định xem có nên triển khai mô hình bằng cách sử dụng logic có điều kiện trong Vertex Pipelines hay không
- Triển khai mô hình đến một điểm cuối bằng cách sử dụng Vertex Prediction
Mỗi bước được nêu sẽ là một thành phần. Hầu hết các bước trong quy trình sẽ sử dụng các thành phần được tạo sẵn cho các dịch vụ Vertex AI thông qua thư viện google_cloud_pipeline_components mà chúng ta đã nhập trước đó trong lớp học lập trình này. Trong phần này, trước tiên, chúng ta sẽ xác định một thành phần tuỳ chỉnh. Sau đó, chúng ta sẽ xác định các bước còn lại của quy trình bằng cách sử dụng các thành phần được tạo sẵn. Các thành phần được tạo sẵn giúp bạn dễ dàng truy cập vào các dịch vụ của Vertex AI, chẳng hạn như huấn luyện và triển khai mô hình.
Bước 1: Thành phần tuỳ chỉnh để đánh giá mô hình
Thành phần tuỳ chỉnh mà chúng ta sẽ xác định sẽ được dùng vào cuối quy trình sau khi quá trình huấn luyện mô hình hoàn tất. Thành phần này sẽ thực hiện một số việc:
- Nhận các chỉ số đánh giá từ mô hình phân loại AutoML đã được huấn luyện
- Phân tích cú pháp các chỉ số và hiển thị chúng trong giao diện người dùng Vertex Pipelines
- So sánh các chỉ số với một ngưỡng để xác định xem có nên triển khai mô hình hay không
Trước khi xác định thành phần, hãy tìm hiểu các tham số đầu vào và đầu ra của thành phần đó. Là thông tin đầu vào, pipeline này lấy một số siêu dữ liệu về dự án trên đám mây của chúng tôi, mô hình đã huấn luyện thu được (chúng ta sẽ xác định thành phần này sau), các chỉ số đánh giá của mô hình và một thresholds_dict_str. thresholds_dict_str là một giá trị mà chúng ta sẽ xác định khi chạy quy trình. Trong trường hợp mô hình phân loại này, đây sẽ là giá trị diện tích dưới đường cong ROC mà chúng ta nên triển khai mô hình. Ví dụ: nếu chúng ta truyền vào 0, 95, tức là chúng ta chỉ muốn quy trình của mình triển khai mô hình nếu chỉ số này lớn hơn 95%.
Thành phần đánh giá của chúng tôi trả về một chuỗi cho biết có nên triển khai mô hình hay không. Thêm nội dung sau vào một ô sổ tay để tạo thành phần tuỳ chỉnh này:
@component(
base_image="gcr.io/deeplearning-platform-release/tf2-cpu.2-3:latest",
output_component_file="tabular_eval_component.yaml",
packages_to_install=["google-cloud-aiplatform"],
)
def classification_model_eval_metrics(
project: str,
location: str, # "us-central1",
api_endpoint: str, # "us-central1-aiplatform.googleapis.com",
thresholds_dict_str: str,
model: Input[Artifact],
metrics: Output[Metrics],
metricsc: Output[ClassificationMetrics],
) -> NamedTuple("Outputs", [("dep_decision", str)]): # Return parameter.
import json
import logging
from google.cloud import aiplatform as aip
# Fetch model eval info
def get_eval_info(client, model_name):
from google.protobuf.json_format import MessageToDict
response = client.list_model_evaluations(parent=model_name)
metrics_list = []
metrics_string_list = []
for evaluation in response:
print("model_evaluation")
print(" name:", evaluation.name)
print(" metrics_schema_uri:", evaluation.metrics_schema_uri)
metrics = MessageToDict(evaluation._pb.metrics)
for metric in metrics.keys():
logging.info("metric: %s, value: %s", metric, metrics[metric])
metrics_str = json.dumps(metrics)
metrics_list.append(metrics)
metrics_string_list.append(metrics_str)
return (
evaluation.name,
metrics_list,
metrics_string_list,
)
# Use the given metrics threshold(s) to determine whether the model is
# accurate enough to deploy.
def classification_thresholds_check(metrics_dict, thresholds_dict):
for k, v in thresholds_dict.items():
logging.info("k {}, v {}".format(k, v))
if k in ["auRoc", "auPrc"]: # higher is better
if metrics_dict[k] < v: # if under threshold, don't deploy
logging.info("{} < {}; returning False".format(metrics_dict[k], v))
return False
logging.info("threshold checks passed.")
return True
def log_metrics(metrics_list, metricsc):
test_confusion_matrix = metrics_list[0]["confusionMatrix"]
logging.info("rows: %s", test_confusion_matrix["rows"])
# log the ROC curve
fpr = []
tpr = []
thresholds = []
for item in metrics_list[0]["confidenceMetrics"]:
fpr.append(item.get("falsePositiveRate", 0.0))
tpr.append(item.get("recall", 0.0))
thresholds.append(item.get("confidenceThreshold", 0.0))
print(f"fpr: {fpr}")
print(f"tpr: {tpr}")
print(f"thresholds: {thresholds}")
metricsc.log_roc_curve(fpr, tpr, thresholds)
# log the confusion matrix
annotations = []
for item in test_confusion_matrix["annotationSpecs"]:
annotations.append(item["displayName"])
logging.info("confusion matrix annotations: %s", annotations)
metricsc.log_confusion_matrix(
annotations,
test_confusion_matrix["rows"],
)
# log textual metrics info as well
for metric in metrics_list[0].keys():
if metric != "confidenceMetrics":
val_string = json.dumps(metrics_list[0][metric])
metrics.log_metric(metric, val_string)
# metrics.metadata["model_type"] = "AutoML Tabular classification"
logging.getLogger().setLevel(logging.INFO)
aip.init(project=project)
# extract the model resource name from the input Model Artifact
model_resource_path = model.metadata["resourceName"]
logging.info("model path: %s", model_resource_path)
client_options = {"api_endpoint": api_endpoint}
# Initialize client that will be used to create and send requests.
client = aip.gapic.ModelServiceClient(client_options=client_options)
eval_name, metrics_list, metrics_str_list = get_eval_info(
client, model_resource_path
)
logging.info("got evaluation name: %s", eval_name)
logging.info("got metrics list: %s", metrics_list)
log_metrics(metrics_list, metricsc)
thresholds_dict = json.loads(thresholds_dict_str)
deploy = classification_thresholds_check(metrics_list[0], thresholds_dict)
if deploy:
dep_decision = "true"
else:
dep_decision = "false"
logging.info("deployment decision is %s", dep_decision)
return (dep_decision,)
Bước 2: Thêm các thành phần được tạo sẵn của Google Cloud
Trong bước này, chúng ta sẽ xác định các thành phần còn lại của quy trình và xem cách chúng kết hợp với nhau. Trước tiên, hãy xác định tên hiển thị cho lượt chạy quy trình bằng dấu thời gian:
import time
DISPLAY_NAME = 'automl-beans{}'.format(str(int(time.time())))
print(DISPLAY_NAME)
Sau đó, hãy sao chép nội dung sau vào một ô sổ tay mới:
@pipeline(name="automl-tab-beans-training-v2",
pipeline_root=PIPELINE_ROOT)
def pipeline(
bq_source: str = "bq://aju-dev-demos.beans.beans1",
display_name: str = DISPLAY_NAME,
project: str = PROJECT_ID,
gcp_region: str = "us-central1",
api_endpoint: str = "us-central1-aiplatform.googleapis.com",
thresholds_dict_str: str = '{"auRoc": 0.95}',
):
dataset_create_op = gcc_aip.TabularDatasetCreateOp(
project=project, display_name=display_name, bq_source=bq_source
)
training_op = gcc_aip.AutoMLTabularTrainingJobRunOp(
project=project,
display_name=display_name,
optimization_prediction_type="classification",
budget_milli_node_hours=1000,
column_transformations=[
{"numeric": {"column_name": "Area"}},
{"numeric": {"column_name": "Perimeter"}},
{"numeric": {"column_name": "MajorAxisLength"}},
{"numeric": {"column_name": "MinorAxisLength"}},
{"numeric": {"column_name": "AspectRation"}},
{"numeric": {"column_name": "Eccentricity"}},
{"numeric": {"column_name": "ConvexArea"}},
{"numeric": {"column_name": "EquivDiameter"}},
{"numeric": {"column_name": "Extent"}},
{"numeric": {"column_name": "Solidity"}},
{"numeric": {"column_name": "roundness"}},
{"numeric": {"column_name": "Compactness"}},
{"numeric": {"column_name": "ShapeFactor1"}},
{"numeric": {"column_name": "ShapeFactor2"}},
{"numeric": {"column_name": "ShapeFactor3"}},
{"numeric": {"column_name": "ShapeFactor4"}},
{"categorical": {"column_name": "Class"}},
],
dataset=dataset_create_op.outputs["dataset"],
target_column="Class",
)
model_eval_task = classification_model_eval_metrics(
project,
gcp_region,
api_endpoint,
thresholds_dict_str,
training_op.outputs["model"],
)
with dsl.Condition(
model_eval_task.outputs["dep_decision"] == "true",
name="deploy_decision",
):
endpoint_op = gcc_aip.EndpointCreateOp(
project=project,
location=gcp_region,
display_name="train-automl-beans",
)
gcc_aip.ModelDeployOp(
model=training_op.outputs["model"],
endpoint=endpoint_op.outputs["endpoint"],
dedicated_resources_min_replica_count=1,
dedicated_resources_max_replica_count=1,
dedicated_resources_machine_type="n1-standard-4",
)
Hãy xem điều gì đang xảy ra trong đoạn mã này:
- Trước tiên, giống như trong pipeline trước đây, chúng ta xác định các tham số đầu vào mà pipeline này sẽ lấy. Chúng ta cần đặt các thông số này theo cách thủ công vì chúng không phụ thuộc vào kết quả của các bước khác trong quy trình.
- Phần còn lại của quy trình sử dụng một số thành phần dựng sẵn để tương tác với các dịch vụ Vertex AI:
TabularDatasetCreateOptạo một tập dữ liệu dạng bảng trong Vertex AI dựa trên một nguồn tập dữ liệu trong Cloud Storage hoặc BigQuery. Trong quy trình này, chúng ta sẽ truyền dữ liệu thông qua một URL bảng BigQueryAutoMLTabularTrainingJobRunOpkhởi động một quy trình huấn luyện AutoML cho một tập dữ liệu dạng bảng. Chúng ta sẽ truyền một số thông số cấu hình cho thành phần này, bao gồm cả loại mô hình (trong trường hợp này là phân loại), một số dữ liệu về các cột, thời gian chúng ta muốn chạy quá trình huấn luyện và một con trỏ đến tập dữ liệu. Xin lưu ý rằng để truyền tập dữ liệu vào thành phần này, chúng ta sẽ cung cấp đầu ra của thành phần trước đó thông quadataset_create_op.outputs["dataset"]EndpointCreateOptạo một điểm cuối trong Vertex AI. Điểm cuối được tạo từ bước này sẽ được truyền dưới dạng thông tin đầu vào cho thành phần tiếp theoModelDeployOptriển khai một mô hình nhất định đến một điểm cuối trong Vertex AI. Trong trường hợp này, chúng ta sẽ sử dụng điểm cuối được tạo ở bước trước. Có các lựa chọn cấu hình bổ sung, nhưng ở đây, chúng tôi sẽ cung cấp loại máy và mô hình của điểm cuối mà chúng tôi muốn triển khai. Chúng ta sẽ truyền mô hình bằng cách truy cập vào đầu ra của bước huấn luyện trong quy trình
- Pipeline này cũng sử dụng logic có điều kiện, một tính năng của Vertex Pipelines cho phép bạn xác định một điều kiện, cùng với các nhánh khác nhau dựa trên kết quả của điều kiện đó. Hãy nhớ rằng khi xác định quy trình, chúng ta đã truyền một tham số
thresholds_dict_str. Đây là ngưỡng độ chính xác mà chúng tôi đang sử dụng để xác định xem có nên triển khai mô hình của mình đến một điểm cuối hay không. Để triển khai việc này, chúng ta sẽ sử dụng lớpConditiontrong KFP SDK. Điều kiện mà chúng ta truyền vào là đầu ra của thành phần eval tuỳ chỉnh mà chúng ta đã xác định trước đó trong lớp học lập trình này. Nếu điều kiện này là đúng, thì quy trình sẽ tiếp tục thực thi thành phầndeploy_op. Nếu độ chính xác không đáp ứng ngưỡng được xác định trước, quy trình sẽ dừng tại đây và không triển khai mô hình.
Bước 3: Biên dịch và chạy quy trình học máy toàn diện
Sau khi xác định toàn bộ quy trình, đã đến lúc biên dịch quy trình đó:
compiler.Compiler().compile(
pipeline_func=pipeline, package_path="tab_classif_pipeline.json"
)
Tiếp theo, hãy xác định công việc:
ml_pipeline_job = aiplatform.PipelineJob(
display_name="automl-tab-beans-training",
template_path="tab_classif_pipeline.json",
pipeline_root=PIPELINE_ROOT,
parameter_values={"project": PROJECT_ID, "display_name": DISPLAY_NAME},
enable_caching=True
)
Và cuối cùng, hãy chạy lệnh:
ml_pipeline_job.submit()
Chuyển đến đường liên kết xuất hiện trong nhật ký sau khi chạy ô ở trên để xem quy trình của bạn trong bảng điều khiển. Quy trình này sẽ mất hơn một giờ để chạy. Hầu hết thời gian đều được dành cho bước huấn luyện AutoML. Đường dẫn hoàn chỉnh sẽ có dạng như sau:

Nếu bật nút "Mở rộng cấu phần phần mềm" ở trên cùng, bạn sẽ có thể xem thông tin chi tiết về các cấu phần phần mềm được tạo từ quy trình của mình. Ví dụ: nếu nhấp vào cấu phần phần mềm dataset, bạn sẽ thấy thông tin chi tiết về tập dữ liệu Vertex AI đã được tạo. Bạn có thể nhấp vào đường liên kết tại đây để chuyển đến trang của tập dữ liệu đó:

Tương tự, để xem các hình ảnh trực quan về chỉ số thu được từ thành phần đánh giá tuỳ chỉnh, hãy nhấp vào cấu phần phần mềm có tên là metricsc. Ở bên phải trang tổng quan, bạn sẽ thấy ma trận nhầm lẫn cho mô hình này:

Để xem mô hình và điểm cuối được tạo từ quy trình này, hãy chuyển đến phần mô hình rồi nhấp vào mô hình có tên automl-beans. Tại đó, bạn sẽ thấy mô hình này được triển khai đến một điểm cuối:

Bạn cũng có thể truy cập vào trang này bằng cách nhấp vào cấu phần phần mềm điểm cuối trong biểu đồ quy trình của mình.
Ngoài việc xem biểu đồ quy trình trong bảng điều khiển, bạn cũng có thể sử dụng Vertex Pipelines để Theo dõi nguồn gốc. Theo dõi dòng dữ liệu có nghĩa là theo dõi các cấu phần phần mềm được tạo trong suốt quy trình của bạn. Điều này có thể giúp chúng ta hiểu được nơi tạo ra các cấu phần phần mềm và cách chúng được sử dụng trong quy trình làm việc của học máy. Ví dụ: để xem tính năng theo dõi dòng dữ liệu cho tập dữ liệu được tạo trong quy trình này, hãy nhấp vào cấu phần phần mềm tập dữ liệu rồi nhấp vào Xem dòng dữ liệu:

Điều này cho thấy tất cả những nơi mà cấu phần phần mềm này đang được sử dụng:

Bước 4: So sánh các chỉ số giữa các lần chạy quy trình
Nếu chạy quy trình này nhiều lần, bạn có thể muốn so sánh các chỉ số giữa các lần chạy. Bạn có thể sử dụng phương thức aiplatform.get_pipeline_df() để truy cập vào siêu dữ liệu chạy. Ở đây, chúng ta sẽ lấy siêu dữ liệu cho tất cả các lần chạy của quy trình này và tải siêu dữ liệu đó vào một Pandas DataFrame:
pipeline_df = aiplatform.get_pipeline_df(pipeline="automl-tab-beans-training-v2")
small_pipeline_df = pipeline_df.head(2)
small_pipeline_df
Vậy là bạn đã hoàn thành lớp học lập trình này!
🎉 Xin chúc mừng! 🎉
Bạn đã tìm hiểu cách sử dụng Vertex AI để:
- Sử dụng Kubeflow Pipelines SDK để tạo các quy trình từ đầu đến cuối bằng các thành phần tuỳ chỉnh
- Chạy quy trình trên Vertex Pipelines và bắt đầu chạy quy trình bằng SDK
- Xem và phân tích biểu đồ Vertex Pipelines trong bảng điều khiển
- Sử dụng các thành phần quy trình được tạo sẵn để thêm các dịch vụ Vertex AI vào quy trình của bạn
- Lên lịch cho các lệnh lặp lại của quy trình
Để tìm hiểu thêm về các phần khác nhau của Vertex, hãy xem tài liệu.
7. Dọn dẹp
Để không bị tính phí, bạn nên xoá các tài nguyên đã tạo trong suốt quá trình thực hành này.
Bước 1: Dừng hoặc xoá phiên bản Notebooks
Nếu muốn tiếp tục sử dụng sổ tay bạn đã tạo trong phòng thí nghiệm này, bạn nên tắt sổ tay khi không sử dụng. Trong giao diện người dùng Notebook trên Cloud Console, hãy chọn sổ tay rồi chọn Dừng. Nếu bạn muốn xoá hoàn toàn phiên bản này, hãy chọn Xoá:

Bước 2: Xoá điểm cuối
Để xoá điểm cuối mà bạn đã triển khai, hãy chuyển đến phần Điểm cuối trong bảng điều khiển Vertex AI rồi nhấp vào biểu tượng xoá:

Sau đó, hãy nhấp vào Undeploy (Huỷ triển khai) trong lời nhắc sau:

Cuối cùng, hãy chuyển đến mục Models (Mô hình) trên bảng điều khiển, tìm mô hình đó rồi nhấp vào Delete model (Xoá mô hình) trong trình đơn có biểu tượng ba dấu chấm ở bên phải:

Bước 3: Xoá nhóm Cloud Storage
Để 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á:
