1. Tổng quan
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo và chạy quy trình học máy bằng Quy trình đỉnh.
Kiến thức bạn sẽ học được
Bạn sẽ tìm hiểu cách:
- Sử dụng SDK quy trình Kubeflow để xây dựng quy trình học máy có thể mở rộng
- Tạo và chạy quy trình giới thiệu gồm 3 bước, trong đó có hoạt động nhập văn bản
- Tạo và chạy 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 tạo 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 công việc của quy trình bằng Trình lập lịch biểu trên đám mây
Tổng chi phí để chạy lớp học này trên Google Cloud là khoảng 25 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.
Ngoài các dịch vụ huấn luyện và triển khai mô hình, Vertex AI còn cung cấp nhiều sản phẩm MLOps, bao gồm cả Vertex Pipelines (tâm điểm của lớp học này), Model Monitoring, Feature Store, v.v. Bạn có thể xem tất cả sản phẩm của Vertex AI trong sơ đồ dưới đây.
Nếu bạn có ý kiến phản hồi, vui lòng xem trang hỗ trợ.
Tại sao quy trình học máy lại hữu ích?
Trước khi đi sâu vào tìm hiểu, hãy cùng tìm hiểu lý do bạn nên sử dụng quy trình. Hãy tưởng tượng bạn đang xây dựng một quy trình làm việc về học máy bao gồm việc xử lý dữ liệu, huấn luyện mô hình, điều chỉnh tham số siêu dữ liệu, đá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, điều này có thể trở nên khó xử nếu bạn coi toàn bộ quy trình làm việc là một khối thống nhất. Khi bắt đầu mở rộng quy mô quy trình học máy, bạn nên chia sẻ quy trình làm việc về học máy với những người khác trong nhóm để họ có thể chạy quy trình đó và đóng góp mã. Nếu không có một quy trình đáng tin cậy và có thể tái lập, 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 của bạn 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 quy trình dựa trên các sự kiện khác trong môi trường trên đám mây, chẳng hạn như bắt đầu chạy quy trình khi có dữ liệu huấn luyện mới.
Tóm tắt: quy trình giúp bạn tự động hoá và sản xuất lại quy trình làm việc về máy học.
3. Thiết lập môi trường đám mây
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: Khởi động Cloud Shell
Trong lớp học này, bạn sẽ làm việc trong một phiên Cloud Shell (Lọt vào đám mây). Đây là một trình thông dịch lệnh do máy ảo lưu trữ và chạy trong đám mây của Google. Bạn cũng có thể dễ dàng chạy phần này trên máy tính của riêng mình, nhưng việc sử dụng Cloud Shell sẽ giúp mọi người có thể truy cập vào một 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 lớp học lập trình, bạn có thể thử lại phần này trên máy tính của riêng 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). Dưới đây là giao diện một lần đó:
Quá trình cấp phép và kết nối với Cloud Shell chỉ mất vài phút.
Máy ảo này được tải sẵn tất cả các công cụ phát triển mà bạn cần. Ứng dụng này cung cấp một thư mục gốc 5 GB ổn định và chạy trong Google Cloud, giúp cải thiện đáng kể hiệu suất mạng và xác thực. Bạn có thể thực hiện hầu hết (nếu không phải 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 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ự trong kết quả đầu ra 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
Kết quả của lệnh
[core] project = <PROJECT_ID>
Nếu không, bạn có thể đặt giá trị này bằng lệnh sau:
gcloud config set project <PROJECT_ID>
Kết quả của lệnh
Updated property [core/project].
Cloud Shell có một vài biến môi trường, trong đó có GOOGLE_CLOUD_PROJECT
chứa tên của dự án Cloud hiện tại. Chúng ta sẽ sử dụng hàm này ở nhiều nơi trong lớp học lập trình 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ẽ biết những dịch vụ này cần thiết ở đâu (và vì sao). Tuy nhiên, bây giờ, 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ư sau:
Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.
Bước 3: Tạo một bộ chứa trong Cloud Storage
Để chạy một công việc huấn luyện trên Vertex AI, chúng ta cần có một bộ chứa bộ nhớ để lưu trữ các thành phần mô hình đã lưu. Bộ chứa phải là theo khu vực. Chúng ta đang 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 đó trong suốt lớp học này). Nếu đã có bộ chứa, bạn có thể bỏ qua bước này.
Chạy các lệnh sau trong dòng lệnh 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 cho tài khoản dịch vụ điện toán quyền truy cập vào bộ chứa này. 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 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):
Tại đó, trong phần Sổ tay do người dùng quản lý, hãy nhấp vào Sổ tay mới:
Sau đó, hãy chọn loại thực thể TensorFlow Enterprise 2.3 (có LTS) không có GPU:
Sử dụng các chế độ mặc định rồi nhấp vào Tạo.
Bước 5: Mở Sổ tay
Sau khi tạo thực thể, hãy chọn Mở JupyterLab:
4. Thiết lập Vertex Pipelines
Chúng ta 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ẽ sử dụng để xây dựng quy trình. 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 quy trình Google Cloud: Thư viện này cung cấp các thành phần tạo sẵn giúp bạn dễ dàng tương tác với các dịch vụ 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 thực thể sổ tay.
Để cài đặt cả hai dịch vụ mà chúng ta sẽ sử dụng trong lớp học lập trình này, trước tiên, hãy đặt cờ người dùng trong một ô trong sổ tay:
USER_FLAG = "--user"
Sau đó, hãy chạy mã sau trong sổ tay:
!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 hạt 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 đúng các gói. Phiên bản SDK KFP 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à bộ chứa
Trong suốt lớp học này, bạn sẽ tham chiếu mã dự án trên Google Cloud và bộ chứa mà bạn đã tạo trước đó. Tiếp theo, chúng ta sẽ tạo biến cho từng biến đó.
Nếu không biết mã dự án của mình, bạn có thể lấy mã đó bằng cách chạy đoạn mã sau:
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 đặt giá trị này 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 bộ chứa. Nếu bạn đã tạo trong lớp học này, thì cách sau sẽ hoạt động. Nếu không, bạn cần phải đặt giá trị 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ố
Điều 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 không đổi. 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. Ở đây, chúng ta đang sử dụng us-central1
làm khu vực, nhưng nếu bạn đã sử dụng một khu vực khác khi tạo bộ chứa, hãy cập nhật biến REGION
trong mã dưới đây:
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 mã trên, bạn sẽ thấy thư mục gốc cho quy trình của mình được in ra. Đây là vị trí của 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. Tệp 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 quy trình Vertex, trước tiên, chúng ta sẽ tạo một quy trình ngắn bằng SDK KFP. Quy trình này không làm bất cứ điều gì liên quan đến máy học (đừng lo, chúng tôi sẽ giải quyết vấn đề đó!), chúng tôi 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 SDK KFP
- 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 một câu bằng cách sử dụng hai đầ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 ba 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 dữ liệu đầu vào và trả về chuỗi đó làm dữ liệu đầ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 thư viện biểu tượng cảm xúc để hướng dẫn bạn cách quản lý các phần phụ thuộc bên ngoài trong quy trìnhbuild_sentence
: Thành phần cuối cùng này sẽ sử dụng kết quả của hai thành phần trước đó để tạo một câu sử dụng biểu tượng cảm xúc. Ví dụ: kết quả đầu ra có thể là "Vertex Pipelines is ✨" (Quy trình đỉnh là ✨).
Hãy bắt đầu lập trình!
Bước 1: Tạo thành phần dựa trên hàm Python
Bằng cách sử dụng SDK KFP, chúng ta có thể tạo các thành phần dựa trên hàm Python. Chúng ta sẽ sử dụng lớp này 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ỉ lấy một chuỗi làm dữ liệu đầ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 cùng tìm hiểu kỹ hơn về cú pháp tại đây:
- Trình trang trí
@component
biên dịch hàm này thành một thành phần khi quy trình 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_image
chỉ định hình ảnh vùng chứa mà thành phần này sẽ sử dụng. - Tham số
output_component_file
là 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 thực thể 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 sau:
product_name_component = kfp.components.load_component_from_file('./first-component.yaml')
-> str
sau định nghĩa hàm chỉ định loại đầu ra cho thành phần này.
Bước 2: Tạo thêm 2 thành phần
Để hoàn tất quy trình, chúng ta sẽ tạo thêm hai thành phần. Chuỗi đầu tiên chúng ta sẽ định nghĩa sẽ lấy một chuỗi làm thông tin đầ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ộ dữ liệu với văn bản nhập được truyền và kết quả là biểu tượng cảm xúc:
@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 phân tích các điểm mới:
- Tham số
packages_to_install
cho thành phần biết mọi phần phụ thuộc thư viện bên ngoài cho 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
NamedTuple
có tên làOutputs
. Lưu ý rằng mỗi chuỗi trong bộ dữ liệu này đều có khoá:emoji_text
vàemoji
. Chúng ta sẽ sử dụng các giá trị này trong thành phần tiếp theo để truy cập kết quả.
Thành phần cuối cùng trong quy trình này sẽ sử dụng đầu ra của hai 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)
Bạn có thể thắc mắc: làm cách nào để thành phần này biết sử dụng kết quả 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ả các thành phần này trong bước tiếp theo.
Bước 3: Kết hợp các thành phần vào một quy trình
Các định nghĩa thành phần mà chúng ta đã xác định ở trên đã tạo các hàm nhà máy có thể được sử 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 bạn sẽ ghi các cấu phần phần mềm của quy trình. Cấu phần phần mềm là 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ỳ tệp nào, nhưng quy trình tiếp theo sẽ tạo.
Trong khối mã tiếp theo, chúng ta xác định một hàm intro_pipeline
. Đây là nơi chúng ta chỉ định dữ liệu đầ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_task
nhận tên sản phẩm làm dữ liệu đầu vào. Ở đây, chúng ta đang truyền "Vertex Pipelines" (Quy trình đỉnh) nhưng bạn có thể thay đổi giá trị này thành bất kỳ giá trị nào bạn muốn.emoji_task
lấy mã văn bản của 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 bất kỳ tên nào bạn muốn. Ví dụ: "party_face" đề cập đến 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 dữ liệu đầu vào, nên chúng ta sẽ chỉ định dữ liệu đầu vào cho các thành phần này theo cách thủ công khi xác định quy trình.- Bước cuối cùng trong quy trình của chúng ta –
consumer_task
có 3 tham số đầu vào:- Kết quả 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
. - Kết quả
emoji
của bướcemoji_task
. 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ự,
emoji_text
được đặt tên là đầu ra từ 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 biểu tượng cảm xúc, quy trình này sẽ sử dụng văn bản này để tạo một câu.
- Kết quả 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
Khi đã xác định xong quy trình, bạn có thể biên dịch quy trình đó. Thao tác sau 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 biến TIMESTAMP
. Chúng ta sẽ sử dụng mã này trong mã 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 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 quy trình chạy trong bảng điều khiển:
Chuyển đến đường liên kết đó. Quy trình của bạn sẽ có dạng như sau khi hoàn tất:
Quy trình này sẽ mất 5 đến 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 kết quả cuối cùng:
Giờ đây, khi đã quen thuộc với cách hoạt động của SDK KFP và quy trình Vertex, bạn đã sẵn sàng tạo một quy trình tạo và triển khai mô hình máy học bằng các dịch vụ Vertex AI khác. Hãy cùng tìm hiểu kỹ hơn nhé.
6. Xây dựng quy trình học máy toàn diện
Đã đến lúc xây dựng quy trình học máy đầu tiên. Trong quy trình này, chúng tôi sẽ sử dụng tập dữ liệu về đậu nành khô của UCI Machine Learning, từ: KOKLU, M. và OZKAN, I.A., (2020), "Phân loại đa lớp hạt khô bằng cách sử dụng thị giác máy tính và kỹ thuật học máy." Trong Máy tính và Điện tử trong Nông nghiệp, 174, 105507. DOI.
Đây là một tập dữ liệu dạng bảng và trong quy trình, chúng tôi sẽ sử dụng tập dữ liệu để huấn luyện, đánh giá và triển khai một mô hình AutoML giúp 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á trên mô hình này
- Dựa trên các chỉ số đánh giá, hãy quyết định xem có triển khai mô hình bằng logic có điều kiện trong quy trình Vertex hay không
- Triển khai mô hình cho một điểm cuối bằng công cụ 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 đều sử dụng thành phần 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 tôi đã 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 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 sử 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ị các chỉ số đó trong giao diện người dùng Vertex Pipelines
- So sánh các chỉ số với ngưỡng để xác định xem có nên triển khai mô hình hay không
Trước khi định nghĩa 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 đó. Dưới dạng dữ liệu đầu vào, quy trình này sẽ lấy một số siêu dữ liệu trên dự án trên đám mây, mô hình được 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à 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à phần nằm dưới giá trị đườ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, thì tức là chúng ta chỉ muốn quy trình triển khai mô hình nếu chỉ số này cao 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ó triển khai mô hình hay không. Thêm nội dung sau vào một ô trong 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 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 các thành phần này kết hợp với nhau. Trước tiên, hãy xác định tên hiển thị cho lần 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 ô mới trong sổ tay:
@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 quy trình trước, chúng ta xác định các tham số đầu vào mà quy trình này nhận. Chúng ta cần đặt các giá trị 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 tạo sẵn để tương tác với các dịch vụ Vertex AI:
TabularDatasetCreateOp
tạo một tập dữ liệu dạng bảng trong Vertex AI dựa trên 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 qua URL bảng BigQueryAutoMLTabularTrainingJobRunOp
bắt đầu một công việc huấn luyện AutoML cho một tập dữ liệu dạng bảng. Chúng ta truyền một vài tham số cấu hình cho thành phần này, bao gồm loại mô hình (trong trường hợp này là phân loại), một số dữ liệu trên các cột, khoảng thời gian chúng ta muốn chạy huấn luyện và con trỏ đến tập dữ liệu. 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"]
EndpointCreateOp
tạ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 dữ liệu đầu vào cho thành phần tiếp theoModelDeployOp
triển khai một mô hình nhất định cho 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 đã tạo ở bước trước. Có các tuỳ 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 máy đầu cuối mà chúng tôi muốn triển khai. Chúng ta truyền mô hình bằng cách truy cập kết quả của bước huấn luyện trong quy trình
- Quy trình này cũng sử dụng logic có điều kiện, một tính năng của Quy trình đỉnh cho phép bạn xác định một điều kiện, cùng với nhiều 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ó triển khai mô hình cho một điểm cuối hay không. Để triển khai việc này, chúng ta sẽ sử dụng lớpCondition
trong SDK KFP. Điều kiện chúng ta truyền vào là kết quả 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, 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 mà chúng tôi đã 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
Khi đã xác định đầy đủ 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 công việc:
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 dành cho bước huấn luyện AutoML. Quy trình hoàn chỉnh sẽ có dạng như sau:
Nếu bật/tắt nút "Mở rộng cấu phần phần mềm" ở trên cùng, bạn có thể xem thông tin chi tiết về nhiều cấu phần phần mềm được tạo qua quy trì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 chứa tập dữ liệu đó:
Tương tự, để xem hình ảnh trực quan của các 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ừ lần chạy 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 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.
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 quy trình Vertex để Theo dõi dòng dõi. Theo dõi nối tiếp, chúng tôi muốn nói đến việc theo dõi các cấu phần phần mềm được tạo trong toàn bộ quy trình của bạn. Điều này có thể giúp chúng ta hiểu được vị trí tạo cấu phần phần mềm và cách sử dụng các cấu phần phần mềm đó trong quy trình làm việc của công nghệ học máy. Ví dụ: để xem hoạt động theo dõi nối tiếp 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ữ liệu dòng thừa:
Thông tin này cho chúng tôi biết tất cả các địa điểm 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ố trên các lần chạy quy trình
Nếu chạy quy trình này nhiều lần, bạn nê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 siêu dữ liệu về lượt 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 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 tất phòng thí nghiệm!
🎉 Xin chúc mừng! 🎉
Bạn đã tìm hiểu cách sử dụng Vertex AI để:
- Sử dụng SDK quy trình Kubeflow để tạo quy trình toàn diện 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 đồ Quy trình Vertex trong bảng điều khiển
- Sử dụng các thành phần quy trình tạo sẵn để thêm các dịch vụ Vertex AI vào quy trình
- Lên lịch cho các công việc định kỳ trong 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 được tạo trong suốt lớp học này.
Bước 1: Dừng hoặc xoá thực thể của Sổ tay
Nếu muốn tiếp tục sử dụng sổ tay mà 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. Trên giao diện người dùng của Sổ tay trong 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, 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 của 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 Huỷ triển khai trong lời nhắc sau:
Cuối cùng, hãy chuyển đến phần Mô hình trên bảng điều khiển, tìm mô hình đó rồi nhấp vào 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á bộ chứa Cloud Storage
Để xoá Bộ chứa Storage, hãy sử dụng trình đơn Điều hướng trong Cloud Console, duyệt đến Bộ nhớ, chọn bộ chứa rồi nhấp vào Xoá: