๋™์˜์ƒ ๋ถ„๋ฅ˜ ๋ชจ๋ธ์—์„œ ์˜ˆ์ธก ๊ฐ€์ ธ์˜ค๊ธฐ

์ด ํŽ˜์ด์ง€์—์„œ๋Š” Google Cloud ์ฝ˜์†” ๋˜๋Š” Vertex AI API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์˜์ƒ ๋ถ„๋ฅ˜ ๋ชจ๋ธ์—์„œ ์ผ๊ด„ ์˜ˆ์ธก์„ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ผ๊ด„ ์˜ˆ์ธก์€ ๋น„๋™๊ธฐ์‹ ์š”์ฒญ์ž…๋‹ˆ๋‹ค. ๋ชจ๋ธ์„ ์—”๋“œํฌ์ธํŠธ์— ๋ฐฐํฌํ•  ํ•„์š” ์—†์ด ๋ชจ๋ธ ๋ฆฌ์†Œ์Šค์—์„œ ์ง์ ‘ ์ผ๊ด„ ์˜ˆ์ธก์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

AutoML ๋™์˜์ƒ ๋ชจ๋ธ์€ ์˜จ๋ผ์ธ ์˜ˆ์ธก์„ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ผ๊ด„ ์˜ˆ์ธก ๊ฐ€์ ธ์˜ค๊ธฐ

์ผ๊ด„ ์˜ˆ์ธก ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด Vertex AI๊ฐ€ ์˜ˆ์ธก ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•˜๋Š” ์ž…๋ ฅ ์†Œ์Šค์™€ ์ถœ๋ ฅ ํ˜•์‹์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ž…๋ ฅ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ

์ผ๊ด„ ์š”์ฒญ์˜ ์ž…๋ ฅ์€ ์˜ˆ์ธก์„ ์œ„ํ•ด ๋ชจ๋ธ์— ๋ณด๋‚ผ ํ•ญ๋ชฉ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. AutoML ๋™์˜์ƒ ๋ชจ๋ธ ์œ ํ˜•์˜ ์ผ๊ด„ ์˜ˆ์ธก์€ JSON Lines ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ˆ์ธกํ•  ๋™์˜์ƒ ๋ชฉ๋ก์„ ์ง€์ •ํ•œ ๋‹ค์Œ JSON Lines ํŒŒ์ผ์„ Cloud Storage ๋ฒ„ํ‚ท์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. timeSegmentEnd ํ•„๋“œ์— Infinity๋ฅผ ์ง€์ •ํ•˜์—ฌ ๋™์˜์ƒ ์ข…๋ฃŒ ์ง€์ ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์ƒ˜ํ”Œ์—์„œ๋Š” ์ž…๋ ฅ JSON Lines ํŒŒ์ผ์˜ ๋‹จ์ผ ์ค„์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

{'content': 'gs://sourcebucket/datasets/videos/source_video.mp4', 'mimeType': 'video/mp4', 'timeSegmentStart': '0.0s', 'timeSegmentEnd': '2.366667s'}

๋ฐฐ์น˜ ์˜ˆ์ธก ์š”์ฒญ

์ผ๊ด„ ์˜ˆ์ธก ์š”์ฒญ์˜ ๊ฒฝ์šฐ Google Cloud ์ฝ˜์†” ๋˜๋Š” Vertex AI API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ œ์ถœํ•œ ์ž…๋ ฅ ํ•ญ๋ชฉ ์ˆ˜์— ๋”ฐ๋ผ ์ผ๊ด„ ์˜ˆ์ธก ํƒœ์Šคํฌ๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋‹ค์†Œ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Google Cloud ์ฝ˜์†”

Google Cloud ์ฝ˜์†”์„ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๊ด„ ์˜ˆ์ธก์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

  1. Google Cloud ์ฝ˜์†”์˜ Vertex AI ์„น์…˜์—์„œ ์ผ๊ด„ ์˜ˆ์ธก ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    ์ผ๊ด„ ์˜ˆ์ธก ํŽ˜์ด์ง€๋กœ ์ด๋™

  2. ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ƒˆ ์ผ๊ด„ ์˜ˆ์ธก ์ฐฝ์„ ์—ด๊ณ  ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

    1. ์ผ๊ด„ ์˜ˆ์ธก์˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    2. ๋ชจ๋ธ ์ด๋ฆ„์—์„œ ์ด ์ผ๊ด„ ์˜ˆ์ธก์— ์‚ฌ์šฉํ•  ๋ชจ๋ธ์˜ ์ด๋ฆ„์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    3. ์†Œ์Šค ๊ฒฝ๋กœ์—์„œ JSON Lines ์ž…๋ ฅ ํŒŒ์ผ์ด ์žˆ๋Š” Cloud Storage ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
    4. ๋Œ€์ƒ ๊ฒฝ๋กœ์—์„œ ์ผ๊ด„ ์˜ˆ์ธก ๊ฒฐ๊ณผ๊ฐ€ ์ €์žฅ๋˜๋Š” Cloud Storage ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ถœ๋ ฅ ํ˜•์‹์€ ๋ชจ๋ธ์˜ ๋ชฉํ‘œ์— ๋”ฐ๋ผ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ ๋ชฉํ‘œ์˜ AutoML ๋ชจ๋ธ์€ JSON Lines ํŒŒ์ผ์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

API

Vertex AI API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๊ด„ ์˜ˆ์ธก ์š”์ฒญ์„ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

REST

์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  • LOCATION_ID: ๋ชจ๋ธ์ด ์ €์žฅ๋˜๊ณ  ์ผ๊ด„ ์˜ˆ์ธก ์ž‘์—…์ด ์‹คํ–‰๋˜๋Š” ๋ฆฌ์ „์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด us-central1์ž…๋‹ˆ๋‹ค.
  • PROJECT_ID: ํ”„๋กœ์ ํŠธ ID์ž…๋‹ˆ๋‹ค.
  • BATCH_JOB_NAME: ์ผ๊ด„ ์ž‘์—…์˜ ํ‘œ์‹œ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
  • MODEL_ID: ์˜ˆ์ธก์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ๋ชจ๋ธ์˜ ID์ž…๋‹ˆ๋‹ค.
  • THRESHOLD_VALUE(์„ ํƒ์‚ฌํ•ญ): ๋ชจ๋ธ์€ ์‹ ๋ขฐ๋„๊ฐ€ ์ด ๊ฐ’ ์ด์ƒ์ธ ์˜ˆ์ธก๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • SEGMENT_CLASSIFICATION (์„ ํƒ์‚ฌํ•ญ): ์„ธ๊ทธ๋จผํŠธ ์ˆ˜์ค€ ๋ถ„๋ฅ˜๋ฅผ ์š”์ฒญํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์ž…๋‹ˆ๋‹ค. Vertex AI๋Š” ์ž…๋ ฅ ์ธ์Šคํ„ด์Šค์—์„œ ์ง€์ •ํ•œ ๋™์˜์ƒ์˜ ์ „์ฒด ์‹œ๊ฐ„ ์„ธ๊ทธ๋จผํŠธ์˜ ๋ผ๋ฒจ๊ณผ ์‹ ๋ขฐ๋„ ์ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ true์ž…๋‹ˆ๋‹ค.
  • SHOT_CLASSIFICATION (์„ ํƒ์‚ฌํ•ญ): ์žฅ๋ฉด ์ˆ˜์ค€ ๋ถ„๋ฅ˜๋ฅผ ์š”์ฒญํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์ž…๋‹ˆ๋‹ค. Vertex AI๋Š” ์ž…๋ ฅ ์ธ์Šคํ„ด์Šค์—์„œ ์ง€์ •ํ•œ ๋™์˜์ƒ์˜ ์ „์ฒด ์‹œ๊ฐ„ ์„ธ๊ทธ๋จผํŠธ์˜ ๊ฐ ์นด๋ฉ”๋ผ ์ƒท์˜ ๊ฒฝ๊ณ„๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ Vertex AI๋Š” ๊ฐ์ง€๋œ ๊ฐ ์žฅ๋ฉด์˜ ๋ผ๋ฒจ๊ณผ ์‹ ๋ขฐ๋„ ์ ์ˆ˜๋ฅผ ์žฅ๋ฉด์˜ ์‹œ์ž‘ ๋ฐ ์ข…๋ฃŒ ์‹œ๊ฐ„๊ณผ ํ•จ๊ป˜ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ false์ž…๋‹ˆ๋‹ค.
  • ONE_SEC_INTERVAL_CLASSIFICATION(์„ ํƒ์‚ฌํ•ญ): 1์ดˆ ๊ฐ„๊ฒฉ์œผ๋กœ ๋™์˜์ƒ ๋ถ„๋ฅ˜๋ฅผ ์š”์ฒญํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถˆ๋ฆฌ์–ธ ๊ฐ’์ž…๋‹ˆ๋‹ค. Vertex AI๋Š” ์ž…๋ ฅ ์ธ์Šคํ„ด์Šค์—์„œ ์ง€์ •ํ•œ ๋™์˜์ƒ์˜ ์ „์ฒด ์‹œ๊ฐ„ ์„ธ๊ทธ๋จผํŠธ์˜ ์ดˆ๋‹น ๋ผ๋ฒจ๊ณผ ์‹ ๋ขฐ๋„ ์ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ false์ž…๋‹ˆ๋‹ค.
  • URI: ์ž…๋ ฅ JSON Lines ํŒŒ์ผ์ด ์žˆ๋Š” Cloud Storage URI
  • BUCKET: Cloud Storage ๋ฒ„ํ‚ท
  • PROJECT_NUMBER: ํ”„๋กœ์ ํŠธ์˜ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ํ”„๋กœ์ ํŠธ ๋ฒˆํ˜ธ

HTTP ๋ฉ”์„œ๋“œ ๋ฐ URL:

POST https://LOCATION_ID-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION_ID/batchPredictionJobs

JSON ์š”์ฒญ ๋ณธ๋ฌธ:

{
    "displayName": "BATCH_JOB_NAME",
    "model": "projects/PROJECT_ID/locations/LOCATION_ID/models/MODEL_ID",
    "modelParameters": {
      "confidenceThreshold": THRESHOLD_VALUE,
      "segmentClassification": SEGMENT_CLASSIFICATION,
      "shotClassification": SHOT_CLASSIFICATION,
      "oneSecIntervalClassification": ONE_SEC_INTERVAL_CLASSIFICATION
    },
    "inputConfig": {
        "instancesFormat": "jsonl",
        "gcsSource": {
            "uris": ["URI"],
        },
    },
    "outputConfig": {
        "predictionsFormat": "jsonl",
        "gcsDestination": {
            "outputUriPrefix": "OUTPUT_BUCKET",
        },
    },
}

์š”์ฒญ์„ ๋ณด๋‚ด๋ ค๋ฉด ๋‹ค์Œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

curl

์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://LOCATION_ID-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION_ID/batchPredictionJobs"

PowerShell

์š”์ฒญ ๋ณธ๋ฌธ์„ request.json ํŒŒ์ผ์— ์ €์žฅํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://LOCATION_ID-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION_ID/batchPredictionJobs" | Select-Object -Expand Content

๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ JSON ์‘๋‹ต์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

{
  "name": "projects/PROJECT_NUMBER/locations/us-central1/batchPredictionJobs/BATCH_JOB_ID",
  "displayName": "BATCH_JOB_NAME",
  "model": "projects/PROJECT_NUMBER/locations/us-central1/models/MODEL_ID",
  "inputConfig": {
    "instancesFormat": "jsonl",
    "gcsSource": {
      "uris": [
        "CONTENT"
      ]
    }
  },
  "outputConfig": {
    "predictionsFormat": "jsonl",
    "gcsDestination": {
      "outputUriPrefix": "BUCKET"
    }
  },
  "state": "JOB_STATE_PENDING",
  "createTime": "2020-05-30T02:58:44.341643Z",
  "updateTime": "2020-05-30T02:58:44.341643Z",
  "modelDisplayName": "MODEL_NAME",
  "modelObjective": "MODEL_OBJECTIVE"
}

์ž‘์—… state๊ฐ€ JOB_STATE_SUCCEEDED๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ BATCH_JOB_ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ๊ด„ ์ž‘์—…์˜ ์ƒํƒœ๋ฅผ ํด๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Java

์ด ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ ์ „์— Vertex AI ๋น ๋ฅธ ์‹œ์ž‘: ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์˜ Java ์„ค์ • ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Vertex AI Java API ์ฐธ๊ณ  ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Vertex AI์— ์ธ์ฆํ•˜๋ ค๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์˜ ์ธ์ฆ ์„ค์ •์„ ์ฐธ์กฐํ•˜์„ธ์š”.


import com.google.cloud.aiplatform.util.ValueConverter;
import com.google.cloud.aiplatform.v1.BatchDedicatedResources;
import com.google.cloud.aiplatform.v1.BatchPredictionJob;
import com.google.cloud.aiplatform.v1.BatchPredictionJob.InputConfig;
import com.google.cloud.aiplatform.v1.BatchPredictionJob.OutputConfig;
import com.google.cloud.aiplatform.v1.BatchPredictionJob.OutputInfo;
import com.google.cloud.aiplatform.v1.BigQueryDestination;
import com.google.cloud.aiplatform.v1.BigQuerySource;
import com.google.cloud.aiplatform.v1.CompletionStats;
import com.google.cloud.aiplatform.v1.GcsDestination;
import com.google.cloud.aiplatform.v1.GcsSource;
import com.google.cloud.aiplatform.v1.JobServiceClient;
import com.google.cloud.aiplatform.v1.JobServiceSettings;
import com.google.cloud.aiplatform.v1.LocationName;
import com.google.cloud.aiplatform.v1.MachineSpec;
import com.google.cloud.aiplatform.v1.ManualBatchTuningParameters;
import com.google.cloud.aiplatform.v1.ModelName;
import com.google.cloud.aiplatform.v1.ResourcesConsumed;
import com.google.cloud.aiplatform.v1.schema.predict.params.VideoClassificationPredictionParams;
import com.google.protobuf.Any;
import com.google.protobuf.Value;
import com.google.rpc.Status;
import java.io.IOException;
import java.util.List;

public class CreateBatchPredictionJobVideoClassificationSample {

  public static void main(String[] args) throws IOException {
    String batchPredictionDisplayName = "YOUR_VIDEO_CLASSIFICATION_DISPLAY_NAME";
    String modelId = "YOUR_MODEL_ID";
    String gcsSourceUri =
        "gs://YOUR_GCS_SOURCE_BUCKET/path_to_your_video_source/[file.csv/file.jsonl]";
    String gcsDestinationOutputUriPrefix =
        "gs://YOUR_GCS_SOURCE_BUCKET/destination_output_uri_prefix/";
    String project = "YOUR_PROJECT_ID";
    createBatchPredictionJobVideoClassification(
        batchPredictionDisplayName, modelId, gcsSourceUri, gcsDestinationOutputUriPrefix, project);
  }

  static void createBatchPredictionJobVideoClassification(
      String batchPredictionDisplayName,
      String modelId,
      String gcsSourceUri,
      String gcsDestinationOutputUriPrefix,
      String project)
      throws IOException {
    JobServiceSettings jobServiceSettings =
        JobServiceSettings.newBuilder()
            .setEndpoint("us-central1-aiplatform.googleapis.com:443")
            .build();

    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (JobServiceClient jobServiceClient = JobServiceClient.create(jobServiceSettings)) {
      String location = "us-central1";
      LocationName locationName = LocationName.of(project, location);

      VideoClassificationPredictionParams modelParamsObj =
          VideoClassificationPredictionParams.newBuilder()
              .setConfidenceThreshold(((float) 0.5))
              .setMaxPredictions(10000)
              .setSegmentClassification(true)
              .setShotClassification(true)
              .setOneSecIntervalClassification(true)
              .build();

      Value modelParameters = ValueConverter.toValue(modelParamsObj);

      ModelName modelName = ModelName.of(project, location, modelId);
      GcsSource.Builder gcsSource = GcsSource.newBuilder();
      gcsSource.addUris(gcsSourceUri);
      InputConfig inputConfig =
          InputConfig.newBuilder().setInstancesFormat("jsonl").setGcsSource(gcsSource).build();

      GcsDestination gcsDestination =
          GcsDestination.newBuilder().setOutputUriPrefix(gcsDestinationOutputUriPrefix).build();
      OutputConfig outputConfig =
          OutputConfig.newBuilder()
              .setPredictionsFormat("jsonl")
              .setGcsDestination(gcsDestination)
              .build();

      BatchPredictionJob batchPredictionJob =
          BatchPredictionJob.newBuilder()
              .setDisplayName(batchPredictionDisplayName)
              .setModel(modelName.toString())
              .setModelParameters(modelParameters)
              .setInputConfig(inputConfig)
              .setOutputConfig(outputConfig)
              .build();
      BatchPredictionJob batchPredictionJobResponse =
          jobServiceClient.createBatchPredictionJob(locationName, batchPredictionJob);

      System.out.println("Create Batch Prediction Job Video Classification Response");
      System.out.format("\tName: %s\n", batchPredictionJobResponse.getName());
      System.out.format("\tDisplay Name: %s\n", batchPredictionJobResponse.getDisplayName());
      System.out.format("\tModel %s\n", batchPredictionJobResponse.getModel());
      System.out.format(
          "\tModel Parameters: %s\n", batchPredictionJobResponse.getModelParameters());

      System.out.format("\tState: %s\n", batchPredictionJobResponse.getState());
      System.out.format("\tCreate Time: %s\n", batchPredictionJobResponse.getCreateTime());
      System.out.format("\tStart Time: %s\n", batchPredictionJobResponse.getStartTime());
      System.out.format("\tEnd Time: %s\n", batchPredictionJobResponse.getEndTime());
      System.out.format("\tUpdate Time: %s\n", batchPredictionJobResponse.getUpdateTime());
      System.out.format("\tLabels: %s\n", batchPredictionJobResponse.getLabelsMap());

      InputConfig inputConfigResponse = batchPredictionJobResponse.getInputConfig();
      System.out.println("\tInput Config");
      System.out.format("\t\tInstances Format: %s\n", inputConfigResponse.getInstancesFormat());

      GcsSource gcsSourceResponse = inputConfigResponse.getGcsSource();
      System.out.println("\t\tGcs Source");
      System.out.format("\t\t\tUris %s\n", gcsSourceResponse.getUrisList());

      BigQuerySource bigQuerySource = inputConfigResponse.getBigquerySource();
      System.out.println("\t\tBigquery Source");
      System.out.format("\t\t\tInput_uri: %s\n", bigQuerySource.getInputUri());

      OutputConfig outputConfigResponse = batchPredictionJobResponse.getOutputConfig();
      System.out.println("\tOutput Config");
      System.out.format(
          "\t\tPredictions Format: %s\n", outputConfigResponse.getPredictionsFormat());

      GcsDestination gcsDestinationResponse = outputConfigResponse.getGcsDestination();
      System.out.println("\t\tGcs Destination");
      System.out.format(
          "\t\t\tOutput Uri Prefix: %s\n", gcsDestinationResponse.getOutputUriPrefix());

      BigQueryDestination bigQueryDestination = outputConfigResponse.getBigqueryDestination();
      System.out.println("\t\tBig Query Destination");
      System.out.format("\t\t\tOutput Uri: %s\n", bigQueryDestination.getOutputUri());

      BatchDedicatedResources batchDedicatedResources =
          batchPredictionJobResponse.getDedicatedResources();
      System.out.println("\tBatch Dedicated Resources");
      System.out.format(
          "\t\tStarting Replica Count: %s\n", batchDedicatedResources.getStartingReplicaCount());
      System.out.format(
          "\t\tMax Replica Count: %s\n", batchDedicatedResources.getMaxReplicaCount());

      MachineSpec machineSpec = batchDedicatedResources.getMachineSpec();
      System.out.println("\t\tMachine Spec");
      System.out.format("\t\t\tMachine Type: %s\n", machineSpec.getMachineType());
      System.out.format("\t\t\tAccelerator Type: %s\n", machineSpec.getAcceleratorType());
      System.out.format("\t\t\tAccelerator Count: %s\n", machineSpec.getAcceleratorCount());

      ManualBatchTuningParameters manualBatchTuningParameters =
          batchPredictionJobResponse.getManualBatchTuningParameters();
      System.out.println("\tManual Batch Tuning Parameters");
      System.out.format("\t\tBatch Size: %s\n", manualBatchTuningParameters.getBatchSize());

      OutputInfo outputInfo = batchPredictionJobResponse.getOutputInfo();
      System.out.println("\tOutput Info");
      System.out.format("\t\tGcs Output Directory: %s\n", outputInfo.getGcsOutputDirectory());
      System.out.format("\t\tBigquery Output Dataset: %s\n", outputInfo.getBigqueryOutputDataset());

      Status status = batchPredictionJobResponse.getError();
      System.out.println("\tError");
      System.out.format("\t\tCode: %s\n", status.getCode());
      System.out.format("\t\tMessage: %s\n", status.getMessage());
      List<Any> details = status.getDetailsList();

      for (Status partialFailure : batchPredictionJobResponse.getPartialFailuresList()) {
        System.out.println("\tPartial Failure");
        System.out.format("\t\tCode: %s\n", partialFailure.getCode());
        System.out.format("\t\tMessage: %s\n", partialFailure.getMessage());
        List<Any> partialFailureDetailsList = partialFailure.getDetailsList();
      }

      ResourcesConsumed resourcesConsumed = batchPredictionJobResponse.getResourcesConsumed();
      System.out.println("\tResources Consumed");
      System.out.format("\t\tReplica Hours: %s\n", resourcesConsumed.getReplicaHours());

      CompletionStats completionStats = batchPredictionJobResponse.getCompletionStats();
      System.out.println("\tCompletion Stats");
      System.out.format("\t\tSuccessful Count: %s\n", completionStats.getSuccessfulCount());
      System.out.format("\t\tFailed Count: %s\n", completionStats.getFailedCount());
      System.out.format("\t\tIncomplete Count: %s\n", completionStats.getIncompleteCount());
    }
  }
}

Node.js

์ด ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ ์ „์— Vertex AI ๋น ๋ฅธ ์‹œ์ž‘: ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์˜ Node.js ์„ค์ • ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Vertex AI Node.js API ์ฐธ๊ณ  ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Vertex AI์— ์ธ์ฆํ•˜๋ ค๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์˜ ์ธ์ฆ ์„ค์ •์„ ์ฐธ์กฐํ•˜์„ธ์š”.

/**
 * TODO(developer): Uncomment these variables before running the sample.\
 * (Not necessary if passing values as arguments)
 */

// const batchPredictionDisplayName = 'YOUR_BATCH_PREDICTION_DISPLAY_NAME';
// const modelId = 'YOUR_MODEL_ID';
// const gcsSourceUri = 'YOUR_GCS_SOURCE_URI';
// const gcsDestinationOutputUriPrefix = 'YOUR_GCS_DEST_OUTPUT_URI_PREFIX';
//    eg. "gs://<your-gcs-bucket>/destination_path"
// const project = 'YOUR_PROJECT_ID';
// const location = 'YOUR_PROJECT_LOCATION';
const aiplatform = require('@google-cloud/aiplatform');
const {params} = aiplatform.protos.google.cloud.aiplatform.v1.schema.predict;

// Imports the Google Cloud Job Service Client library
const {JobServiceClient} = require('@google-cloud/aiplatform').v1;

// Specifies the location of the api endpoint
const clientOptions = {
  apiEndpoint: 'us-central1-aiplatform.googleapis.com',
};

// Instantiates a client
const jobServiceClient = new JobServiceClient(clientOptions);

async function createBatchPredictionJobVideoClassification() {
  // Configure the parent resource
  const parent = `projects/${project}/locations/${location}`;
  const modelName = `projects/${project}/locations/${location}/models/${modelId}`;

  // For more information on how to configure the model parameters object, see
  // https://cloud.google.com/ai-platform-unified/docs/predictions/batch-predictions
  const modelParamsObj = new params.VideoClassificationPredictionParams({
    confidenceThreshold: 0.5,
    maxPredictions: 1000,
    segmentClassification: true,
    shotClassification: true,
    oneSecIntervalClassification: true,
  });

  const modelParameters = modelParamsObj.toValue();

  const inputConfig = {
    instancesFormat: 'jsonl',
    gcsSource: {uris: [gcsSourceUri]},
  };
  const outputConfig = {
    predictionsFormat: 'jsonl',
    gcsDestination: {outputUriPrefix: gcsDestinationOutputUriPrefix},
  };
  const batchPredictionJob = {
    displayName: batchPredictionDisplayName,
    model: modelName,
    modelParameters,
    inputConfig,
    outputConfig,
  };
  const request = {
    parent,
    batchPredictionJob,
  };

  // Create batch prediction job request
  const [response] = await jobServiceClient.createBatchPredictionJob(request);

  console.log('Create batch prediction job video classification response');
  console.log(`Name : ${response.name}`);
  console.log('Raw response:');
  console.log(JSON.stringify(response, null, 2));
}
createBatchPredictionJobVideoClassification();

Python์šฉ Vertex AI SDK

Python์šฉ Vertex AI SDK๋ฅผ ์„ค์น˜ํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์€ Python์šฉ Vertex AI SDK ์„ค์น˜๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Python์šฉ Vertex AI SDK API ์ฐธ์กฐ ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

def create_batch_prediction_job_sample(
    project: str,
    location: str,
    model_resource_name: str,
    job_display_name: str,
    gcs_source: Union[str, Sequence[str]],
    gcs_destination: str,
    sync: bool = True,
):
    aiplatform.init(project=project, location=location)

    my_model = aiplatform.Model(model_resource_name)

    batch_prediction_job = my_model.batch_predict(
        job_display_name=job_display_name,
        gcs_source=gcs_source,
        gcs_destination_prefix=gcs_destination,
        sync=sync,
    )

    batch_prediction_job.wait()

    print(batch_prediction_job.display_name)
    print(batch_prediction_job.resource_name)
    print(batch_prediction_job.state)
    return batch_prediction_job

์ผ๊ด„ ์˜ˆ์ธก ๊ฒฐ๊ณผ ๊ฒ€์ƒ‰

Vertex AI๋Š” ์ง€์ •๋œ ๋Œ€์ƒ์— ์ผ๊ด„ ์˜ˆ์ธก ์ถœ๋ ฅ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

์ผ๊ด„ ์˜ˆ์ธก ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์š”์ฒญ์— ์ง€์ •ํ•œ Cloud Storage ๋ฒ„ํ‚ท์— ์˜ˆ์ธก ๊ฒฐ๊ณผ๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

์ผ๊ด„ ์˜ˆ์ธก ๊ฒฐ๊ณผ ์˜ˆ์‹œ

๋‹ค์Œ์€ ๋™์˜์ƒ ๋ถ„๋ฅ˜ ๋ชจ๋ธ์˜ ์ผ๊ด„ ์˜ˆ์ธก ๊ฒฐ๊ณผ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

{
  "instance": {
   "content": "gs://bucket/video.mp4",
    "mimeType": "video/mp4",
    "timeSegmentStart": "1s",
    "timeSegmentEnd": "5s"
  }
  "prediction": [{
    "id": "1",
    "displayName": "cat",
    "type": "segment-classification",
    "timeSegmentStart": "1s",
    "timeSegmentEnd": "5s",
    "confidence": 0.7
  }, {
    "id": "1",
    "displayName": "cat",
    "type": "shot-classification",
    "timeSegmentStart": "1s",
    "timeSegmentEnd": "4s",
    "confidence": 0.9
  }, {
    "id": "2",
    "displayName": "dog",
    "type": "shot-classification",
    "timeSegmentStart": "4s",
    "timeSegmentEnd": "5s",
    "confidence": 0.6
  }, {
    "id": "1",
    "displayName": "cat",
    "type": "one-sec-interval-classification",
    "timeSegmentStart": "1s",
    "timeSegmentEnd": "1s",
    "confidence": 0.95
  }, {
    "id": "1",
    "displayName": "cat",
    "type": "one-sec-interval-classification",
    "timeSegmentStart": "2s",
    "timeSegmentEnd": "2s",
    "confidence": 0.9
  }, {
    "id": "1",
    "displayName": "cat",
    "type": "one-sec-interval-classification",
    "timeSegmentStart": "3s",
    "timeSegmentEnd": "3s",
    "confidence": 0.85
  }, {
    "id": "2",
    "displayName": "dog",
    "type": "one-sec-interval-classification",
    "timeSegmentStart": "4s",
    "timeSegmentEnd": "4s",
    "confidence": 0.6
  }]
}