์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช… ๊ตฌ์„ฑ

์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช…์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Model ๋ฆฌ์†Œ์Šค๋ฅผ Model Registry์— ๊ฐ€์ ธ์˜ฌ ๋•Œ explanationSpec์„ ์ง€์ •ํ•˜์—ฌ ์„ค๋ช…์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์˜จ๋ผ์ธ ์„ค๋ช…์„ ์š”์ฒญํ•  ๋•Œ ์š”์ฒญ์— ExplanationSpecOverride๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ตฌ์„ฑ๊ฐ’์˜ ์ผ๋ถ€๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๊ด„ ์„ค๋ช…์€ ์ง€์›๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์š”์ฒญํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€์—์„œ๋Š” ์ด๋Ÿฌํ•œ ์˜ต์…˜์„ ๊ตฌ์„ฑํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋ธ์„ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ์—…๋กœ๋“œํ•  ๋•Œ ์„ค๋ช… ๊ตฌ์„ฑ

์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋‹ค์Œ ์‚ฌํ•ญ์„ ํ™•์ธํ•˜์„ธ์š”.

  1. ๋ชจ๋ธ ์•„ํ‹ฐํŒฉํŠธ๊ฐ€ ํฌํ•จ๋œ Cloud Storage ์œ„์น˜๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ธ์€ ๋ ˆ์ด์–ด ์ด๋ฆ„์„ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ์ถœ๋ ฅ์„ ์ž ์žฌ ๊ณต๊ฐ„์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋ช…์„ ์ œ๊ณตํ•˜๋Š” ์‹ฌ์ธต์‹ ๊ฒฝ๋ง(DNN)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์ž„๋ฒ ๋”ฉ(์ž ์žฌ ๊ณต๊ฐ„ ํ‘œํ˜„)์„ ์ง์ ‘ ์ถœ๋ ฅํ•˜๋Š” ๋ชจ๋ธ์„ ์ œ๊ณตํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์ด ์ž ์žฌ ๊ณต๊ฐ„์€ ์„ค๋ช…์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์˜ˆ์‹œ ํ‘œํ˜„์„ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค.

  2. ์ตœ๊ทผ์ ‘ ์ด์›ƒ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ์ƒ‰์ธ์„ ์ƒ์„ฑํ•  ์ธ์Šคํ„ด์Šค๊ฐ€ ํฌํ•จ๋œ Cloud Storage ์œ„์น˜๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ž…๋ ฅ ๋ฐ์ดํ„ฐ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์ฝ˜์†”

Google Cloud ์ฝ˜์†”์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋ธ ๊ฐ€์ ธ์˜ค๊ธฐ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

์„ค๋ช… ๊ธฐ๋Šฅ ํƒญ์—์„œ ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช…์„ ์„ ํƒํ•˜๊ณ  ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

๊ฐ ํ•„๋“œ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Google Cloud ์ฝ˜์†”(์•„๋ž˜ ์ฐธ์กฐ)์˜ ํŒ๊ณผ Example ๋ฐ ExplanationMetadata์˜ ์ฐธ๊ณ  ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.

์„ค๋ช… ๊ธฐ๋Šฅ ํƒญ์— ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์ด ํ‘œ์‹œ๋œ ์ฝ˜์†”์˜ ๋ชจ๋ธ ๊ฐ€์ ธ์˜ค๊ธฐ ํ™”๋ฉด

gcloud CLI

  1. ๋‹ค์Œ ExplanationMetadata๋ฅผ ๋กœ์ปฌ ํ™˜๊ฒฝ์˜ JSON ํŒŒ์ผ์— ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ํŒŒ์ผ ์ด๋ฆ„์€ ์ค‘์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ํŒŒ์ผ ์ด๋ฆ„์„ explanation-metadata.json์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
{
  "inputs": {
    "my_input": {
      "inputTensorName": "INPUT_TENSOR_NAME",
      "encoding": "IDENTITY",
    },
    "id": {
      "inputTensorName": "id",
      "encoding": "IDENTITY"
    }
  },
  "outputs": {
    "embedding": {
      "outputTensorName": "OUTPUT_TENSOR_NAME"
    }
  }
}
  1. (์„ ํƒ์‚ฌํ•ญ) ์ „์ฒด NearestNeighborSearchConfig๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ๋กœ์ปฌ ํ™˜๊ฒฝ์˜ JSON ํŒŒ์ผ์— ๋‹ค์Œ์„ ์”๋‹ˆ๋‹ค. ํŒŒ์ผ ์ด๋ฆ„์€ ์ค‘์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ์ด ์˜ˆ์‹œ์—์„œ๋Š” ํŒŒ์ผ ์ด๋ฆ„์„ search_config.json์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
{
  "contentsDeltaUri": "",
  "config": {
      "dimensions": 50,
      "approximateNeighborsCount": 10,
      "distanceMeasureType": "SQUARED_L2_DISTANCE",
      "featureNormType": "NONE",
      "algorithmConfig": {
          "treeAhConfig": {
              "leafNodeEmbeddingCount": 1000,
              "fractionLeafNodesToSearch": 1.0
          }
      }
    }
  }
  1. ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์—ฌ Model์„ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

Preset ๊ฒ€์ƒ‰ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ --explanation-nearest-neighbor-search-config-file ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ญ์ œํ•˜์„ธ์š”. NearestNeighborSearchConfig๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒฝ์šฐ --explanation-modality ๋ฐ --explanation-query ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช…๊ณผ ๊ฐ€์žฅ ๊ด€๋ จ์„ฑ์ด ๋†’์€ ํ”Œ๋ž˜๊ทธ๋Š” ๊ตต๊ฒŒ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

gcloud ai models upload \
    --region=LOCATION \
    --display-name=MODEL_NAME \
    --container-image-uri=IMAGE_URI \
    --artifact-uri=MODEL_ARTIFACT_URI \
    --explanation-method=examples \
    --uris=[URI, ...] \
    --explanation-neighbor-count=NEIGHBOR_COUNT \
    --explanation-metadata-file=explanation-metadata.json \
    --explanation-modality=IMAGE|TEXT|TABULAR \
    --explanation-query=PRECISE|FAST \
    --explanation-nearest-neighbor-search-config-file=search_config.json

์ž์„ธํ•œ ๋‚ด์šฉ์€ gcloud ai ๋ชจ๋ธ ์—…๋กœ๋“œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  1. ์—…๋กœ๋“œ ์ž‘์—…์—์„œ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” OPERATION_ID๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์— "done": true๊ฐ€ ํฌํ•จ๋  ๋•Œ๊นŒ์ง€ ์ž‘์—… ์ƒํƒœ๋ฅผ ํด๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. gcloud ai operations describe ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ํด๋งํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    gcloud ai operations describe <operation-id>
    

    ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์„ค๋ช…์„ ์š”์ฒญํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋ฐ ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ด ๋‹จ๊ณ„๋Š” ์˜ˆ์‹œ์˜ ์ฟผ๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ์ƒ‰์ธ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

REST

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

  • PROJECT
  • LOCATION

๋‹ค๋ฅธ ์ž๋ฆฌํ‘œ์‹œ์ž์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋ ค๋ฉด Model, explanationSpec, Examples์„ ์ฐธ์กฐํ•˜์„ธ์š”ใ…—.

๋ชจ๋ธ ์—…๋กœ๋“œ์— ๋Œ€ํ•œ ์ƒ์„ธ ์„ค๋ช…์€ upload ๋ฉ”์„œ๋“œ์™€ ๋ชจ๋ธ ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์•„๋ž˜ JSON ์š”์ฒญ ๋ณธ๋ฌธ์€ Preset ๊ฒ€์ƒ‰ ๊ตฌ์„ฑ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์ „์ฒด NearestNeighborSearchConfig๋ฅผ ์ง€์ •ํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค.

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

POST https://LOCATION-aiplatform.googleapis.com/v1/projects/PROJECT/locations/LOCATION/models:upload

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

{
  "model": {
    "displayName": "my-model",
    "artifactUri": "gs://your-model-artifact-folder",
    "containerSpec": {
      "imageUri": "us-docker.pkg.dev/vertex-ai/prediction/tf2-cpu.2-11:latest",
    },
    "explanationSpec": {
      "parameters": {
        "examples": {
          "gcsSource": {
            "uris": ["gs://your-examples-folder"]
          },
          "neighborCount": 10,
          "presets": {
            "modality": "image"
          }
        }
      },
      "metadata": {
        "outputs": {
            "embedding": {
                "output_tensor_name": "embedding"
            }
        },
        "inputs": {
          "my_fancy_input": {
            "input_tensor_name": "input_tensor_name",
            "encoding": "identity",
            "modality": "image"
          },
          "id": {
            "input_tensor_name": "id",
            "encoding": "identity"
          }
        }
      }
    }
  }
}

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

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

{
  "name": "projects/PROJECT_NUMBER/locations/LOCATION/models/MODEL_ID/operations/OPERATION_ID",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.aiplatform.v1.UploadModelOperationMetadata",
    "genericMetadata": {
      "createTime": "2022-01-08T01:21:10.147035Z",
      "updateTime": "2022-01-08T01:21:10.147035Z"
    }
  }
}

์—…๋กœ๋“œ ์ž‘์—…์—์„œ ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” OPERATION_ID๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์‘๋‹ต์— "done": true๊ฐ€ ํฌํ•จ๋  ๋•Œ๊นŒ์ง€ ์ž‘์—… ์ƒํƒœ๋ฅผ ํด๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. gcloud ai operations describe ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํƒœ๋ฅผ ํด๋งํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

gcloud ai operations describe <operation-id>

์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์„ค๋ช…์„ ์š”์ฒญํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋ฐ ๋ชจ๋ธ ์•„ํ‚คํ…์ฒ˜์˜ ํฌ๊ธฐ์— ๋”ฐ๋ผ ์ด ๋‹จ๊ณ„๋Š” ์˜ˆ์‹œ์˜ ์ฟผ๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ์ƒ‰์ธ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Python

์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช… ๋…ธํŠธ๋ถ์—์„œ ๋ชจ๋ธ ์—…๋กœ๋“œ ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

NearestNeighborSearchConfig

๋‹ค์Œ JSON ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ๋Š” upload ์š”์ฒญ์—์„œ ์‚ฌ์ „ ์„ค์ • ๋Œ€์‹  ์ „์ฒด NearestNeighborSearchConfig๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

{
  "model": {
    "displayName": displayname,
    "artifactUri": model_path_to_deploy,
    "containerSpec": {
      "imageUri": DEPLOY_IMAGE,
    },
    "explanationSpec": {
      "parameters": {
        "examples": {
          "gcsSource": {
            "uris": [DATASET_PATH]
          },
          "neighborCount": 5,
          "nearest_neighbor_search_config": {
            "contentsDeltaUri": "",
            "config": {
              "dimensions": dimensions,
              "approximateNeighborsCount": 10,
              "distanceMeasureType": "SQUARED_L2_DISTANCE",
              "featureNormType": "NONE",
              "algorithmConfig": {
                  "treeAhConfig": {
                      "leafNodeEmbeddingCount": 1000,
                      "fractionLeafNodesToSearch": 1.0
                  }
                }
              }
          }
        }
      },
      "metadata": { ... }
    }
  }
}

์•„๋ž˜ ํ‘œ์—๋Š” NearestNeighborSearchConfig์˜ ํ•„๋“œ๊ฐ€ ๋‚˜์—ด๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„๋“œ
dimensions

int32

ํ•„์ˆ˜ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค. ์ž…๋ ฅ ๋ฒกํ„ฐ์˜ ์ฐจ์› ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋ฐ€์ง‘ ์ž„๋ฒ ๋”ฉ์—๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

approximateNeighborsCount

int32

tree-AH ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

์ •ํ™•ํ•œ ์ˆœ์„œ ๋ณ€๊ฒฝ์ด ์ˆ˜ํ–‰๋˜๊ธฐ ์ „์— ์œ ์‚ฌ ๊ฒ€์ƒ‰์„ ํ†ตํ•ด ์ฐพ์„ ์ด์›ƒ์˜ ๊ธฐ๋ณธ ๊ฐœ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ •ํ™•ํ•œ ์ˆœ์„œ ๋ณ€๊ฒฝ์€ ์œ ์‚ฌ ๊ฒ€์ƒ‰ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋น„์šฉ์ด ๋” ๋งŽ์ด ๋“œ๋Š” ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ์„ ์ด์šฉํ•ด ์žฌ์ •๋ ฌ๋˜๋Š” ์ ˆ์ฐจ์ž…๋‹ˆ๋‹ค.

ShardSize ShardSize

๊ฐ ์ƒค๋“œ์˜ ํฌ๊ธฐ. ์ƒ‰์ธ์ด ํฌ๋ฉด ์ง€์ •๋œ ์ƒค๋“œ ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ƒค๋”ฉ๋ฉ๋‹ˆ๋‹ค. ์„œ๋น™ ์ค‘์— ๊ฐ ์ƒค๋“œ๋Š” ๋ณ„๋„์˜ ๋…ธ๋“œ์—์„œ ์ œ๊ณต๋˜๋ฉฐ ๋…๋ฆฝ์ ์œผ๋กœ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.

distanceMeasureType

DistanceMeasureType

์ตœ๊ทผ์ ‘ ์ด์›ƒ ๊ฒ€์ƒ‰์— ์‚ฌ์šฉ๋˜๋Š” ๊ฑฐ๋ฆฌ ์ธก์ •์ž…๋‹ˆ๋‹ค.

featureNormType

FeatureNormType

๊ฐ ๋ฒกํ„ฐ์—์„œ ์ˆ˜ํ–‰๋  ์ •๊ทœํ™” ์œ ํ˜•์ž…๋‹ˆ๋‹ค.

algorithmConfig oneOf:

๋ฒกํ„ฐ ๊ฒ€์ƒ‰์—์„œ ํšจ์œจ์ ์ธ ๊ฒ€์ƒ‰์— ์‚ฌ์šฉํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๊ตฌ์„ฑ์ž…๋‹ˆ๋‹ค. ๋ฐ€์ง‘ ์ž„๋ฒ ๋”ฉ์—๋งŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • TreeAhConfig: tree-AH ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์„ฑ ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ TensorFlow ์ถ”์ฒœ์ž ๋ฐ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰์œผ๋กœ ์‹ฌ์ธต ๊ฒ€์ƒ‰ ํ™•์žฅ ๋ธ”๋กœ๊ทธ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.
  • BruteForceConfig: ์ด ์˜ต์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ ์ฟผ๋ฆฌ์˜ ํ‘œ์ค€ ์„ ํ˜• ๊ฒ€์ƒ‰์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์ฐจ๋ณ„ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ๊ตฌ์„ฑํ•  ํ•„๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๋ ค๋ฉด BruteForceConfig์— ๋นˆ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

DistanceMeasureType

์—ด๊ฑฐํ˜•
SQUARED_L2_DISTANCE ์œ ํด๋ฆฌ๋“œ(L2) ๊ฑฐ๋ฆฌ
L1_DISTANCE ๋งจํ•ดํŠผ(L1) ๊ฑฐ๋ฆฌ
DOT_PRODUCT_DISTANCE ๊ธฐ๋ณธ๊ฐ’ ์Šค์นผ๋ผ๊ณฑ์˜ ์Œ์ˆ˜๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.
COSINE_DISTANCE ์ฝ”์‚ฌ์ธ ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค. ์ฝ”์‚ฌ์ธ ๊ฑฐ๋ฆฌ ๋Œ€์‹  DOT_PRODUCT_Distance + UNIT_L2_NORM์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. Google์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ DOT_PRODUCT ๊ฑฐ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ตœ์ ํ™”๋˜์—ˆ์œผ๋ฉฐ, UNIT_L2_NORM๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ์ฝ”์‚ฌ์ธ ๊ฑฐ๋ฆฌ์™€ ๋™์ผํ•œ ์ˆœ์œ„ ๋ฐ ์ˆ˜ํ•™์  ๋“ฑ๊ฐ€๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

FeatureNormType

์—ด๊ฑฐํ˜•
UNIT_L2_NORM ๋‹จ์œ„ L2 ์ •๊ทœํ™” ์œ ํ˜•์ž…๋‹ˆ๋‹ค.
NONE ๊ธฐ๋ณธ๊ฐ’ ์ง€์ •๋œ ์ •๊ทœํ™” ์œ ํ˜•์ด ์—†์Šต๋‹ˆ๋‹ค.

TreeAhConfig

tree-AH ์•Œ๊ณ ๋ฆฌ์ฆ˜(Shallow tree + Asymmetric Hashing)์— ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ•„๋“œ์ž…๋‹ˆ๋‹ค.

ํ•„๋“œ
fractionLeafNodesToSearch double
์ฟผ๋ฆฌ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌํ”„ ๋…ธ๋“œ์˜ ๊ธฐ๋ณธ ๋น„์œจ์ž…๋‹ˆ๋‹ค. ๋ฒ”์œ„๋Š” 0.0~1.0 ๋ฏธ๋งŒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ 0.05์ž…๋‹ˆ๋‹ค.
leafNodeEmbeddingCount int32
๊ฐ ๋ฆฌํ”„ ๋…ธ๋“œ์˜ ์ž„๋ฒ ๋”ฉ ์ˆ˜์ž…๋‹ˆ๋‹ค. ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ 1000์ž…๋‹ˆ๋‹ค.
leafNodesToSearchPercent int32
์ง€์› ์ค‘๋‹จ๋จ, fractionLeafNodesToSearch๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ฟผ๋ฆฌ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌํ”„ ๋…ธ๋“œ์˜ ๊ธฐ๋ณธ ๋น„์œจ์ž…๋‹ˆ๋‹ค. 1~100 ๋ฒ”์œ„ ๋‚ด์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์„ค์ •๋˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์€ 10(์ฆ‰, 10%)์ž…๋‹ˆ๋‹ค.

BruteForceConfig

์ด ์˜ต์…˜์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ ์ฟผ๋ฆฌ์˜ ํ‘œ์ค€ ์„ ํ˜• ๊ฒ€์ƒ‰์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์ฐจ๋ณ„ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด ๊ตฌ์„ฑํ•  ํ•„๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ ํƒํ•˜๋ ค๋ฉด BruteForceConfig์˜ ๋นˆ ๊ฐ์ฒด๋ฅผ algorithmConfig์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

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

๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ Cloud Storage ์œ„์น˜์— ์—…๋กœ๋“œํ•˜์„ธ์š”. ํŒŒ์ผ์ด JSON ์ค„ ํ˜•์‹์ธ์ง€ ํ™•์ธํ•˜์„ธ์š”.

ํŒŒ์ผ์€ JSON Lines ํ˜•์‹์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์ƒ˜ํ”Œ์€ ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜ ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช… ๋…ธํŠธ๋ถ์—์„œ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

{"id": "0", "bytes_inputs": {"b64": "..."}}
{"id": "1", "bytes_inputs": {"b64": "..."}}
{"id": "2", "bytes_inputs": {"b64": "..."}}

์ƒ‰์ธ ๋˜๋Š” ๊ตฌ์„ฑ ์—…๋ฐ์ดํŠธ

Vertex AI๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋ธ์˜ ์ตœ๊ทผ์ ‘ ์ด์›ƒ ์ƒ‰์ธ์ด๋‚˜ Example ๊ตฌ์„ฑ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ ์„ธํŠธ์˜ ์ƒ‰์ธ์„ ์žฌ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋ชจ๋ธ์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ชจ๋ธ์˜ ์ƒ‰์ธ์— 1,000๊ฐœ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๊ณ  ์ธ์Šคํ„ด์Šค 500๊ฐœ๋ฅผ ๋” ์ถ”๊ฐ€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ UpdateExplanationDataset๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์›๋ž˜์˜ ์ธ์Šคํ„ด์Šค 1,000๊ฐœ๋ฅผ ๋‹ค์‹œ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ  ์ƒ‰์ธ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ค๋ช… ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

Python

def update_explanation_dataset(model_id, new_examples):
    response = clients["model"].update_explanation_dataset(model=model_id,  examples=new_examples)
    update_dataset_response = response.result()
    return update_dataset_response

PRESET_CONFIG = {
    "modality": "TEXT",
    "query": "FAST"
}
NEW_DATASET_FILE_PATH = "new_dataset_path"
NUM_NEIGHBORS_TO_RETURN = 10

EXAMPLES = aiplatform.Examples(presets=PRESET_CONFIG,
                                    gcs_source=aiplatform.types.io.GcsSource(uris=[NEW_DATASET_FILE_PATH]),
                                      neighbor_count=NUM_NEIGHBORS_TO_RETURN)

MODEL_ID = 'model_id'
update_dataset_response = update_explanation_dataset(MODEL_ID, EXAMPLES)

์‚ฌ์šฉ ์ฐธ๊ณ ์‚ฌํ•ญ:

  • model_id๋Š” UpdateExplanationDataset ์ž‘์—… ํ›„์—๋„ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

  • UpdateExplanationDataset ์ž‘์—…์€ Model ๋ฆฌ์†Œ์Šค์—๋งŒ ์˜ํ–ฅ์„ ์ฃผ๋ฉฐ, ์—ฐ๊ฒฐ๋œ DeployedModel๋Š” ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ฆ‰, deployedModel์˜ ์ƒ‰์ธ์— ๋ฐฐํฌ ๋‹น์‹œ์˜ ๋ฐ์ดํ„ฐ ์„ธํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. deployedModel์˜ ์ƒ‰์ธ์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ์—…๋ฐ์ดํŠธํ•œ ๋ชจ๋ธ์„ ์—”๋“œํฌ์ธํŠธ๋กœ ์žฌ๋ฐฐํฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜จ๋ผ์ธ ์„ค๋ช…์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๊ตฌ์„ฑ ์žฌ์ •์˜

์„ค๋ช…์„ ์š”์ฒญํ•  ๋•Œ ExplanationSpecOverride ํ•„๋“œ๋ฅผ ์ง€์ •ํ•˜์—ฌ ์ฆ‰์„์—์„œ ์ผ๋ถ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋”ฐ๋ผ์„œ๋Š” ๋ฐ˜ํ™˜๋˜๋Š” ์„ค๋ช… ์œ ํ˜•์— ์ผ๋ถ€ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์–‘ํ•œ ์„ค๋ช…์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์„ค๋ช…์— ๋‹จ์ผ ์œ ํ˜•์˜ ์˜ˆ์‹œ๊ฐ€ ์„ค๋ช…์—์„œ ๊ณผ๋„ํ•˜๊ฒŒ ํ‘œํ˜„๋˜์ง€ ์•Š์Œ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํฌ๋ผ์šฐ๋”ฉ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ๋ชจ๋ธ์—์„œ ์ƒˆ๊ฐ€ ๋น„ํ–‰๊ธฐ๋กœ ๋ผ๋ฒจ์ด ์ง€์ •๋œ ์ด์œ ๋ฅผ ํŒŒ์•…ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๊ทผ๋ณธ ์›์ธ์„ ํšจ๊ณผ์ ์œผ๋กœ ์กฐ์‚ฌํ•˜๊ธฐ ์œ„ํ•ด ๋„ˆ๋ฌด ๋งŽ์€ ์ƒˆ ์˜ˆ์‹œ๋ฅผ ์„ค๋ช…์œผ๋กœ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ํ‘œ์—๋Š” ์˜ˆ์ œ ๊ธฐ๋ฐ˜ ์„ค๋ช… ์š”์ฒญ์— ๋Œ€ํ•ด ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์š”์•ฝ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์†์„ฑ ์ด๋ฆ„ ์†์„ฑ ๊ฐ’ ์„ค๋ช…
neighborCount int32 ์„ค๋ช…์œผ๋กœ ๋ฐ˜ํ™˜ํ•  ์˜ˆ์‹œ ์ˆ˜์ž…๋‹ˆ๋‹ค.
crowdingCount int32 ๋™์ผํ•œ ํฌ๋ผ์šฐ๋”ฉ ํƒœ๊ทธ๋กœ ๋ฐ˜ํ™˜ํ•  ์ตœ๋Œ€ ์˜ˆ์‹œ ์ˆ˜์ž…๋‹ˆ๋‹ค.
allow String Array ์„ค๋ช…์— ํ—ˆ์šฉ๋˜๋Š” ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค.
deny String Array ์„ค๋ช…์— ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ํƒœ๊ทธ์ž…๋‹ˆ๋‹ค.

๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ํ•„ํ„ฐ๋ง์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์žฌ์ •์˜๊ฐ€ ํฌํ•จ๋œ JSON ์š”์ฒญ ๋ณธ๋ฌธ์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

{
  "instances":[
    {
      "id": data[0]["id"],
      "bytes_inputs": {"b64": bytes},
      "restricts": "",
      "crowding_tag": ""
    }
  ],
  "explanation_spec_override": {
    "examples_override": {
      "neighbor_count": 5,
      "crowding_count": 2,
      "restrictions": [
        {
          "namespace_name": "label",
          "allow": ["Papilloma", "Rift_Valley", "TBE", "Influenza", "Ebol"]
        }
      ]
    }
  }
}

๋‹ค์Œ ๋‹จ๊ณ„

๋‹ค์Œ์€ ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ explain ์š”์ฒญ์˜ ์‘๋‹ต ์˜ˆ์ž…๋‹ˆ๋‹ค.

[
   {
      "neighbors":[
         {
            "neighborId":"311",
            "neighborDistance":383.8
         },
         {
            "neighborId":"286",
            "neighborDistance":431.4
         }
      ],
      "input":"0"
   },
   {
      "neighbors":[
         {
            "neighborId":"223",
            "neighborDistance":471.6
         },
         {
            "neighborId":"55",
            "neighborDistance":392.7
         }
      ],
      "input":"1"
   }
]

๊ฐ€๊ฒฉ ์ฑ…์ •

๊ฐ€๊ฒฉ ์ฑ…์ • ํŽ˜์ด์ง€์—์„œ ์˜ˆ์‹œ ๊ธฐ๋ฐ˜ ์„ค๋ช…์— ๋Œ€ํ•œ ์„น์…˜ ์‚ดํŽด๋ณด๊ธฐ