Vertex AI를 사용한 Spark ML 모델 제공

Last reviewed 2023-07-11 UTC

데이터 과학자 및 머신러닝(ML) 엔지니어에게는 ML 모델에서 온라인(또는 실시간) 예측을 생성해야 하는 요구 사항을 충족할 수 있을 정도로 빠른 제공 아키텍처가 필요한 경우가 많습니다. Vertex AI가 이러한 요구사항을 충족할 수 있습니다.

Vertex AI를 사용하면 다양한 ML 프레임워크에서 모델을 제공할 수 있습니다. TensorFlow, PyTorch, XGBoost, scikit-learn과 같은 프레임워크의 경우 Vertex AI는 이러한 ML 모델을 실행할 수 있도록 사전 빌드된 컨테이너를 제공합니다. 이러한 ML 프레임워크를 아직 사용하지 않는 경우 Vertex AI에서 사용할 자체 커스텀 컨테이너를 만들어야 합니다.

이 문서는 Spark ML 모델을 제공하기 위해 커스텀 컨테이너를 만들어야 하는 사용자를 대상으로 합니다. 이 문서에는 커스텀 컨테이너에 필요한 제공 아키텍처에 대한 설명과 Spark MLib 모델을 위한 아키텍처를 보여주는 참조 구현이 포함되어 있습니다.

이 문서의 참조 구현 부분을 최대한 활용하려면 Spark MLlib 모델을 MLeap 형식으로 내보내는 데 익숙하고 Vertex AI를 사용하여 예측을 제공하는 방법을 이해하고 컨테이너 이미지를 사용한 경험이 있어야 합니다.

아키텍처

일부 ML 프레임워크에서는 사전 빌드된 컨테이너를 사용할 수 있지만, Spark와 같은 다른 ML 프레임워크 사용자는 Vertex AI가 예측을 실행할 수 있는 커스텀 컨테이너를 빌드해야 합니다. 다음 다이어그램은 Spark MLib 모델 및 커스텀 컨테이너가 필요한 다른 모델을 제공하는 데 필요한 제공 아키텍처를 보여줍니다.

이 문서에서 사용되는 모델의 제공 아키텍처입니다.

이 아키텍처에는 다음 구성요소가 포함됩니다.

  • Cloud Storage: 모델을 실행하는 데 필요한 모델 아티팩트를 위한 스토리지를 제공합니다. 동반된 참조 구현에 사용되는 Spark ML 모델의 경우 모델 아티팩트는 MLeap 번들과 모델 스키마로 구성됩니다.
  • Cloud Build: 빌더 이미지를 사용하여 제공 컨테이너 이미지라는 커스텀 컨테이너 이미지를 빌드합니다. 빌드 프로세스가 모델 제공 코드를 컴파일 및 패키징하고, 제공 컨테이너 이미지를 빌드한 다음, 제공 컨테이너 이미지를 Artifact Registry에 푸시합니다.
  • Artifact Registry: 다음 객체가 포함되어 있습니다.
    • Cloud Build가 제공 컨테이너 이미지를 빌드하는 데 사용하는 scala-sbt 빌더 컨테이너 이미지입니다.
    • Cloud Build에서 빌드한 제공 컨테이너 이미지입니다.
  • Vertex AI: Cloud Storage에서 업로드된 ML 모델을 포함합니다. 업로드된 모델은 Cloud Storage 내의 모델 아티팩트 위치 및 Artifact Registry 내의 제공 컨테이너 이미지 위치로 구성됩니다. Vertex AI에는 모델이 배포된 엔드포인트도 포함됩니다. 모델이 엔드포인트에 배포되면 Vertex AI는 모델이 온라인 예측을 제공할 수 있도록 물리적 리소스를 모델과 연결합니다.

이 제공 아키텍처를 구현하는 과정에서 다른 애플리케이션에서 사용할 수 있도록 ML 모델을 내보내고 자체 제공 컨테이너 이미지를 정의해야 합니다. 이 문서에 제공된 참조 구현은 제공 컨테이너 이미지를 정의하고 빌드하는 데 사용되는 코드를 제공합니다. 이 코드에는 이전에 내보낸 Spark ML 모델의 모델 아티팩트도 포함됩니다. 몇 가지 구성 변경의 경우 이 참조 구현을 사용해서 고유한 Spark ML 모델을 제공할 수 있습니다.

하지만 참조 구현을 사용하지 않고 직접 이 제공 아키텍처를 구현할 수 있습니다. 자체 아키텍처를 구현하기로 결정한 경우 다음을 수행해야 합니다.

  • 다른 애플리케이션에서 사용할 수 있도록 모델을 내보냅니다. 이 프로세스는 사용 중인 ML 프레임워크 및 도구에 따라 달라집니다. 예를 들어 참조 구현에 설명된 대로 MLeap 번들을 만들어 Spark MLlib 모델을 내보낼 수 있습니다. 예측용 모델 아티팩트 내보내기에서 모델을 내보내는 다른 예시를 확인할 수 있습니다.
  • 해당 이미지가 Vertex AI와 호환되는 커스텀 컨테이너 요구사항을 충족하도록 제공 컨테이너 이미지를 설계합니다. 코드는 선택한 프로그래밍 언어로 되어 있을 수 있습니다.
  • 사용한 프로그래밍 언어와 호환되는 패키지 파일 형식으로 코드를 패키징합니다. 예를 들어 자바 코드에 JAR 파일을 사용하거나 Python 코드에 Python wheel을 사용할 수 있습니다.
  • 커스텀 모드 코드를 제공할 수 있는 커스텀 컨테이너 이미지를 만듭니다.

참조 구현

다음 참조 구현은 꽃의 꽃받침과 꽃잎의 길이와 너비를 기반으로 아이리스 꽃의 종류를 예측하는 Spark MLib 모델을 제공합니다.

이 구현에 사용되는 모델은 vertex-ai-spark-ml-serving.git 저장소example_model 디렉터리에서 찾을 수 있습니다. 디렉터리에는 제공 컨테이너가 예측을 실행하기 위해 사용하는 모델 아티팩트가 포함되며 다음 파일도 포함되어 있습니다.

  • example_model/model.zip 파일은 Spark MLlib를 사용하여 빌드되고, Iris 데이터 세트를 사용하여 학습되었으며, MLeap 번들로 변환된 로지스틱 회귀 모델입니다. 이 모델은 꽃의 꽃받침과 꽃잎의 길이와 너비를 사용하여 아이리스 꽃의 종을 예측합니다.
  • example_model/schema.json 파일은 모델 스키마를 설명하는 JSON 파일입니다. 모델 스키마는 예측 인스턴스에 필요한 입력 필드와 MLeap 스키마에 필요한 예측 결과에 대한 출력 필드를 설명합니다.

자체 Mlib 모델 사용

이 참조 구현에서 자체 모델을 사용하려면 먼저 Spark MLlib 모델을 MLeap 번들로 내보냈는지 확인합니다. 그런 다음 Spark MLib 모델을 제공하려면 적절한 모델 아티팩트인 MLeap 번들과 모델 스키마를 제공해야 합니다.

MLeap 번들

제공 컨테이너는 시작 시 Vertex AI에서 컨테이너로 전달되는 AIP_STORAGE_URI 환경 변수를 사용하여 MLeap 번들의 위치를 결정합니다. AIP_STORAGE_URI 변수의 값은 모델을 Vertex AI에 업로드할 때 지정됩니다.

모델 스키마

모델 스키마는 모델의 입력 기능 및 예측 출력을 설명합니다. 모델 스키마는 JSON 데이터를 사용하여 표현됩니다. 다음은 이 참조 구현에서 꽃의 길이와 꽃받침과 꽃잎의 너비를 기준으로 아이리스 꽃의 종류를 예측하는 데 사용되는 스키마입니다.

{
  "input": [
    {
      "name": "sepal_length",
      "type": "FLOAT"
    },
    {
      "name": "sepal_width",
      "type": "FLOAT"
    },
    {
      "name": "petal_length",
      "type": "FLOAT"
    },
    {
      "name": "petal_width",
      "type": "FLOAT"
    }
  ],
  "output": [
    {
      "name": "probability",
      "type": "DOUBLE",
      "struct": "VECTOR"
    }
  ]
}

스키마 예시의 input 배열에 모델의 입력 필드(열)가 포함되고 output 배열에는 모델에서 반환될 출력 필드(열)가 포함됩니다. 두 배열 모두 배열의 각 객체에 다음 속성이 포함됩니다.

  • name: 필드(열) 이름입니다.
  • type: 필드(열) 유형입니다. 유효한 유형에는 BOOLEAN, BYTE, DOUBLE, FLOAT, INTEGER, LONG, SHORT, STRING이 있습니다.
  • (선택사항) struct: 스칼라 또는 배열과 같은 필드 구조입니다. 유효한 구조에는 BASIC(스칼라 유형), ARRAY(Spark Array), VECTOR(Spark DenseVector)가 포함됩니다. BASICstruct 필드가 없을 때 사용됩니다.

모델 스키마를 제공 컨테이너로 전달하려면 다음 방법 중 하나를 사용하면 됩니다.

  • MLEAP_SCHEMA 환경 변수에서 스키마를 정의하는 JSON 데이터를 지정합니다. MLEAP_SCHEMA 환경 변수에는 JSON 스키마가 포함된 파일의 경로가 아니라 JSON 데이터 자체가 포함되어야 합니다.
  • schema.json이라는 JSON 데이터를 저장하고 이 파일을 ${AIP_STORAGE_URI}/schema.json의 컨테이너에 제공합니다. 이 문서에 제공된 MLib 모델 예시에 사용되는 방법입니다.

두 방법을 모두 사용하여 모델 스키마를 제공 컨테이너로 전달할 경우 MLEAP_SCHEMA 환경 변수에 저장된 JSON 데이터가 우선 적용됩니다.

비용

이 참조 구현은 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.

이 참조 구현을 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않도록 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

  1. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  2. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  3. API Vertex AI, Cloud Build, Cloud Storage, and Artifact Registry 사용 설정

    API 사용 설정

  4. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

  5. 프로젝트 ID를 찾아서 Cloud Shell에서 설정합니다.
    export PROJECT_ID=YOUR_PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    YOUR_PROJECT_ID를 프로젝트 ID로 바꿉니다.

scala-sbt 빌더 이미지 만들기

scala-sbt 커뮤니티 빌더와 함께 Cloud Build를 사용하여 제공 컨테이너 이미지를 빌드합니다. 이 빌드 프로세스는 프로젝트의 Container Registry에 sbt-scala 빌더 이미지가 있는지에 따라 달라집니다.

  1. Cloud Shell에서 cloud-builders-community 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
    
  2. 프로젝트 디렉터리로 이동합니다.

    cd cloud-builders-community/scala-sbt
    
  3. scala-sbt 빌더 이미지를 빌드하고 이를 Container Registry에 푸시합니다.

    gcloud builds submit .
    

제공 컨테이너 이미지 빌드

Vertex AI는 제공 컨테이너를 사용하여 모델 예시에 대한 예측 요청을 실행합니다. 제공 컨테이너 이미지를 빌드하는 첫 번째 단계는 Artifact Registry에 이미지를 저장할 Docker 저장소를 만드는 것입니다. 그런 후 Vertex AI에 저장소에서 제공 컨테이너 이미지를 가져오기 위한 권한을 부여해야 합니다. 저장소를 만들고 권한을 부여한 후에는 제공 컨테이너 이미지를 빌드하고 이미지를 Artifact Registry에 푸시할 수 있습니다.

  1. Cloud Shell에서 Artifact Registry에 Docker 저장소를 만듭니다.

    REPOSITORY="vertex-ai-prediction"
    LOCATION="us-central1"
    
    gcloud artifacts repositories create $REPOSITORY \
        --repository-format=docker \
        --location=$LOCATION
    
  2. Artifact Registry 리더 역할을 Vertex AI 서비스 에이전트에 부여합니다.

    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
        --format="value(projectNumber)")
    SERVICE_ACCOUNT="service-$PROJECT_NUMBER@gcp-sa-aiplatform.iam.gserviceaccount.com"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:$SERVICE_ACCOUNT" \
        --role="roles/artifactregistry.reader"
    
  3. spark-ml-serving 저장소를 복제합니다.

    git clone https://github.com/GoogleCloudPlatform/vertex-ai-spark-ml-serving.git
    
  4. 프로젝트 디렉터리로 이동합니다.

    cd vertex-ai-spark-ml-serving
    
  5. 프로젝트에 제공 컨테이너 이미지를 빌드합니다.

    IMAGE=spark-ml-serving
    
    gcloud builds submit --config=cloudbuild.yaml \
        --substitutions="_LOCATION=$LOCATION,_REPOSITORY=$REPOSITORY,_IMAGE=$IMAGE" .
    

    cloudbuild.yaml 파일은 scala-sbt 빌더 및 docker 이미지 빌더의 두 가지 빌더를 지정합니다. Cloud Build는 scala-sbt 빌더를 사용하여 Cloud Storage에서 모델 제공 코드를 컴파일한 후 컴파일된 코드를 실행 가능한 JAR 파일로 패키지합니다. Cloud Build는 docker 빌더를 사용하여 JAR 파일이 포함된 제공 컨테이너 이미지를 빌드합니다. 제공 컨테이너 이미지를 빌드한 후 이미지가 Artifact Registry에 푸시됩니다.

Vertex AI로 모델 가져오기

제공 컨테이너가 Cloud Storage에서 모델 아티팩트를 읽습니다. 모델을 Vertex AI로 가져오려면 먼저 이러한 아티팩트에 대해 스토리지 위치를 만들어야 합니다. 모델을 가져올 때는 모델 아티팩트 스토리지 위치 및 Artifact Registry에 있는 제공 컨테이너 이미지가 모두 필요합니다.

  1. Cloud Shell에서 모델 아티팩트에 대한 버킷을 만듭니다.

    REGION="us-central1"
    BUCKET="YOUR_BUCKET_NAME"
    gsutil mb -l $REGION gs://$BUCKET
    

    YOUR_BUCKET_NAME을 버킷 이름으로 바꿉니다.

  2. 모델 아티팩트를 버킷에 복사합니다.

    gsutil cp example_model/* gs://$BUCKET/example_model/
    
  3. 모델을 Vertex AI로 가져옵니다.

    DISPLAY_NAME="iris-$(date +'%Y%m%d%H%M%S')"
    IMAGE_URI="${LOCATION}-docker.pkg.dev/$PROJECT_ID/${REPOSITORY}/${IMAGE}"
    ARTIFACT_URI="gs://$BUCKET/example_model/"
    
    gcloud ai models upload \
        --region=$REGION \
        --display-name=$DISPLAY_NAME \
        --container-image-uri=$IMAGE_URI \
        --artifact-uri=$ARTIFACT_URI \
        --container-health-route="/health" \
        --container-predict-route="/predict"
    

    gcloud ai models upload 명령어에서 --artifact-uri 매개변수의 값은 AIP_STORAGE_URI 변수의 값을 지정합니다. 이 변수는 Vertex AI로 가져오는 중인 MLeap 번들의 위치를 제공합니다.

새 엔드포인트에 모델 배포

Vertex AI가 예측을 실행하려면 가져온 모델을 엔드포인트에 배포해야 합니다. 모델을 배포할 때는 엔드포인트의 ID 및 모델의 ID가 모두 필요합니다.

  1. Cloud Shell에서 모델 엔드포인트를 만듭니다.

    gcloud ai endpoints create \
        --region=$REGION \
        --display-name=$DISPLAY_NAME
    

    gcloud 명령줄 도구가 엔드포인트를 만드는 데 몇 초 정도 걸릴 수 있습니다.

  2. 새로 만든 엔드포인트의 엔드포인트 ID를 가져옵니다.

    ENDPOINT_ID=$(gcloud ai endpoints list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print ENDPOINT_ID to the console
    echo "Your endpoint ID is: $ENDPOINT_ID"
    
  3. Vertex AI에 모델 가져오기 섹션에서 가져온 모델의 모델 ID를 확인합니다.

    MODEL_ID=$(gcloud ai models list \
        --region=$REGION \
        --filter=display_name=$DISPLAY_NAME \
        --format='value(name)')
    
    # Print MODEL_ID to the console
    echo "Your model ID is: $MODEL_ID"
    
  4. 모델을 엔드포인트에 배포합니다.

    gcloud ai endpoints deploy-model $ENDPOINT_ID \
        --region=$REGION \
        --model=$MODEL_ID \
        --display-name=$DISPLAY_NAME \
        --traffic-split="0=100"
    

    gcloud 명령어는 모델을 엔드포인트에 배포합니다. 기본값은 머신 리소스 유형, 최소 및 최대 노드 수, 기타 구성 옵션에 사용됩니다. 모델 배포 옵션에 대한 자세한 내용은 Vertex AI 문서를 참조하세요.

엔드포인트 테스트

엔드포인트에 모델을 배포한 후에는 구현을 테스트할 수 있습니다. 엔드포인트를 테스트하려면 참조 구현 코드에 포함된 예시 클라이언트를 사용할 수 있습니다. 예시 클라이언트는 예측 인스턴스를 생성하고 엔드포인트에 예측 요청을 전송합니다. 각 예측 인스턴스에는 sepal_length, sepal_width, petal_length, petal_width에 대한 무작위화된 값이 포함됩니다. 기본적으로 예시 클라이언트는 여러 예측 인스턴스를 단일 요청으로 결합합니다. 엔드포인트 응답의 응답에는 요청에 전송된 각 인스턴스의 예측이 포함됩니다. 예측에는 아이리스 꽃 데이터 세트(setosa, versicolor, virginica)의 각 클래스에 대한 확률이 포함됩니다.

  • Cloud Shell에서 예시 예측 클라이언트를 실행합니다.

    cd example_client
    ./run_client.sh --project $PROJECT_ID \
        --location $LOCATION \
        --endpoint $ENDPOINT_ID
    

    스크립트를 처음 실행하면 Python 가상 환경이 생성되고 종속 항목이 설치됩니다. 종속 항목을 설치하면 스크립트가 예시 클라이언트를 실행합니다. 각 요청에 대해 클라이언트가 예측 인스턴스 및 해당 클래스 확률을 터미널에 출력합니다. 다음은 출력의 일부를 보여줍니다.

    Sending 10 asynchronous prediction requests with 3 instances per request ...
    
    ==> Response from request #10:
    
    Instance 1:     sepal_length:   5.925825137450266
                    sepal_width:    4.5047557888651
                    petal_length:   1.0432434310300223
                    petal_width:    0.5050397721287457
    
    Prediction 1:   setosa:         0.2036041134824573
                    versicolor:     0.6062980065549213
                    virginica:      0.1900978799626214
    
    Instance 2:     sepal_length:   6.121228622484405
                    sepal_width:    3.406317728235072
                    petal_length:   3.178583759980504
                    petal_width:    2.815141143581328
    
    Prediction 2:   setosa:         0.471811302254083
                    versicolor:     0.2063720436033448
                    virginica:      0.3218166541425723
    
    Instance 3:     sepal_length:   7.005781590327274
                    sepal_width:    2.532116893508745
                    petal_length:   2.6351337947193474
                    petal_width:    2.270855223519198
    
    Prediction 3:   setosa:         0.453579051699638
                    versicolor:     0.2132869980698818
                    virginica:      0.3331339502304803
    

삭제

이 참조 구현에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

프로젝트 삭제

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

개별 리소스 삭제

  1. Cloud Shell에서 엔드포인트에서 모델을 배포 취소합니다.

    DEPLOYED_MODEL_ID=$(gcloud ai endpoints describe $ENDPOINT_ID \
        --region=$REGION \
        --format='value(deployedModels.id)')
    
    gcloud ai endpoints undeploy-model $ENDPOINT_ID \
        --region=$REGION \
        --deployed-model-id=$DEPLOYED_MODEL_ID
    
  2. 엔드포인트를 삭제합니다.

    gcloud ai endpoints delete $ENDPOINT_ID \
        --region=$REGION \
        --quiet
    
  3. 모델을 삭제합니다.

    gcloud ai models delete $MODEL_ID \
        --region=$REGION
    
  4. 제공 컨테이너 이미지를 삭제합니다.

    gcloud artifacts docker images delete \
        $LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE \
        --delete-tags \
        --quiet
    
  5. scala-sbt 빌더 컨테이너를 삭제합니다.

    gcloud container images delete gcr.io/$PROJECT_ID/scala-sbt \
        --force-delete-tags \
        --quiet
    
  6. 더 이상 필요하지 않은 Cloud Storage 버킷을 삭제합니다.

    gsutil rm -r YOUR_BUCKET_NAME
    

    버킷을 삭제하면 해당 버킷에 저장된 모든 객체도 삭제됩니다. 삭제된 버킷과 객체는 삭제 후 복구할 수 없습니다.

다음 단계