معرفی خطوط لوله Vertex

1. بررسی اجمالی

در این آزمایشگاه، نحوه ایجاد و اجرای خطوط لوله ML با Vertex Pipelines را خواهید آموخت.

چیزی که یاد می گیرید

شما یاد خواهید گرفت که چگونه:

  • از Kubeflow Pipelines SDK برای ساخت خطوط لوله ML مقیاس پذیر استفاده کنید
  • یک خط لوله مقدماتی 3 مرحله ای ایجاد و اجرا کنید که ورودی متن را می گیرد
  • خط لوله ای ایجاد و اجرا کنید که یک مدل طبقه بندی AutoML را آموزش می دهد، ارزیابی می کند و به کار می گیرد
  • از اجزای از پیش ساخته شده برای تعامل با خدمات Vertex AI استفاده کنید که از طریق کتابخانه google_cloud_pipeline_components ارائه شده است.
  • یک کار خط لوله را با Cloud Scheduler برنامه ریزی کنید

کل هزینه اجرای این آزمایشگاه در Google Cloud حدود 25 دلار است.

2. مقدمه ای بر Vertex AI

این آزمایشگاه از جدیدترین محصول هوش مصنوعی موجود در Google Cloud استفاده می کند. Vertex AI پیشنهادات ML را در سراسر Google Cloud در یک تجربه توسعه یکپارچه ادغام می کند. پیش از این، مدل‌های آموزش دیده با AutoML و مدل‌های سفارشی از طریق سرویس‌های جداگانه قابل دسترسی بودند. پیشنهاد جدید هر دو را به همراه سایر محصولات جدید در یک API واحد ترکیب می کند. همچنین می توانید پروژه های موجود را به Vertex AI منتقل کنید.

علاوه بر خدمات آموزش و استقرار مدل، Vertex AI همچنین شامل انواع محصولات MLOps از جمله Vertex Pipelines (تمرکز این آزمایشگاه)، مانیتورینگ مدل، فروشگاه ویژگی و غیره است. در نمودار زیر می‌توانید همه محصولات Vertex AI را مشاهده کنید.

نمای کلی محصول Vertex

اگر بازخوردی دارید، لطفاً صفحه پشتیبانی را ببینید.

چرا خطوط لوله ML مفید هستند؟

قبل از غواصی، ابتدا بیایید بفهمیم که چرا می خواهید از خط لوله استفاده کنید. تصور کنید که در حال ایجاد یک گردش کار ML هستید که شامل پردازش داده ها، آموزش یک مدل، تنظیم هایپرپارامتر، ارزیابی و استقرار مدل است. هر یک از این مراحل ممکن است وابستگی‌های متفاوتی داشته باشند، که اگر کل گردش کار را یکپارچه در نظر بگیرید، ممکن است سخت شوند. همانطور که شروع به مقیاس‌بندی فرآیند ML خود می‌کنید، ممکن است بخواهید گردش کار ML خود را با دیگران در تیم خود به اشتراک بگذارید تا آنها بتوانند آن را اجرا کرده و کد را ارائه دهند. بدون یک فرآیند قابل اعتماد و قابل تکرار، این می تواند دشوار شود. با خطوط لوله، هر مرحله در فرآیند ML شما ظرف خودش را دارد. این به شما امکان می دهد مراحل را به طور مستقل توسعه دهید و ورودی و خروجی هر مرحله را به روشی تکرارپذیر دنبال کنید. همچنین می‌توانید اجرای خط لوله خود را بر اساس رویدادهای دیگر در محیط Cloud خود، مانند شروع اجرای خط لوله زمانی که داده‌های آموزشی جدید در دسترس است، برنامه‌ریزی یا راه‌اندازی کنید.

خطوط لوله tl;dr : به شما کمک می کند گردش کار ML خود را خودکار و بازتولید کنید .

3. راه اندازی محیط ابری

برای اجرای این کد لبه به یک پروژه Google Cloud Platform با فعال بودن صورتحساب نیاز دارید. برای ایجاد یک پروژه، دستورالعمل های اینجا را دنبال کنید.

مرحله 1: Cloud Shell را راه اندازی کنید

در این آزمایشگاه شما قرار است در یک جلسه Cloud Shell کار کنید، که یک مفسر دستور است که توسط یک ماشین مجازی در حال اجرا در ابر گوگل میزبانی می شود. شما به همین راحتی می توانید این بخش را به صورت محلی در رایانه شخصی خود اجرا کنید، اما استفاده از Cloud Shell به همه امکان دسترسی به یک تجربه تکرارپذیر در یک محیط سازگار را می دهد. پس از پایان آزمایشگاه، می توانید دوباره این بخش را در رایانه شخصی خود امتحان کنید.

مجوز پوسته ابری

Cloud Shell را فعال کنید

از سمت راست بالای Cloud Console، روی دکمه زیر کلیک کنید تا Cloud Shell را فعال کنید :

Cloud Shell را فعال کنید

اگر قبلاً Cloud Shell را راه‌اندازی نکرده‌اید، یک صفحه میانی (در زیر تاشو) برای شما نمایش داده می‌شود که آن را توصیف می‌کند. اگر اینطور است، روی Continue کلیک کنید (و دیگر آن را نخواهید دید). در اینجا به نظر می رسد که آن صفحه یک بار مصرف:

راه اندازی Cloud Shell

تهیه و اتصال به Cloud Shell فقط باید چند لحظه طول بکشد.

Cloud Shell init

این ماشین مجازی با تمام ابزارهای توسعه مورد نیاز شما بارگذاری شده است. این دایرکتوری اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد شبکه و احراز هویت را بسیار افزایش می دهد. بیشتر، اگر نه همه، کار شما در این کد لبه را می توان به سادگی با یک مرورگر یا Chromebook انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که قبلاً احراز هویت شده اید و پروژه قبلاً روی ID پروژه شما تنظیم شده است.

برای تایید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:

gcloud auth list

شما باید چیزی شبیه به این را در خروجی فرمان ببینید:

خروجی پوسته ابری

دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:

gcloud config list project

خروجی فرمان

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می توانید آن را با این دستور تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی فرمان

Updated property [core/project].

Cloud Shell دارای چند متغیر محیطی است، از جمله GOOGLE_CLOUD_PROJECT که حاوی نام پروژه Cloud فعلی ما است. ما از این در جاهای مختلف این آزمایشگاه استفاده خواهیم کرد. می توانید آن را با اجرا ببینید:

echo $GOOGLE_CLOUD_PROJECT

مرحله 2: API ها را فعال کنید

در مراحل بعدی، می‌بینید که این سرویس‌ها کجا (و چرا) مورد نیاز هستند، اما در حال حاضر، این دستور را اجرا کنید تا به پروژه‌تان اجازه دسترسی به Compute Engine، Container Registry و Vertex AI را بدهید:

gcloud services enable compute.googleapis.com         \
                       containerregistry.googleapis.com  \
                       aiplatform.googleapis.com  \
                       cloudbuild.googleapis.com \
                       cloudfunctions.googleapis.com

این باید یک پیام موفقیت آمیز مشابه این را ایجاد کند:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

مرحله 3: یک سطل ذخیره سازی ابری ایجاد کنید

برای اجرای یک کار آموزشی در Vertex AI، به یک سطل ذخیره سازی برای ذخیره دارایی های مدل ذخیره شده خود نیاز داریم. سطل باید منطقه ای باشد. ما در اینجا از us-central استفاده می کنیم، اما شما می توانید از منطقه دیگری استفاده کنید (فقط آن را در سراسر این آزمایشگاه جایگزین کنید). اگر از قبل یک سطل دارید، می توانید از این مرحله رد شوید.

دستورات زیر را در ترمینال Cloud Shell خود اجرا کنید تا یک سطل ایجاد کنید:

BUCKET_NAME=gs://$GOOGLE_CLOUD_PROJECT-bucket
gsutil mb -l us-central1 $BUCKET_NAME

در مرحله بعد به حساب سرویس محاسباتی خود دسترسی به این سطل را می دهیم. این اطمینان حاصل می کند که Vertex Pipelines دارای مجوزهای لازم برای نوشتن فایل ها در این سطل است. برای افزودن این مجوز دستور زیر را اجرا کنید:

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

مرحله 4: یک نمونه Vertex AI Workbench ایجاد کنید

از بخش Vertex AI در Cloud Console خود، روی Workbench کلیک کنید:

منوی Vertex AI

از آنجا، در Notebooks توسط کاربر مدیریت شده ، روی New Notebook کلیک کنید:

نوت بوک جدید ایجاد کنید

سپس نوع نمونه TensorFlow Enterprise 2.3 (با LTS) را بدون پردازنده گرافیکی انتخاب کنید:

نمونه TFE

از گزینه های پیش فرض استفاده کنید و سپس روی ایجاد کلیک کنید.

مرحله 5: نوت بوک خود را باز کنید

پس از ایجاد نمونه، Open JupyterLab را انتخاب کنید:

نوت بوک را باز کنید

4. راه اندازی خطوط لوله ورتکس

چند کتابخانه اضافی وجود دارد که برای استفاده از Vertex Pipelines باید نصب کنیم:

  • Kubeflow Pipelines : این SDK است که ما برای ساخت خط لوله خود از آن استفاده خواهیم کرد. Vertex Pipelines از خطوط لوله در حال اجرا ساخته شده با خطوط لوله Kubeflow یا TFX پشتیبانی می کند.
  • Google Cloud Pipeline Components : این کتابخانه اجزای از پیش ساخته شده ای را ارائه می دهد که تعامل با خدمات Vertex AI را از مراحل خط لوله شما آسان تر می کند.

مرحله 1: نوت بوک پایتون ایجاد کنید و کتابخانه ها را نصب کنید

ابتدا از منوی Launcher در نمونه Notebook خود، با انتخاب Python 3 یک نوت بوک ایجاد کنید:

نوت بوک Python3 ایجاد کنید

با کلیک بر روی علامت + در سمت چپ بالای نمونه نوت بوک خود می توانید به منوی Launcher دسترسی پیدا کنید.

برای نصب هر دو سرویسی که در این آزمایشگاه استفاده خواهیم کرد، ابتدا پرچم کاربر را در سلول نوت بوک تنظیم کنید:

USER_FLAG = "--user"

سپس موارد زیر را از نوت بوک خود اجرا کنید:

!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

پس از نصب این بسته ها، باید هسته را مجددا راه اندازی کنید:

import os

if not os.getenv("IS_TESTING"):
    # Automatically restart kernel after installs
    import IPython

    app = IPython.Application.instance()
    app.kernel.do_shutdown(True)

در نهایت بررسی کنید که بسته ها را به درستی نصب کرده اید. نسخه KFP SDK باید >=1.8 باشد:

!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__))"

مرحله 2: شناسه و سطل پروژه خود را تنظیم کنید

در سراسر این آزمایشگاه، شناسه پروژه Cloud و سطلی را که قبلا ایجاد کرده‌اید، ارجاع خواهید داد. در مرحله بعد برای هر یک از آنها متغیرهایی ایجاد می کنیم.

اگر ID پروژه خود را نمی دانید، ممکن است بتوانید با اجرای موارد زیر آن را دریافت کنید:

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)

در غیر این صورت، آن را در اینجا تنظیم کنید:

if PROJECT_ID == "" or PROJECT_ID is None:
    PROJECT_ID = "your-project-id"  # @param {type:"string"}

سپس یک متغیر برای ذخیره نام سطل خود ایجاد کنید. اگر آن را در این آزمایشگاه ایجاد کرده باشید، موارد زیر کار خواهند کرد. در غیر این صورت، باید این را به صورت دستی تنظیم کنید:

BUCKET_NAME="gs://" + PROJECT_ID + "-bucket"

مرحله 3: وارد کردن کتابخانه ها

موارد زیر را برای وارد کردن کتابخانه‌هایی که در سراسر این کد لبه استفاده می‌کنیم اضافه کنید:

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

مرحله 4: ثابت ها را تعریف کنید

آخرین کاری که باید قبل از ساخت خط لوله خود انجام دهیم، تعریف چند متغیر ثابت است. PIPELINE_ROOT مسیر ذخیره سازی ابری است که در آن مصنوعات ایجاد شده توسط خط لوله ما نوشته می شود. ما در اینجا از us-central1 به عنوان منطقه استفاده می کنیم، اما اگر هنگام ایجاد سطل خود از منطقه دیگری استفاده کرده اید، متغیر REGION را در کد زیر به روز کنید:

PATH=%env PATH
%env PATH={PATH}:/home/jupyter/.local/bin
REGION="us-central1"

PIPELINE_ROOT = f"{BUCKET_NAME}/pipeline_root/"
PIPELINE_ROOT

پس از اجرای کد بالا، باید فهرست اصلی خط لوله خود را چاپ شده ببینید. این محل ذخیره سازی ابری است که مصنوعات خط لوله شما در آن نوشته می شود. در قالب gs://YOUR-BUCKET-NAME/pipeline_root/ خواهد بود

5. ایجاد اولین خط لوله

برای آشنایی با نحوه عملکرد خطوط لوله Vertex، ابتدا یک خط لوله کوتاه با استفاده از KFP SDK ایجاد می کنیم. این خط لوله هیچ کاری مرتبط با ML انجام نمی دهد (نگران نباشید، ما به آنجا خواهیم رسید!)، ما از آن برای آموزش به شما استفاده می کنیم:

  • نحوه ایجاد اجزای سفارشی در KFP SDK
  • نحوه اجرا و نظارت بر خط لوله در Vertex Pipelines

ما خط لوله ای ایجاد می کنیم که یک جمله را با استفاده از دو خروجی چاپ می کند: نام محصول و توضیحات ایموجی. این خط لوله از سه جزء تشکیل خواهد شد:

  • product_name : این کامپوننت یک نام محصول (یا هر اسمی که واقعاً می خواهید) را به عنوان ورودی می گیرد و آن رشته را به عنوان خروجی برمی گرداند.
  • emoji : این کامپوننت توضیحات متنی یک ایموجی را می گیرد و آن را به شکلک تبدیل می کند. برای مثال، کد متنی ✨ "sparkles" است. این مؤلفه از یک کتابخانه ایموجی استفاده می کند تا به شما نشان دهد چگونه وابستگی های خارجی را در خط لوله خود مدیریت کنید
  • build_sentence : این جزء نهایی خروجی دو مورد قبلی را برای ساختن جمله ای که از ایموجی استفاده می کند مصرف می کند. به عنوان مثال، خروجی حاصل ممکن است "راس Pipelines است ✨" باشد.

بیایید شروع به کدنویسی کنیم!

مرحله 1: یک مؤلفه مبتنی بر تابع پایتون ایجاد کنید

با استفاده از KFP SDK، می توانیم اجزایی را بر اساس توابع پایتون ایجاد کنیم. ما از آن برای 3 جزء در اولین خط لوله خود استفاده خواهیم کرد. ابتدا مولفه product_name می سازیم، که به سادگی یک رشته را به عنوان ورودی می گیرد و آن رشته را برمی گرداند. موارد زیر را به دفترچه یادداشت خود اضافه کنید:

@component(base_image="python:3.9", output_component_file="first-component.yaml")
def product_name(text: str) -> str:
    return text

بیایید نگاهی دقیق تر به نحو در اینجا بیندازیم:

  • دکوراتور @component این تابع را در زمانی که خط لوله اجرا می شود به یک جزء کامپایل می کند. هر زمان که یک مؤلفه سفارشی بنویسید، از این استفاده خواهید کرد.
  • پارامتر base_image تصویر محفظه ای را که این کامپوننت استفاده می کند مشخص می کند.
  • پارامتر output_component_file اختیاری است و فایل yaml را برای نوشتن جزء کامپایل شده مشخص می کند. پس از اجرای سلول، باید آن فایل را ببینید که در نمونه نوت بوک شما نوشته شده است. اگر می‌خواهید این مؤلفه را با کسی به اشتراک بگذارید، می‌توانید فایل yaml تولید شده را برای او ارسال کنید و از او بخواهید آن را با موارد زیر بارگذاری کند:
product_name_component = kfp.components.load_component_from_file('./first-component.yaml')
  • -> str بعد از تعریف تابع، نوع خروجی این جزء را مشخص می کند.

مرحله 2: دو جزء اضافی ایجاد کنید

برای تکمیل خط لوله خود، دو جزء دیگر ایجاد خواهیم کرد. اولین موردی که تعریف می کنیم یک رشته را به عنوان ورودی می گیرد و در صورت وجود این رشته را به ایموجی مربوطه خود تبدیل می کند. یک تاپل را با متن ورودی ارسال شده و ایموجی به دست آمده برمی گرداند:

@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)

این جزء کمی پیچیده تر از قبلی ما است. بیایید موارد جدید را تجزیه کنیم:

  • پارامتر packages_to_install هر گونه وابستگی کتابخانه خارجی برای این کانتینر را به مؤلفه می گوید. در این مورد، ما از کتابخانه ای به نام emoji استفاده می کنیم.
  • این کامپوننت یک NamedTuple به نام Outputs را برمی گرداند. توجه داشته باشید که هر یک از رشته های این تاپل دارای کلیدهایی هستند: emoji_text و emoji . ما از اینها در کامپوننت بعدی خود برای دسترسی به خروجی استفاده خواهیم کرد.

کامپوننت نهایی در این خط لوله خروجی دو مورد اول را مصرف می کند و آنها را برای بازگشت یک رشته ترکیب می کند:

@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)

شاید از خود بپرسید: چگونه این مؤلفه می داند که از خروجی مراحل قبلی که تعریف کرده اید استفاده کند؟ سوال خوب! در مرحله بعد همه را با هم گره می زنیم.

مرحله 3: قرار دادن اجزا در کنار هم در یک خط لوله

تعاریف مؤلفه ای که در بالا تعریف کردیم، توابع کارخانه ای ایجاد کردند که می توانند در تعریف خط لوله برای ایجاد مراحل استفاده شوند. برای راه‌اندازی خط لوله، از دکوراتور @pipeline استفاده کنید، خط لوله را نام و توضیح دهید و مسیر اصلی را که مصنوعات خط لوله شما باید در آن نوشته شوند، ارائه دهید. منظور ما از مصنوعات، هر فایل خروجی تولید شده توسط خط لوله شما است. این خط لوله مقدماتی هیچ تولید نمی کند، اما خط لوله بعدی ما تولید خواهد کرد.

در بلوک بعدی کد یک تابع intro_pipeline تعریف می کنیم. اینجاست که ورودی های مراحل اولیه خط لوله خود و نحوه اتصال مراحل به یکدیگر را مشخص می کنیم:

  • product_task نام محصول را به عنوان ورودی می گیرد. در اینجا ما در حال عبور از "خطوط Vertex" هستیم، اما شما می توانید آن را به هر چیزی که می خواهید تغییر دهید.
  • emoji_task کد متنی ایموجی را به عنوان ورودی می گیرد. شما همچنین می توانید این را به هر چیزی که می خواهید تغییر دهید. به عنوان مثال، "party_face" به ایموجی 🥳 اشاره دارد. توجه داشته باشید که از آنجایی که هم این و هم مولفه product_task هیچ مرحله‌ای ندارند که ورودی را به آن‌ها وارد کند، وقتی خط لوله خود را تعریف می‌کنیم، ورودی آن‌ها را به صورت دستی مشخص می‌کنیم.
  • آخرین مرحله در خط لوله ما - consumer_task دارای سه پارامتر ورودی است:
    • خروجی product_task . از آنجایی که این مرحله فقط یک خروجی تولید می کند، می توانیم از طریق product_task.output به آن ارجاع دهیم.
    • خروجی emoji مرحله emoji_task ما. مولفه emoji تعریف شده در بالا را ببینید، جایی که ما پارامترهای خروجی را نامگذاری کردیم.
    • به طور مشابه، emoji_text به نام خروجی از مولفه emoji . در صورتی که خط لوله ما متنی را ارسال کند که با ایموجی مطابقت ندارد، از این متن برای ساختن یک جمله استفاده خواهد کرد.
@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"],
    )

مرحله 4: خط لوله را کامپایل و اجرا کنید

با تعریف خط لوله شما، آماده کامپایل آن هستید. موارد زیر یک فایل JSON ایجاد می کند که از آن برای اجرای خط لوله استفاده می کنید:

compiler.Compiler().compile(
    pipeline_func=intro_pipeline, package_path="intro_pipeline_job.json"
)

بعد، یک متغیر TIMESTAMP ایجاد کنید. ما از این در شناسه شغلی خود استفاده خواهیم کرد:

from datetime import datetime

TIMESTAMP = datetime.now().strftime("%Y%m%d%H%M%S")

سپس کار خط لوله خود را تعریف کنید:

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
)

در نهایت، کار را برای ایجاد یک اجرای خط لوله جدید اجرا کنید:

job.submit()

پس از اجرای این سلول، باید گزارش هایی را با پیوندی برای مشاهده خط لوله اجرا شده در کنسول خود مشاهده کنید:

گزارش کار خط لوله

به آن لینک بروید. خط لوله شما پس از تکمیل باید به این شکل باشد:

خط لوله مقدماتی تکمیل شده

این خط لوله 5-6 دقیقه طول می کشد تا اجرا شود . پس از اتمام، می توانید بر روی مولفه build-sentence کلیک کنید تا خروجی نهایی را ببینید:

خروجی خط لوله مقدماتی

اکنون که با نحوه عملکرد KFP SDK و Vertex Pipelines آشنا شدید، آماده ساختن خط لوله ای هستید که یک مدل ML را با استفاده از سایر خدمات Vertex AI ایجاد و اجرا می کند. بیایید شیرجه بزنیم!

6. ایجاد خط لوله ML سرتاسر

وقت آن است که اولین خط لوله ML خود را بسازید. در این خط لوله، از مجموعه داده‌های لوبیا خشک یادگیری ماشینی UCI استفاده خواهیم کرد، از: KOKLU، M. و OZKAN، IA، (2020)، «طبقه‌بندی چند کلاسه لوبیا خشک با استفاده از تکنیک‌های بینایی رایانه و یادگیری ماشین». In Computers and Electronics in Agriculture, 174, 105507. DOI .

این یک مجموعه داده جدولی است و در خط لوله ما از مجموعه داده برای آموزش، ارزیابی و استقرار یک مدل AutoML استفاده می‌کنیم که دانه‌ها را بر اساس ویژگی‌هایشان به یکی از ۷ نوع طبقه‌بندی می‌کند.

این خط لوله:

  • ایجاد یک مجموعه داده در
  • یک مدل طبقه بندی جدولی با AutoML آموزش دهید
  • معیارهای ارزیابی را در این مدل دریافت کنید
  • بر اساس معیارهای ارزیابی، تصمیم بگیرید که آیا مدل را با استفاده از منطق شرطی در خطوط لوله Vertex مستقر کنید یا خیر.
  • با استفاده از Vertex Prediction ، مدل را در نقطه پایانی مستقر کنید

هر یک از مراحل ذکر شده یک جزء خواهد بود. اکثر مراحل خط لوله از اجزای از پیش ساخته شده برای خدمات Vertex AI از طریق کتابخانه google_cloud_pipeline_components که قبلاً در این Codelab وارد کردیم، استفاده می کنند. در این بخش ابتدا یک جزء سفارشی را تعریف می کنیم. سپس، بقیه مراحل خط لوله را با استفاده از اجزای از پیش ساخته شده تعریف می کنیم. اجزای از پیش ساخته شده دسترسی به خدمات Vertex AI مانند آموزش مدل و استقرار را آسان تر می کند.

مرحله 1: یک جزء سفارشی برای ارزیابی مدل

پس از اتمام آموزش مدل، جزء سفارشی که تعریف خواهیم کرد، در انتهای خط لوله ما استفاده خواهد شد. این کامپوننت چند کار را انجام می دهد:

  • معیارهای ارزیابی را از مدل طبقه‌بندی آموزش دیده AutoML دریافت کنید
  • معیارها را تجزیه کنید و در رابط کاربری Vertex Pipelines رندر کنید
  • معیارها را با یک آستانه مقایسه کنید تا مشخص کنید آیا مدل باید به کار گرفته شود یا خیر

قبل از اینکه کامپوننت را تعریف کنیم، اجازه دهید پارامترهای ورودی و خروجی آن را درک کنیم. به عنوان ورودی، این خط لوله مقداری ابرداده در پروژه Cloud ما، مدل آموزش‌دیده حاصل (این مؤلفه را بعداً تعریف خواهیم کرد)، معیارهای ارزیابی مدل، و یک thresholds_dict_str . thresholds_dict_str چیزی است که ما هنگام اجرای خط لوله خود تعریف می کنیم. در مورد این مدل طبقه بندی، این ناحیه زیر مقدار منحنی ROC خواهد بود که باید مدل را برای آن مستقر کنیم. به عنوان مثال، اگر از 0.95 عبور کنیم، به این معنی است که ما فقط می‌خواهیم که خط لوله ما مدل را اجرا کند که این معیار بالاتر از 95٪ باشد.

مؤلفه ارزیابی ما رشته‌ای را برمی‌گرداند که نشان می‌دهد آیا باید مدل را مستقر کنیم یا نه. برای ایجاد این مؤلفه سفارشی موارد زیر را در یک سلول نوت بوک اضافه کنید:

@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,)

مرحله 2: افزودن اجزای از پیش ساخته شده Google Cloud

در این مرحله ما بقیه اجزای خط لوله خود را تعریف می کنیم و می بینیم که چگونه همه آنها با هم هماهنگ می شوند. ابتدا نام نمایشی خط لوله خود را با استفاده از مهر زمانی تعریف کنید:

import time
DISPLAY_NAME = 'automl-beans{}'.format(str(int(time.time())))
print(DISPLAY_NAME)

سپس موارد زیر را در یک سلول نوت بوک جدید کپی کنید:

@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",
        )

بیایید ببینیم در این کد چه اتفاقی می افتد:

  • ابتدا، درست مانند خط لوله قبلی، پارامترهای ورودی را که این خط لوله می گیرد، تعریف می کنیم. ما باید اینها را به صورت دستی تنظیم کنیم زیرا به خروجی مراحل دیگر در خط لوله بستگی ندارند.
  • بقیه خط لوله از چند جزء از پیش ساخته شده برای تعامل با خدمات Vertex AI استفاده می کند:
    • TabularDatasetCreateOp یک مجموعه داده جدولی در Vertex AI ایجاد می کند که منبع داده ای را در Cloud Storage یا BigQuery داده است. در این خط لوله، ما داده ها را از طریق URL جدول BigQuery ارسال می کنیم
    • AutoMLTabularTrainingJobRunOp کار آموزش AutoML را برای مجموعه داده جدولی آغاز می کند. ما چند پارامتر پیکربندی را به این مؤلفه ارسال می‌کنیم، از جمله نوع مدل (در این مورد، طبقه‌بندی)، برخی از داده‌ها در ستون‌ها، مدت زمانی که می‌خواهیم آموزش را اجرا کنیم، و یک اشاره‌گر به مجموعه داده. توجه داشته باشید که برای ارسال مجموعه داده به این مؤلفه، خروجی مؤلفه قبلی را از طریق dataset_create_op.outputs["dataset"] ارائه می کنیم.
    • EndpointCreateOp یک نقطه پایانی در Vertex AI ایجاد می کند. نقطه پایانی ایجاد شده از این مرحله به عنوان ورودی به مؤلفه بعدی ارسال می شود
    • ModelDeployOp یک مدل داده شده را به نقطه پایانی در Vertex AI مستقر می کند. در این مورد، ما از نقطه پایانی ایجاد شده از مرحله قبل استفاده می کنیم. گزینه‌های پیکربندی اضافی در دسترس هستند، اما در اینجا نوع و مدل دستگاه نقطه پایانی را که می‌خواهیم اجرا کنیم، ارائه می‌کنیم. ما در حال عبور از مدل با دسترسی به خروجی های مرحله آموزش در خط لوله خود هستیم
  • این خط لوله همچنین از منطق شرطی استفاده می کند، ویژگی Vertex Pipelines که به شما امکان می دهد یک شرط را به همراه شاخه های مختلف بر اساس نتیجه آن شرط تعریف کنید. به یاد داشته باشید که وقتی خط لوله خود را تعریف کردیم، یک پارامتر thresholds_dict_str را پاس کردیم. این آستانه دقتی است که ما برای تعیین اینکه آیا مدل خود را در یک نقطه پایانی مستقر کنیم یا خیر، استفاده می کنیم. برای پیاده سازی این، از کلاس Condition از KFP SDK استفاده می کنیم. شرطی که ما از آن عبور می کنیم خروجی کامپوننت سفارشی eval است که قبلاً در این codelab تعریف کردیم. اگر این شرط درست باشد، خط لوله به اجرای جزء deploy_op ادامه خواهد داد. اگر دقت به آستانه از پیش تعریف شده ما نرسد، خط لوله در اینجا متوقف می شود و مدلی را مستقر نمی کند.

مرحله 3: خط لوله ML سرتاسری را کامپایل و اجرا کنید

با تعریف خط لوله کامل ما، زمان آن رسیده که آن را کامپایل کنیم:

compiler.Compiler().compile(
    pipeline_func=pipeline, package_path="tab_classif_pipeline.json"
)

بعد، کار را تعریف کنید:

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
)

و در نهایت کار را اجرا کنید:

ml_pipeline_job.submit()

پس از اجرای سلول بالا به پیوند نشان داده شده در گزارش ها بروید تا خط لوله خود را در کنسول ببینید. اجرای این خط لوله کمی بیش از یک ساعت طول خواهد کشید. بیشتر زمان در مرحله آموزش AutoML صرف می شود. خط لوله تکمیل شده چیزی شبیه به این خواهد بود:

خط لوله AutoML تکمیل شد

اگر دکمه "گسترش مصنوعات" را در بالا تغییر دهید، می توانید جزئیات مربوط به مصنوعات مختلف ایجاد شده از خط لوله خود را مشاهده کنید. برای مثال، اگر روی آرتیفکت dataset کلیک کنید، جزئیات مربوط به مجموعه داده Vertex AI ایجاد شده را مشاهده خواهید کرد. برای رفتن به صفحه مربوط به مجموعه داده می توانید روی پیوند اینجا کلیک کنید:

مجموعه داده خط لوله

به طور مشابه، برای دیدن تجسم‌های متریک حاصل از مؤلفه ارزیابی سفارشی ما، روی مصنوع به نام metricsc کلیک کنید. در سمت راست داشبورد خود، می‌توانید ماتریس سردرگمی این مدل را ببینید:

تجسم متریک

برای مشاهده مدل و نقطه پایانی ایجاد شده از اجرای این خط لوله، به قسمت models رفته و بر روی مدل با نام automl-beans کلیک کنید. . در آنجا باید این مدل را در یک نقطه پایانی مشاهده کنید:

مدل-نقطه پایانی

همچنین می توانید با کلیک بر روی آرتیفکت نقطه پایانی در نمودار خط لوله خود به این صفحه دسترسی پیدا کنید.

علاوه بر مشاهده نمودار خط لوله در کنسول، می‌توانید از Pipelines Vertex برای ردیابی خط و نسب نیز استفاده کنید. منظور ما از ردیابی نسب، ردیابی مصنوعات ایجاد شده در سراسر خط لوله شما است. این می تواند به ما کمک کند تا بفهمیم که مصنوعات در کجا ایجاد شده اند و چگونه از آنها در جریان کار ML استفاده می شود. به عنوان مثال، برای مشاهده ردیابی خط و نسب برای مجموعه داده ایجاد شده در این خط لوله، روی مصنوع مجموعه داده و سپس View Lineage کلیک کنید:

مشاهده اصل و نسب

این همه مکان هایی را که از این مصنوع استفاده می شود به ما نشان می دهد:

جزئیات اصل و نسب

مرحله 4: مقایسه معیارها در سراسر خطوط لوله

اگر چندین بار این خط لوله را اجرا کنید، ممکن است بخواهید معیارها را در طول اجراها مقایسه کنید. می توانید از متد aiplatform.get_pipeline_df() برای دسترسی به ابرداده های اجرا شده استفاده کنید. در اینجا، ما متادیتا را برای همه اجرای این خط لوله دریافت می کنیم و آن را در Pandas DataFrame بارگذاری می کنیم:

pipeline_df = aiplatform.get_pipeline_df(pipeline="automl-tab-beans-training-v2")
small_pipeline_df = pipeline_df.head(2)
small_pipeline_df

با آن، شما آزمایشگاه را به پایان رساندید!

🎉 تبریک می گویم! 🎉

شما یاد گرفته اید که چگونه از Vertex AI برای موارد زیر استفاده کنید:

  • از Kubeflow Pipelines SDK برای ساخت خطوط لوله انتها به انتها با اجزای سفارشی استفاده کنید
  • خطوط لوله خود را روی Vertex Pipelines اجرا کنید و اجرای خط لوله را با SDK شروع کنید
  • نمودار Vertex Pipelines خود را در کنسول مشاهده و تجزیه و تحلیل کنید
  • از اجزای خط لوله از پیش ساخته شده برای افزودن خدمات Vertex AI به خط لوله خود استفاده کنید
  • کارهای خط لوله مکرر را برنامه ریزی کنید

برای کسب اطلاعات بیشتر در مورد بخش های مختلف Vertex، مستندات را بررسی کنید.

7. پاکسازی

برای اینکه هزینه ای از شما دریافت نشود، توصیه می شود منابع ایجاد شده در سراسر این آزمایشگاه را حذف کنید.

مرحله 1: نمونه Notebook خود را متوقف یا حذف کنید

اگر می‌خواهید به استفاده از نوت‌بوکی که در این آزمایشگاه ایجاد کرده‌اید ادامه دهید، توصیه می‌شود در صورت عدم استفاده آن را خاموش کنید. از رابط کاربری Notebooks در Cloud Console، نوت بوک را انتخاب کنید و سپس Stop را انتخاب کنید. اگر می خواهید نمونه را به طور کامل حذف کنید، حذف را انتخاب کنید:

توقف نمونه

مرحله 2: نقطه پایانی خود را حذف کنید

برای حذف نقطه پایانی که مستقر کرده اید، به بخش Endpoints کنسول Vertex AI خود بروید و روی نماد حذف کلیک کنید:

نقطه پایانی را حذف کنید

سپس از دستور زیر بر روی Undeploy کلیک کنید:

مدل Undeploy

در نهایت، به بخش Models کنسول خود بروید، آن مدل را پیدا کنید و از منوی سه نقطه سمت راست، روی Delete model کلیک کنید:

حذف مدل

مرحله 3: سطل Cloud Storage خود را حذف کنید

برای حذف Storage Bucket، با استفاده از منوی Navigation در Cloud Console خود، به Storage بروید، سطل خود را انتخاب کنید و روی Delete کلیک کنید:

ذخیره سازی را حذف کنید