Compare commits

...
20 Commits
Author SHA1 Message Date
Andrew Ferlitsch 7832abd957 fix: missing bucket 2023-05-08 19:00:14 +00:00
Andrew Ferlitsch 447bbbff43 update: boilerplate reduction 12 2023-05-06 01:14:54 +00:00
dstnluong-googleandGitHub 5651427a97 Update stable_diffusion notebook with steps for local inference. (#1813)
* Update stable_diffusion notebook with steps for local inference.

* Lint

* Move comments to top and shorten line.

* Lint

* Make code comment titles, add print statements, and update Objective

* change print to display

* lint

* change training dockers to serving dockers
2023-05-05 20:04:46 +00:00
Andrew FerlitschandGitHub 6195e7bbf9 Ci cd 2 (#1802)
* update: record tallied results to GCS bucket

* fix: test percent

* update: accumulator support

* fix: use args for where to store results

* fix: args for results file

* fix: gs bucket ptrfix

* fix: tuning args

* fix: ci/cd test on openin artifacts bucket

* fix: 2nd try at bucket issue

* fix: 2nd try at bucket issue

* debug: bucket issue

* debug: bucket issue

* debug: bucket issue

* debug: bucket issue

* debug: bucket issue

* debug: bucket issue

* debug: no entries written

* debug: no entries written

* debug: not accumulating

* debug: not accumulating

* debug: not accumulating

* debug: not accumulating

* Update requirements.txt

* debug: not accumulating

* debug: not accumulating

* debug: matching notebook name

* debug: pandas problem

* debug: import issues

* debug: load

* Update requirements.txt

* Update requirements.txt

* debug: read csv

* debug: read csv

* debug: read csv

* debug: indxer

* debug: indexer

* debug: accum

* debug: accum

* debug: accum

* debug: accum

* debug: accum

* debug: accum

* debug: accum

* debug: casting

* debug: casting

* debug: casting

* debug: casting

* debug: duration nit

* debug: duration nit

* fix: flaky

* fix: BUILD_ID

* fix: BUILD_ID

* fix: BUILD_ID

* fix: BUILD_ID

* fix: BUILD_ID

* fix: BUILD_ID

* fix: BUILD_ID

* fix: review

* fix: review

* fix: review

* fix: biz logic

* fix: biz logic

* fix: review

* fix: build_id required

* fix: use json format

* review: JSON simplifing

* review: JSON simplifing

* update: NotbookExecutionResult updates

* fix: revert to JSON

* update: use util to read from bucket

* fix: remove pandas inmport
2023-05-05 20:03:49 +00:00
Andrew FerlitschandGitHub 2b4f7834b8 feat: MG notebook to finetune BERT (#1815)
* feat: MG notebook to finetune BERT

* review updates
2023-05-05 18:23:48 +00:00
Andrew FerlitschandGitHub 6eadb9199d feat: MG notebook to finetune T5X (#1816)
* feat: MG notebook to finetune T5X

* fix: review comments
2023-05-05 18:23:06 +00:00
Bernie OngeweandGitHub cf9ba17c7d Update tabular_optimized_online_prediction.ipynb (#1819)
Can only set up one Service Networking configuration per _network_. However, we can have multiple VPC networks per project, each with its own Service Networking configuration
2023-05-05 15:22:31 +00:00
KCFindstrandGitHub 384fa2c1b6 Add service account config to TIMM notebook (#1818) 2023-05-05 14:55:29 +00:00
Xiang XuandGitHub 4d24324cc6 fix controlnet (#1817) 2023-05-04 22:45:16 +00:00
Lav RaiandGitHub b1331406a0 Fix format-check and size-check error for detectron2. (#1814)
* Fix format-check and size-check error for detectron2.

* Fix format-check and size-check error for detectron2.
2023-05-04 19:02:19 +00:00
KCFindstrandGitHub cf00491bdc Update Model Garden TFVision notebooks. (#1808)
* Update #ModelGarden TFVision notebooks.

1. Added checkpoints for resnet-50, scaled_yolov4, deeplabv3+
2. Supported launching dockers in europe and asia region.

* Use a smaller batch size to resolve OOM issue
2023-05-04 15:39:53 +00:00
Huguens JeanandGitHub b24de2c375 Add notebook to trigger model garden training with model descriptions. (#1792)
* Trigger Model Garden Training

* Add notebook to trigger model garden training with model descriptions for ip sensitive checkpoints.

* Remove notebook in official folder.

* Fix type in notebook filename.

* Updated notebook description to reflect ip sensitive model garden training for EFFICIENTNET v2 using CLOUD key.

* Updated notebook with model garden specific configs for proprietary checkpoints.

* Linter check.

* Clear notebook's output.
2023-05-04 15:39:24 +00:00
Lav RaiandGitHub 79d80a1f4f Fix format-check and size-check error for stable diffusion inpainting. (#1812) 2023-05-04 00:01:31 +00:00
Xiang XuandGitHub de3e31e037 fix serve (#1811) 2023-05-03 23:20:00 +00:00
Andrew FerlitschandGitHub d45d5fad51 fix links (#1807) 2023-05-01 15:59:33 +00:00
Andrew FerlitschandGitHub 10a9e776b7 there is a regression in later packages (#1809) 2023-04-28 16:37:14 +00:00
Andrew FerlitschandGitHub db80aa4953 Revert "outdated (#1798)" (#1806)
This reverts commit 3d461a8458.
2023-04-27 21:07:59 +00:00
Xiang XuandGitHub f4345ed935 fix gs (#1804) 2023-04-26 22:00:11 +00:00
Lav RaiandGitHub b191b93c7e Fix detectron2 permission errors. (#1803) 2023-04-26 19:55:37 +00:00
gericdongandGitHub 8acf15cccb feat: notebook for text models for explainable AI feature attribution - sampled shapley (#1801)
* feat:notebook for text models for explanable AI feature attribution - sampled shapley

* addressed review comments
2023-04-25 17:52:39 +00:00
21 changed files with 5345 additions and 435 deletions
+19 -4
View File
@@ -17,7 +17,7 @@
import argparse
import pathlib
import random
import os
import execute_changed_notebooks_helper
@@ -47,6 +47,12 @@ parser.add_argument(
required=False,
default=100,
)
parser.add_argument(
"--build_id",
type=str,
help="The build id (which may be a Cloud Build job specific or user explicit.",
required=True
)
parser.add_argument(
"--base_branch",
help="The base git branch to diff against to find changed files.",
@@ -129,26 +135,35 @@ changed_notebooks = execute_changed_notebooks_helper.get_changed_notebooks(
base_branch=args.base_branch,
)
results_bucket = f"{args.artifacts_bucket}"
results_file = f"{args.build_id}.json"
if args.test_percent == 100:
notebooks = changed_notebooks
accumulative_results = {}
else:
notebooks = [changed_notebook for changed_notebook in changed_notebooks if random.randint(1, 100) < args.test_percent]
accumulative_results = execute_changed_notebooks_helper.load_results(results_bucket, results_file)
notebooks = [changed_notebook for changed_notebook in changed_notebooks if execute_changed_notebooks_helper.select_notebook(changed_notebook, accumulative_results, args.test_percent)]
if args.dry_run:
print("Dry run ...\n")
for notebook in notebooks:
print(f"Would execute: {notebook.path}")
print(f"Would execute: {notebook}")
else:
execute_changed_notebooks_helper.process_and_execute_notebooks(
notebooks=notebooks,
container_uri=args.container_uri,
staging_bucket=args.staging_bucket,
artifacts_bucket=args.artifacts_bucket,
results_file=results_file,
accumulative_results=accumulative_results,
should_parallelize=args.should_parallelize,
timeout=args.timeout,
variable_project_id=args.variable_project_id,
variable_region=args.variable_region,
variable_service_account=args.variable_service_account,
variable_vpc_network=args.variable_vpc_network,
private_pool_id=args.private_pool_id,
private_pool_id=args.private_pool_id
)
@@ -21,11 +21,15 @@ import json
import git
import operator
import os
import io
import json
import pathlib
import re
import subprocess
import random
from google.cloud import storage
import utils
from typing import List, Optional
from typing import List, Optional, Dict, Any
from utils import util
import execute_notebook_helper
@@ -65,7 +69,9 @@ def format_timedelta(delta: datetime.timedelta) -> str:
@dataclasses.dataclass
class NotebookExecutionResult:
name: str
path: str
duration: datetime.timedelta
start_time: datetime.datetime
is_pass: bool
log_url: str
output_uri: str
@@ -80,6 +86,40 @@ class NotebookExecutionResult:
else:
return None
def load_results(results_bucket: str,
results_file: str) -> Dict[str,Any]:
'''
Load accumulated notebook test results
'''
print("Loading existing accumulative results ...")
accumulative_results = {}
try:
content = util.download_blob_into_memory(results_bucket, results_file, download_as_text=True)
accumulative_results = json.loads(content)
print(accumulative_results)
except Exception as e:
print(e)
# If there are no accumulative results, an empty dict is returned
return accumulative_results
def select_notebook(changed_notebook: str,
accumulative_results: Dict[str, Any],
test_percent: int) -> bool:
'''
Algorithm to randomly select a notebook, but weight the propbability of selected based on past failures
'''
if changed_notebook in accumulative_results:
pass_count = accumulative_results[changed_notebook]['passed']
fail_count = accumulative_results[changed_notebook]['failed']
else:
pass_count = 1
fail_count = 0
return (random.randint(1, 100) * (1 + (fail_count / (pass_count + fail_count))) < test_percent)
def _process_notebook(
notebook_path: str,
@@ -191,7 +231,9 @@ def process_and_execute_notebook(
result = NotebookExecutionResult(
name=tag,
path=notebook,
duration=datetime.timedelta(seconds=0),
start_time=datetime.datetime.now(),
is_pass=False,
output_uri=notebook_output_uri,
log_url="",
@@ -201,7 +243,6 @@ def process_and_execute_notebook(
)
# TODO: Handle cases where multiple notebooks have the same name
time_start = datetime.datetime.now()
operation = None
try:
# Get the python version for running the notebook if specified
@@ -247,9 +288,10 @@ def process_and_execute_notebook(
# Block and wait for the result
operation_result = operation.result(timeout=timeout_in_seconds)
result.duration = datetime.datetime.now() - time_start
result.duration = datetime.datetime.now() - result.start_time
result.is_pass = True
print(f"{notebook} PASSED in {format_timedelta(result.duration)}.")
except Exception as error:
result.error_message = str(error)
@@ -268,7 +310,7 @@ def process_and_execute_notebook(
except Exception as error:
result.error_message = str(error)
result.duration = datetime.datetime.now() - time_start
result.duration = datetime.datetime.now() - result.start_time
result.is_pass = False
print(
@@ -336,12 +378,54 @@ def get_changed_notebooks(
return notebooks
def _save_results(results: List[NotebookExecutionResult],
accumulative_results: Dict[str,Any],
artifacts_bucket: str,
results_file: str):
artifacts_bucket = artifacts_bucket.replace("gs://", "").split('/')[0]
print("Updating accumulative results ...")
for result in results:
if result.path in accumulative_results:
accumulative_results[result.path]['duration'] = result.duration.total_seconds()
accumulative_results[result.path]['start_time'] = str(result.start_time)
if result.is_pass:
accumulative_results[result.path]['passed'] += 1
else:
accumulative_results[result.path]['failed'] += 1
print(f"updating {result.path}")
else:
if result.is_pass:
pass_count = 1
fail_count = 0
else:
pass_count = 0
fail_count = 1
accumulative_results[result.path] = {
'duration': result.duration.total_seconds(),
'start_time': str(result.start_time),
'passed': pass_count,
'failed': fail_count
}
print(f"adding {result.path}")
print("Saving accumulative results ...")
content = json.dumps(accumulative_results)
client = storage.Client()
bucket = client.get_bucket(artifacts_bucket)
bucket.blob(str(results_file)).upload_from_string(content, 'text/json')
def process_and_execute_notebooks(
notebooks: List[str],
container_uri: str,
staging_bucket: str,
artifacts_bucket: str,
results_file: str,
accumulative_results: List[NotebookExecutionResult],
should_parallelize: bool,
timeout: int,
variable_project_id: str,
@@ -369,6 +453,10 @@ def process_and_execute_notebooks(
Required. The GCS staging bucket to write source code to.
artifacts_bucket (str):
Required. The GCS staging bucket to write executed notebooks to.
results_file (str):
Required: The path to the artifacts bucket to save results
accumulative_results (List):
Required: The in-memory previous accumulative notebook CI/CD test results.
variable_project_id (str):
Required. The value for PROJECT_ID to inject into notebooks.
variable_region (str):
@@ -471,7 +559,7 @@ def process_and_execute_notebooks(
print("=" * 100)
build_id = results_sorted[0].build_id
logs_bucket_name = (results_sorted[0].logs_bucket).removeprefix("gs://")
logs_bucket_name = (results_sorted[0].logs_bucket).replace("gs://", "")
log_file_name = f"log-{build_id}.txt"
log_contents = util.download_blob_into_memory(
@@ -489,6 +577,11 @@ def process_and_execute_notebooks(
else:
print(log_contents)
_save_results(results_sorted,
accumulative_results,
artifacts_bucket,
results_file)
print("\n=== END RESULTS===\n")
total_notebook_duration = functools.reduce(
@@ -36,7 +36,7 @@ steps:
- -c
- |
. workspace/env/bin/activate &&
python3 .cloud-build/execute_changed_notebooks_cli.py --test_paths_file "${_TEST_PATHS_FILE}" --base_branch "${_FORCED_BASE_BRANCH}" --container_uri ${_PYTHON_IMAGE} --staging_bucket ${_GCS_STAGING_BUCKET} --artifacts_bucket ${_GCS_STAGING_BUCKET}/executed_notebooks/PR_${_PR_NUMBER}/BUILD_${BUILD_ID} --variable_project_id ${PROJECT_ID} --variable_region ${_GCP_REGION} --variable_service_account ${_GCP_SERVICE_ACCOUNT} --variable_vpc_network "${_GPC_VPC_NETWORK_NAME}" `if [ ! -z "${_PRIVATE_POOL_NAME}" ]; then echo "--private_pool_id ${_PRIVATE_POOL_NAME}"; fi`
python3 .cloud-build/execute_changed_notebooks_cli.py --test_paths_file "${_TEST_PATHS_FILE}" --base_branch "${_FORCED_BASE_BRANCH}" --container_uri ${_PYTHON_IMAGE} --staging_bucket ${_GCS_STAGING_BUCKET} --artifacts_bucket ${_GCS_STAGING_BUCKET}/executed_notebooks/PR_${_PR_NUMBER}/BUILD_${BUILD_ID} --variable_project_id ${PROJECT_ID} --variable_region ${_GCP_REGION} --variable_service_account ${_GCP_SERVICE_ACCOUNT} --variable_vpc_network "${_GPC_VPC_NETWORK_NAME}" `if [ ! -z "${_PRIVATE_POOL_NAME}" ]; then echo "--private_pool_id ${_PRIVATE_POOL_NAME}"; fi` --build_id ${BUILD_ID}
env:
- 'IS_TESTING=1'
timeout: 86400s
+5 -2
View File
@@ -3,12 +3,15 @@ numpy
jupyter
nbconvert
papermill
pandas
matplotlib
tabulate
google-cloud-aiplatform
google-cloud-storage
google-cloud-build
google-cloud-storage
ratemate
GitPython
tqdm
tqdm
fsspec
pandas
@@ -196,7 +196,7 @@
" USER_FLAG = \"--user\"\n",
"\n",
"! pip3 install {USER_FLAG} --upgrade --quiet google-cloud-aiplatform \\\n",
" google-cloud-pipeline-components \\\n",
" google-cloud-pipeline-components==1.0.25 \\\n",
" kfp "
]
},
@@ -0,0 +1,852 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "copyright"
},
"outputs": [],
"source": [
"# Copyright 2023 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "title:generic,gcp"
},
"source": [
"# Get started with Model Garden Pipeline Templates for BERT models\n",
"\n",
"\n",
"<table align=\"left\">\n",
"\n",
" <td>\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_template_pipelines_bert.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_template_pipelines_bert.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/communitymodel_garden/model_garden_template_pipelines_bert.ipynb\">\n",
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
" Open in Vertex AI Workbench\n",
" </a>\n",
" </td> \n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "overview:mlops"
},
"source": [
"## Overview\n",
"\n",
"\n",
"This tutorial demonstrates how to modify, compile and execute a prebuilt Vertex AI Model Garden pipeline template with Vertex AI Pipelines.\n",
"\n",
"Learn more about [Create a pipeline template](https://cloud.google.com/vertex-ai/docs/pipelines/create-pipeline-template)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "objective:mlops,stage4,get_started_vertex_model_evaluation"
},
"source": [
"### Objective\n",
"\n",
"In this tutorial, you learn how to use a prebuilt pipeline template with `Vertex AI Pipelines` to fine-tune a BERT text classification model, where the model is accessed from `Vertex AI Model Garden`.\n",
"\n",
"This tutorial uses the following Google Cloud ML services:\n",
"\n",
"- `Vertex AI Pipelines`\n",
"- `Vertex AI Training`\n",
"- `Vertex AI Model Garden`\n",
"- `Google Cloud Pipeline Components`\n",
"\n",
"\n",
"The steps performed include:\n",
"\n",
"- Create a user-defined repository in the `Artifact Registry`.\n",
"- Upload the prebuilt pipeline template to the `Artifact Registry`.\n",
"- Create a pipeline job with the prebuilt pipeline template to fine-tune a BERT model.\n",
"- Execute the pipeline using `Vertex AI Pipelines`.\n",
" - Load BERT model from Vertex AI Model Garden\n",
" - Fine-tune train the model\n",
" - Do batch prediction\n",
" - Evaluate the model from the batch prediction results\n",
"- Obtain the Vertex AI Model resource from the pipeline artifacts.\n",
"- Deploy the model to a Vertex AI Endpoint\n",
"- Make a prediction"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dataset:bank,lbn"
},
"source": [
"### Model\n",
"\n",
"This tutorial uses a pre-trained BERT text classification model from `Vertex AI Model Garden`, which is then fine-tuned (transfer learning) on a dataset of text phrases which are classified as either FirstClass or SecondClass.\n",
"\n",
"Learn more about [BERT pretrained encoder model]( https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/3). "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "costs"
},
"source": [
"### Costs\n",
"\n",
"This tutorial uses billable components of Google Cloud:\n",
"\n",
"* Vertex AI\n",
"* Cloud Storage\n",
"* Dataflow\n",
"\n",
"Learn about [Vertex AI\n",
"pricing](https://cloud.google.com/vertex-ai/pricing), [Cloud Storage\n",
"pricing](https://cloud.google.com/storage/pricing), and [Dataflow pricing](https://cloud.google.com/dataflow/pricing)\n",
"and use the [Pricing\n",
"Calculator](https://cloud.google.com/products/calculator/)\n",
"to generate a cost estimate based on your projected usage."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "install_mlops"
},
"source": [
"## Installations\n",
"\n",
"Install the packages required for executing this notebook.\n",
"\n",
"*Note:* This tutorial requires KFP 2.x."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "install_mlops"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"! pip3 install --upgrade google-cloud-aiplatform \\\n",
" google-cloud-pipeline-components \\\n",
" kfp==2.0.0b15"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "restart"
},
"source": [
"### Colab only: Uncomment the following cell to restart the kernel"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "D-ZBOjErv5mM"
},
"outputs": [],
"source": [
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
"# import IPython\n",
"\n",
"# app = IPython.Application.instance()\n",
"# app.kernel.do_shutdown(True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "before_you_begin"
},
"source": [
"## Before you begin\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "before_you_begin:nogpu"
},
"source": [
"### Set your project ID\n",
"\n",
"**If you don't know your project ID**, try the following:\n",
"* Run `gcloud config list`.\n",
"* Run `gcloud projects list`.\n",
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_project_id"
},
"outputs": [],
"source": [
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"\n",
"# Set the project id\n",
"! gcloud config set project {PROJECT_ID}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "region"
},
"source": [
"#### Region\n",
"\n",
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "region"
},
"outputs": [],
"source": [
"REGION = \"us-central1\" # @param {type: \"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c4ccf556d4ea"
},
"source": [
"### Enable APIs\n",
"\n",
"You can enable the required APIs using `gcloud`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "619529337e6d"
},
"outputs": [],
"source": [
"! gcloud services enable compute.googleapis.com \\\n",
" containerregistry.googleapis.com \\\n",
" aiplatform.googleapis.com \\\n",
" artifactregistry.googleapis.com"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gcp_authenticate"
},
"source": [
"### Authenticate your Google Cloud account\n",
"\n",
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FvQeFm3Gv5mR"
},
"source": [
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ce6043da7b33"
},
"outputs": [],
"source": [
"# ! gcloud auth login"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0367eac06a10"
},
"source": [
"**3. Colab, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "21ad4dbb4a61"
},
"outputs": [],
"source": [
"IS_COLAB = False\n",
"# from google.colab import auth\n",
"# auth.authenticate_user()\n",
"# IS_COLAB=True"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c13224697bfb"
},
"source": [
"**4. Service account or other**\n",
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bucket:mbsdk"
},
"source": [
"### Create a Cloud Storage bucket\n",
"\n",
"Create a storage bucket to store intermediate artifacts such as datasets."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bucket"
},
"outputs": [],
"source": [
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "create_bucket"
},
"source": [
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "create_bucket"
},
"outputs": [],
"source": [
"! gsutil mb -l $REGION $BUCKET_URI"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "set_service_account"
},
"source": [
"#### Service Account\n",
"\n",
"**If you don't know your service account**, try to get your service account using `gcloud` command by executing the second cell below."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_service_account"
},
"outputs": [],
"source": [
"SERVICE_ACCOUNT = \"[your-service-account]\" # @param {type:\"string\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "autoset_service_account"
},
"outputs": [],
"source": [
"if (\n",
" SERVICE_ACCOUNT == \"\"\n",
" or SERVICE_ACCOUNT is None\n",
" or SERVICE_ACCOUNT == \"[your-service-account]\"\n",
"):\n",
" # Get your service account from gcloud\n",
" if not IS_COLAB:\n",
" shell_output = !gcloud auth list 2>/dev/null\n",
" SERVICE_ACCOUNT = shell_output[2].replace(\"*\", \"\").strip()\n",
"\n",
" if IS_COLAB:\n",
" shell_output = ! gcloud projects describe $PROJECT_ID\n",
" project_number = shell_output[-1].split(\":\")[1].strip().replace(\"'\", \"\")\n",
" SERVICE_ACCOUNT = f\"{project_number}-compute@developer.gserviceaccount.com\"\n",
"\n",
" print(\"Service Account:\", SERVICE_ACCOUNT)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "set_service_account:pipelines"
},
"source": [
"#### Set service account access for Vertex AI Pipelines\n",
"\n",
"Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_service_account:pipelines"
},
"outputs": [],
"source": [
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator \n",
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "setup_vars"
},
"source": [
"### Set up variables\n",
"\n",
"Next, set up some variables used throughout the tutorial.\n",
"### Import libraries and define constants"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "import_kfp"
},
"outputs": [],
"source": [
"import json\n",
"\n",
"import google.cloud.aiplatform as aiplatform\n",
"from kfp.registry import RegistryClient"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "init_aip:mbsdk,all"
},
"source": [
"### Initialize Vertex AI SDK for Python\n",
"\n",
"Initialize the Vertex AI SDK for Python for your project and corresponding bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "init_aip:mbsdk,all"
},
"outputs": [],
"source": [
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_URI)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9b773e8d2bd2"
},
"source": [
"## Create repo in Artifact Registry\n",
"\n",
"First, you create your own (user-defined) repository in the `Artifact Registry`. You use this repository to upload and retrieve your pipeline templates.\n",
"\n",
"The name of your repo is `quickstart-kfp-repo`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "520de849cee2"
},
"outputs": [],
"source": [
"REPO_NAME = \"quickstart-kfp-repo\"\n",
"\n",
"! gcloud artifacts repositories create {REPO_NAME} --location={REGION} --repository-format=KFP"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1611d3517c0f"
},
"source": [
"### Upload the pipeline template\n",
"\n",
"Next, you instantiate a client interface to the Artifact Registry. Then with the `upload_pipeline()` method you upload your pipeline template."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "72db37f6d67c"
},
"outputs": [],
"source": [
"BERT_YAML = \"gs://cloud-samples-data/vertex-ai/dataset-management/datasets/bert_finetuning/pipeline.yaml\"\n",
"\n",
"! gsutil cp {BERT_YAML} pipeline.yaml\n",
"\n",
"client = RegistryClient(\n",
" host=f\"https://{REGION}-kfp.pkg.dev/{PROJECT_ID}/quickstart-kfp-repo\"\n",
")\n",
"\n",
"templateName, versionName = client.upload_pipeline(\n",
" file_name=\"pipeline.yaml\",\n",
" tags=[\"v1\", \"latest\"],\n",
" extra_headers={\n",
" \"description\": \"This is a pipeline template for fine-tuning a BERT model.\"\n",
" },\n",
")\n",
"\n",
"! rm pipeline.yaml"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "02f82754fc0d"
},
"source": [
"### View your artifacts in your registry\n",
"\n",
"Next, using the `gcloud artifacts files` command you view the artifacts, inclusive of the pipeline template, in your artifacts repository."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "b2f641eb2056"
},
"outputs": [],
"source": [
"! gcloud artifacts files list --repository={REPO_NAME} --location={REGION}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9d5296831cfb"
},
"source": [
"## Load and execute the pipeline job\n",
"\n",
"Next, you create a Vertex AI Pipeline job from your BERT pipeline template by instantiating a PipelineJob(), with the following parameters:\n",
"\n",
"- `display_name`: The human readable name for the pipeline job.\n",
"- `template_path`: The path to the pipeline template in the Artifact Registry.\n",
"- `enable_caching`: On re-runs, use the results from previous successful and unchanged steps.\n",
"- `pipeline_root`: A Cloud storage location for storing pipeline results.\n",
"- `parameter_values`: The parameters and values that are input to the template pipeline. In this example, they are:\n",
" - `project`: Your project ID.\n",
" - `class_labels`: A list of valid class labels, in cardinal order.\n",
" - `root_dir`: A Cloud Storage scratch area.\n",
" - `training_data_path`: A Cloud Storage location to the training data.\n",
" - `ground_truth_gcs_source_uris`: A Cloud Storage location to evaluation data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "a3c502fc7e41"
},
"outputs": [],
"source": [
"PIPELINE_ROOT = f\"{BUCKET_URI}/pipeline_root/bert-finetuning\"\n",
"\n",
"job = aiplatform.PipelineJob(\n",
" display_name=\"bert-finetuning\",\n",
" template_path=f\"https://{REGION}-kfp.pkg.dev/{PROJECT_ID}/quickstart-kfp-repo/{templateName}/{versionName}\",\n",
" pipeline_root=PIPELINE_ROOT,\n",
" enable_caching=False,\n",
" parameter_values={\n",
" \"project\": PROJECT_ID,\n",
" \"class_labels\": [\"FirstClass\", \"SecondClass\", \"[UNK]\"],\n",
" \"root_dir\": BUCKET_URI,\n",
" \"ground_truth_gcs_source_uris\": [\n",
" \"gs://cloud-samples-data/vertex-ai/dataset-management/datasets/bert_finetuning/wide_and_deep_trainer_container_tests_input.jsonl\"\n",
" ],\n",
" \"training_data_path\": \"gs://cloud-samples-data/vertex-ai/dataset-management/datasets/bert_finetuning/wide_and_deep_trainer_container_tests_input.jsonl\",\n",
" },\n",
")\n",
"\n",
"job.run()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "view_pipleline_results:bqml"
},
"source": [
"### View the pipeline results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "view_pipleline_results:bqml"
},
"outputs": [],
"source": [
"PROJECT_NUMBER = job.gca_resource.name.split(\"/\")[1]\n",
"print(PROJECT_NUMBER)\n",
"\n",
"\n",
"def print_pipeline_output(job, output_task_name):\n",
" JOB_ID = job.name\n",
" print(JOB_ID)\n",
" artifact = \"\"\n",
" for _ in range(len(job.gca_resource.job_detail.task_details)):\n",
" TASK_ID = job.gca_resource.job_detail.task_details[_].task_id\n",
" EXECUTE_OUTPUT = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/executor_output.json\"\n",
" )\n",
" GCP_RESOURCES = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/gcp_resources\"\n",
" )\n",
" EVALUATION_METRICS = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/evaluation_metrics\"\n",
" )\n",
" # Check if file exists, 0 is success\n",
" !gsutil -q stat $EXECUTE_OUTPUT\n",
" if _exit_code == 0:\n",
" ! gsutil cat $EXECUTE_OUTPUT\n",
" artifact = EXECUTE_OUTPUT\n",
" break\n",
" !gsutil -q stat $GCP_RESOURCES\n",
" if _exit_code == 0:\n",
" ! gsutil cat $GCP_RESOURCES\n",
" artifact = GCP_RESOURCES\n",
" break\n",
" !gsutil -q stat $EVALUATION_METRICS\n",
" if _exit_code == 0:\n",
" ! gsutil cat $EVALUATION_METRICS\n",
" artifact = EVALUATION_METRICS\n",
" break\n",
"\n",
" return artifact\n",
"\n",
"\n",
"print(\"get-vertex-model\")\n",
"artifacts = print_pipeline_output(job, \"get-vertex-model\")\n",
"output = !gsutil cat $artifacts\n",
"print(output)\n",
"output = json.loads(output[0])\n",
"model_id = output[\"artifacts\"][\"model\"][\"artifacts\"][0][\"metadata\"][\"resourceName\"]\n",
"print(\"\\n\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f431a9e6f025"
},
"source": [
"### Delete the pipeline job\n",
"\n",
"The method 'delete()' will delete the pipeline job."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "00bf554abbc6"
},
"outputs": [],
"source": [
"job.delete()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3d183db57ae2"
},
"source": [
"### Deploy the model\n",
"\n",
"Next, you deploy the model to an endpoint:\n",
"\n",
"- Use the `model_id` obtained from the pipeline artifacts to instaniate a Vertex AI Model resource instance.\n",
"- Deploy the Vertex AI Model resource to a Vertex AI Endpoint resource.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "591ccc049ce5"
},
"outputs": [],
"source": [
"model = aiplatform.Model(model_id)\n",
"endpoint = model.deploy(\n",
" accelerator_count=1,\n",
" accelerator_type=aiplatform.gapic.AcceleratorType.NVIDIA_TESLA_T4.name,\n",
" machine_type=\"n1-standard-4\",\n",
")\n",
"print(endpoint)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "edb781a92864"
},
"source": [
"### Make a prediction\n",
"\n",
"Finally, you make a prediction with the deployed model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "72d94012a987"
},
"outputs": [],
"source": [
"endpoint.predict([\"this is a test\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cleanup:mbsdk"
},
"source": [
"# Cleaning up\n",
"\n",
"To clean up all Google Cloud resources used in this project, you can [delete the Google Cloud\n",
"project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#shutting_down_projects) you used for the tutorial.\n",
"\n",
"Otherwise, you can delete the individual resources you created in this tutorial."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cleanup:mbsdk"
},
"outputs": [],
"source": [
"delete_bucket = False\n",
"\n",
"endpoint.undeploy_all()\n",
"endpoint.delete()\n",
"model.delete()\n",
"\n",
"if delete_bucket or os.getenv(\"IS_TESTING\"):\n",
" ! gsutil rm -r $BUCKET_URI\n",
"\n",
"! rm -rf custom custom.tar.gz"
]
}
],
"metadata": {
"colab": {
"name": "model_garden_pipeline_templates_bert.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -0,0 +1,850 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "copyright"
},
"outputs": [],
"source": [
"# Copyright 2023 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "title:generic,gcp"
},
"source": [
"# Get started with Model Garden Pipeline Templates for T5X models\n",
"\n",
"\n",
"<table align=\"left\">\n",
"\n",
" <td>\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_template_pipelines_t5x.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_template_pipelines_t5x.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/communitymodel_garden/model_garden_template_pipelines_t5x.ipynb\">\n",
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
" Open in Vertex AI Workbench\n",
" </a>\n",
" </td> \n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "overview:mlops"
},
"source": [
"## Overview\n",
"\n",
"\n",
"This tutorial demonstrates how to modify, compile and execute a prebuilt Vertex AI Model Garden pipeline template with Vertex AI Pipelines.\n",
"\n",
"Learn more about [Create a pipeline template](https://cloud.google.com/vertex-ai/docs/pipelines/create-pipeline-template)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "objective:mlops,stage4,get_started_vertex_model_evaluation"
},
"source": [
"### Objective\n",
"\n",
"In this tutorial, you learn how to use a prebuilt pipeline template with `Vertex AI Pipelines` to fine-tune a T5X text classification model, where the model is accessed from `Vertex AI Model Garden`.\n",
"\n",
"This tutorial uses the following Google Cloud ML services:\n",
"\n",
"- `Vertex AI Pipelines`\n",
"- `Vertex AI Training`\n",
"- `Vertex AI Model Garden`\n",
"- `Google Cloud Pipeline Components`\n",
"\n",
"\n",
"The steps performed include:\n",
"\n",
"- Create a user-defined repository in the `Artifact Registry`.\n",
"- Upload the prebuilt pipeline template to the `Artifact Registry`.\n",
"- Create a pipeline job with the prebuilt pipeline template to fine-tune a T5X model.\n",
"- Execute the pipeline using `Vertex AI Pipelines`.\n",
" - Load T5X model from Vertex AI Model Garden\n",
" - Fine-tune train the model\n",
"- Obtain the Vertex AI Model resource from the pipeline artifacts.\n",
"- Deploy the model to a Vertex AI Endpoint\n",
"- Make a prediction"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dataset:bank,lbn"
},
"source": [
"### Model\n",
"\n",
"This tutorial uses a pre-trained T5 text classification model from `Vertex AI Model Garden`, which is then fine-tuned (transfer learning) on a dataset of text phrases which are classified as either FirstClass or SecondClass.\n",
"\n",
"Learn more about [Text-to-text transfer transformer](https://github.com/google-research/text-to-text-transfer-transformer). "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "costs"
},
"source": [
"### Costs\n",
"\n",
"This tutorial uses billable components of Google Cloud:\n",
"\n",
"* Vertex AI\n",
"* Cloud Storage\n",
"* Dataflow\n",
"\n",
"Learn about [Vertex AI\n",
"pricing](https://cloud.google.com/vertex-ai/pricing), [Cloud Storage\n",
"pricing](https://cloud.google.com/storage/pricing), and [Dataflow pricing](https://cloud.google.com/dataflow/pricing)\n",
"and use the [Pricing\n",
"Calculator](https://cloud.google.com/products/calculator/)\n",
"to generate a cost estimate based on your projected usage."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "install_mlops"
},
"source": [
"## Installations\n",
"\n",
"Install the packages required for executing this notebook.\n",
"\n",
"*Note:* This tutorial requires KFP 2.x."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "install_mlops"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"! pip3 install --upgrade google-cloud-aiplatform \\\n",
" google-cloud-pipeline-components \\\n",
" kfp==2.0.0b15"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "restart"
},
"source": [
"### Colab only: Uncomment the following cell to restart the kernel"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "D-ZBOjErv5mM"
},
"outputs": [],
"source": [
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
"# import IPython\n",
"\n",
"# app = IPython.Application.instance()\n",
"# app.kernel.do_shutdown(True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "before_you_begin"
},
"source": [
"## Before you begin\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "before_you_begin:nogpu"
},
"source": [
"### Set your project ID\n",
"\n",
"**If you don't know your project ID**, try the following:\n",
"* Run `gcloud config list`.\n",
"* Run `gcloud projects list`.\n",
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_project_id"
},
"outputs": [],
"source": [
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"\n",
"# Set the project id\n",
"! gcloud config set project {PROJECT_ID}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "region"
},
"source": [
"#### Region\n",
"\n",
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "region"
},
"outputs": [],
"source": [
"REGION = \"us-central1\" # @param {type: \"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c4ccf556d4ea"
},
"source": [
"### Enable APIs\n",
"\n",
"You can enable the required APIs using `gcloud`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "619529337e6d"
},
"outputs": [],
"source": [
"! gcloud services enable compute.googleapis.com \\\n",
" containerregistry.googleapis.com \\\n",
" aiplatform.googleapis.com \\\n",
" artifactregistry.googleapis.com"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gcp_authenticate"
},
"source": [
"### Authenticate your Google Cloud account\n",
"\n",
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "FvQeFm3Gv5mR"
},
"source": [
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ce6043da7b33"
},
"outputs": [],
"source": [
"# ! gcloud auth login"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0367eac06a10"
},
"source": [
"**3. Colab, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "21ad4dbb4a61"
},
"outputs": [],
"source": [
"IS_COLAB = False\n",
"# from google.colab import auth\n",
"# auth.authenticate_user()\n",
"# IS_COLAB=True"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c13224697bfb"
},
"source": [
"**4. Service account or other**\n",
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bucket:mbsdk"
},
"source": [
"### Create a Cloud Storage bucket\n",
"\n",
"Create a storage bucket to store intermediate artifacts such as datasets."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bucket"
},
"outputs": [],
"source": [
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "create_bucket"
},
"source": [
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "create_bucket"
},
"outputs": [],
"source": [
"! gsutil mb -l $REGION $BUCKET_URI"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "set_service_account"
},
"source": [
"#### Service Account\n",
"\n",
"**If you don't know your service account**, try to get your service account using `gcloud` command by executing the second cell below."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_service_account"
},
"outputs": [],
"source": [
"SERVICE_ACCOUNT = \"[your-service-account]\" # @param {type:\"string\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "autoset_service_account"
},
"outputs": [],
"source": [
"if (\n",
" SERVICE_ACCOUNT == \"\"\n",
" or SERVICE_ACCOUNT is None\n",
" or SERVICE_ACCOUNT == \"[your-service-account]\"\n",
"):\n",
" # Get your service account from gcloud\n",
" if not IS_COLAB:\n",
" shell_output = !gcloud auth list 2>/dev/null\n",
" SERVICE_ACCOUNT = shell_output[2].replace(\"*\", \"\").strip()\n",
"\n",
" if IS_COLAB:\n",
" shell_output = ! gcloud projects describe $PROJECT_ID\n",
" project_number = shell_output[-1].split(\":\")[1].strip().replace(\"'\", \"\")\n",
" SERVICE_ACCOUNT = f\"{project_number}-compute@developer.gserviceaccount.com\"\n",
"\n",
" print(\"Service Account:\", SERVICE_ACCOUNT)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "set_service_account:pipelines"
},
"source": [
"#### Set service account access for Vertex AI Pipelines\n",
"\n",
"Run the following commands to grant your service account access to read and write pipeline artifacts in the bucket that you created in the previous step -- you only need to run these once per service account."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_service_account:pipelines"
},
"outputs": [],
"source": [
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectCreator \n",
"! gsutil iam ch serviceAccount:{SERVICE_ACCOUNT}:roles/storage.objectViewer "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "setup_vars"
},
"source": [
"### Set up variables\n",
"\n",
"Next, set up some variables used throughout the tutorial.\n",
"### Import libraries and define constants"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "import_kfp"
},
"outputs": [],
"source": [
"import json\n",
"\n",
"import google.cloud.aiplatform as aiplatform\n",
"from kfp.registry import RegistryClient"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "init_aip:mbsdk,all"
},
"source": [
"### Initialize Vertex AI SDK for Python\n",
"\n",
"Initialize the Vertex AI SDK for Python for your project and corresponding bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "init_aip:mbsdk,all"
},
"outputs": [],
"source": [
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_URI)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9b773e8d2bd2"
},
"source": [
"## Create repo in Artifact Registry\n",
"\n",
"First, you create your own (user-defined) repository in the `Artifact Registry`. You use this repository to upload and retreive your pipeline templates.\n",
"\n",
"The name of your repo is `quickstart-kfp-repo`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "520de849cee2"
},
"outputs": [],
"source": [
"REPO_NAME = \"quickstart-kfp-repo\"\n",
"\n",
"! gcloud artifacts repositories create {REPO_NAME} --location={REGION} --repository-format=KFP"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1611d3517c0f"
},
"source": [
"### Upload the pipeline template\n",
"\n",
"Next, you instantiate a client interface to the Artifact Registry. Then with the `upload_pipeline()` method you upload your pipeline template."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7f002e57998a"
},
"outputs": [],
"source": [
"T5X_YAML = \"gs://cloud-samples-data/vertex-ai/dataset-management/datasets/t5_finetuning/pipeline.yaml\"\n",
"\n",
"! gsutil cp {T5X_YAML} pipeline.yaml\n",
"\n",
"client = RegistryClient(\n",
" host=f\"https://{REGION}-kfp.pkg.dev/{PROJECT_ID}/quickstart-kfp-repo\"\n",
")\n",
"\n",
"templateName, versionName = client.upload_pipeline(\n",
" file_name=\"pipeline.yaml\",\n",
" tags=[\"v1\", \"latest\"],\n",
" extra_headers={\n",
" \"description\": \"This is a pipeline template for fine-tuning a T5 model.\"\n",
" },\n",
")\n",
"\n",
"! rm pipeline.yaml"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "02f82754fc0d"
},
"source": [
"### View your artifacts in your registry\n",
"\n",
"Next, using the `gcloud artifacts files` command you view the artifacts, inclusive of the pipeline template, in your artifacts repository."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "b2f641eb2056"
},
"outputs": [],
"source": [
"! gcloud artifacts files list --repository={REPO_NAME} --location={REGION}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "968a46a3cb6d"
},
"source": [
"## Load and execute the pipeline job\n",
"\n",
"Next, you create a Vertex AI Pipeline job from your T5 pipeline template by instantiating a PipelineJob(), with the following parameters:\n",
"\n",
"- `display_name`: The human readable name for the pipeline job.\n",
"- `template_path`: The path to the pipeline template in the Artifact Registry.\n",
"- `enable_caching`: On re-runs, use the results from previous successful and unchanged steps.\n",
"- `pipeline_root`: A Cloud storage location for storing pipeline results.\n",
"- `parameter_values`: The parameters and values that are input to the template pipeline. In this example, they are:\n",
"TODO\n",
" - `project`: Your project ID.\n",
" - `class_labels`: A list of valid class labels, in cardinal order.\n",
" - `root_dir`: A Cloud Storage scratch area.\n",
" - `training_data_path`: A Cloud Storage location to the training data.\n",
" - `ground_truth_gcs_source_uris`: A Cloud Storage location to evaluation data."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "a3c502fc7e41"
},
"outputs": [],
"source": [
"PIPELINE_ROOT = f\"{BUCKET_URI}/pipeline_root/t5_finetuning\"\n",
"\n",
"job = aiplatform.PipelineJob(\n",
" display_name=\"t5x-finetuning\",\n",
" template_path=f\"https://{REGION}-kfp.pkg.dev/{PROJECT_ID}/quickstart-kfp-repo/{templateName}/{versionName}\",\n",
" pipeline_root=PIPELINE_ROOT,\n",
" enable_caching=False,\n",
" parameter_values={\n",
" \"project_id\": PROJECT_ID,\n",
" \"accelerator_count\": 32,\n",
" \"feature_keys\": \"question\",\n",
" \"label_key\": \"answer\",\n",
" \"training_data_path\": \"gs://cloud-llm-public/tfds/natural_questions_open/1.0.0_shortened/natural_questions_open-train.tfrecord-00000-of-00001\",\n",
" \"validation_data_path\": \"gs://cloud-llm-public/tfds/natural_questions_open/1.0.0_shortened/natural_questions_open-validation.tfrecord-00000-of-00001\",\n",
" },\n",
")\n",
"\n",
"job.run()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "view_pipleline_results:bqml"
},
"source": [
"### View the pipeline results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "view_pipleline_results:bqml"
},
"outputs": [],
"source": [
"PROJECT_NUMBER = job.gca_resource.name.split(\"/\")[1]\n",
"print(PROJECT_NUMBER)\n",
"\n",
"\n",
"def print_pipeline_output(job, output_task_name):\n",
" JOB_ID = job.name\n",
" print(JOB_ID)\n",
" artifact = \"\"\n",
" for _ in range(len(job.gca_resource.job_detail.task_details)):\n",
" TASK_ID = job.gca_resource.job_detail.task_details[_].task_id\n",
" EXECUTE_OUTPUT = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/executor_output.json\"\n",
" )\n",
" GCP_RESOURCES = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/gcp_resources\"\n",
" )\n",
" EVALUATION_METRICS = (\n",
" PIPELINE_ROOT\n",
" + \"/\"\n",
" + PROJECT_NUMBER\n",
" + \"/\"\n",
" + JOB_ID\n",
" + \"/\"\n",
" + output_task_name\n",
" + \"_\"\n",
" + str(TASK_ID)\n",
" + \"/evaluation_metrics\"\n",
" )\n",
" # Check if file exists, 0 is success\n",
" !gsutil -q stat $EXECUTE_OUTPUT\n",
" if _exit_code == 0:\n",
" ! gsutil cat $EXECUTE_OUTPUT\n",
" artifact = EXECUTE_OUTPUT\n",
" break\n",
" !gsutil -q stat $GCP_RESOURCES\n",
" if _exit_code == 0:\n",
" ! gsutil cat $GCP_RESOURCES\n",
" artifact = GCP_RESOURCES\n",
" break\n",
" !gsutil -q stat $EVALUATION_METRICS\n",
" if _exit_code == 0:\n",
" ! gsutil cat $EVALUATION_METRICS\n",
" artifact = EVALUATION_METRICS\n",
" break\n",
"\n",
" return artifact\n",
"\n",
"\n",
"print(\"model-upload\")\n",
"artifacts = print_pipeline_output(job, \"model-upload\")\n",
"output = !gsutil cat $artifacts\n",
"print(output)\n",
"output = json.loads(output[0])\n",
"model_id = output[\"artifacts\"][\"model\"][\"artifacts\"][0][\"metadata\"][\"resourceName\"]\n",
"print(\"\\n\\n\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f431a9e6f025"
},
"source": [
"### Delete the pipeline job\n",
"\n",
"The method 'delete()' will delete the pipeline job."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "00bf554abbc6"
},
"outputs": [],
"source": [
"job.delete()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3d183db57ae2"
},
"source": [
"### Deploy the model\n",
"\n",
"Next, you deploy the model to an endpoint:\n",
"\n",
"- Use the `model_id` obtained from the pipeline artifacts to instantiate a Vertex AI Model resource instance.\n",
"- Deploy the Vertex AI Model resource to a Vertex AI Endpoint resource.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "591ccc049ce5"
},
"outputs": [],
"source": [
"model = aiplatform.Model(model_id)\n",
"endpoint = model.deploy(\n",
" accelerator_count=1,\n",
" accelerator_type=aiplatform.gapic.AcceleratorType.NVIDIA_TESLA_T4.name,\n",
" machine_type=\"n1-standard-4\",\n",
")\n",
"print(endpoint)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "edb781a92864"
},
"source": [
"### Make a prediction\n",
"\n",
"Finally, you make a prediction with the deployed model."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "72d94012a987"
},
"outputs": [],
"source": [
"endpoint.predict([\"this is a test\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cleanup:mbsdk"
},
"source": [
"# Cleaning up\n",
"\n",
"To clean up all Google Cloud resources used in this project, you can [delete the Google Cloud\n",
"project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#shutting_down_projects) you used for the tutorial.\n",
"\n",
"Otherwise, you can delete the individual resources you created in this tutorial."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "cleanup:mbsdk"
},
"outputs": [],
"source": [
"delete_bucket = True\n",
"\n",
"endpoint.undeploy_all()\n",
"endpoint.delete()\n",
"model.delete()\n",
"\n",
"if delete_bucket or os.getenv(\"IS_TESTING\"):\n",
" ! gsutil rm -r $BUCKET_URI\n",
"\n",
"! rm -rf custom custom.tar.gz"
]
}
],
"metadata": {
"colab": {
"name": "model_garden_pipeline_templates_t5x.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -184,7 +184,9 @@
"\n",
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
"\n",
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs.\n",
"\n",
"1. [Create a service account](https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console) with `Vertex AI User` and `Storage Object Admin` roles for deploying fine tuned model to Vertex AI endpoint."
]
},
{
@@ -211,7 +213,10 @@
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
"GCS_BUCKET = \"\" # @param {type:\"string\"}\n",
"\n",
"# The service account you created in step-5 above, it's like \"<account_name>@<project>.iam.gserviceaccount.com\"\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
@@ -271,7 +276,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {
"id": "354da31189dc"
},
@@ -336,8 +341,6 @@
" \"MODEL_ID\": model_id,\n",
" \"TASK\": task,\n",
" }\n",
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
" model = aiplatform.Model.upload(\n",
" display_name=model_name,\n",
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
@@ -345,7 +348,6 @@
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
" serving_container_health_route=\"/ping\",\n",
" serving_container_environment_variables=serving_env,\n",
" artifact_uri=artifact_uri,\n",
" )\n",
" model.deploy(\n",
" endpoint=endpoint,\n",
@@ -353,6 +355,7 @@
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
" accelerator_count=1,\n",
" deploy_request_timeout=1800,\n",
" service_account=SERVICE_ACCOUNT,\n",
" )\n",
" return model, endpoint"
]
@@ -427,6 +430,8 @@
" \"--resolution=512\",\n",
" \"--learning_rate=1e-5\",\n",
" \"--train_batch_size=2\",\n",
" \"--checkpointing_steps=50000\",\n",
" \"--checkpoints_total_limit=1\",\n",
" ],\n",
" replica_count=num_nodes,\n",
" machine_type=machine_type,\n",
@@ -572,7 +577,7 @@
"outputs": [],
"source": [
"model, endpoint = deploy_model(\n",
" model_id=f\"gs://{GCS_BUCKET}/controlnet/output\", task=\"image-to-image\"\n",
" model_id=f\"gs://{GCS_BUCKET}/controlnet/output\", task=\"controlnet\"\n",
")"
]
},
@@ -45,7 +45,7 @@
" </a>\n",
" </td>\n",
" <td> <td>\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_detectron2.ipynb\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_detectron2.ipynb\">\n",
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
"Open in Vertex AI Workbench\n",
" </a>\n",
@@ -189,7 +189,9 @@
"\n",
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
"\n",
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs.\n",
"\n",
"1. [Create a service account](https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console) with `Vertex AI User`, `Storage Object Admin`, and `GCS Storage Bucket Owner` roles for deploying fine tuned model to Vertex AI endpoint."
]
},
{
@@ -213,10 +215,16 @@
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
"\n",
"# The region you want to launch jobs in.\n",
"REGION = \"\" # @param {type:\"string\"}\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket for storing experiments output. For example 'gs://my_bucket'.\n",
"BUCKET_URI = \"\" # @param {type:\"string\"}"
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
"\n",
"# The service account for deploying fine tuned model.\n",
"# The service account looks like:\n",
"# '<account_name>@<project>.iam.gserviceaccount.com'\n",
"# Follow step 5 above to create this account.\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
@@ -814,7 +822,8 @@
},
"outputs": [],
"source": [
"local_balloon_data_directory = \"balloon\" # @param {type:\"string\"}"
"local_balloon_data_directory = \"balloon\" # @param {type:\"string\"}\n",
"BALLOON_DATA_GCS_PATH = os.path.join(BUCKET_URI, \"balloon_dataset\")"
]
},
{
@@ -902,14 +911,47 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "oOfgze5RpJQ8"
"id": "0OykIZen9gCC"
},
"outputs": [],
"source": [
"# Move Balloon data from local directory to Cloud Storage.\n",
"BALLOON_DATA_GCS_PATH = os.path.join(BUCKET_URI, \"balloon_dataset\")\n",
"!gsutil -m cp -r $local_balloon_data_directory/* $BALLOON_DATA_GCS_PATH/\n",
"!gsutil ls $BALLOON_DATA_GCS_PATH"
"\n",
"import glob\n",
"\n",
"from google.cloud import storage\n",
"\n",
"\n",
"def get_bucket_and_blob_name(filepath):\n",
" # The gcs path is of the form gs://<bucket-name>/<blob-name>\n",
" gs_suffix = filepath.split(\"gs://\", 1)[1]\n",
" return tuple(gs_suffix.split(\"/\", 1))\n",
"\n",
"\n",
"def upload_local_dir_to_gcs(local_dir_path, gcs_dir_path):\n",
" \"\"\"Uploads files in a local directory to a GCS directory.\"\"\"\n",
" client = storage.Client()\n",
" bucket_name = gcs_dir_path.split(\"/\")[2]\n",
" bucket = client.get_bucket(bucket_name)\n",
" for local_file in glob.glob(local_dir_path + \"/**\"):\n",
" if not os.path.isfile(local_file):\n",
" continue\n",
" filename = local_file[1 + len(local_dir_path) :]\n",
" gcs_file_path = os.path.join(gcs_dir_path, filename)\n",
" _, blob_name = get_bucket_and_blob_name(gcs_file_path)\n",
" blob = bucket.blob(blob_name)\n",
" blob.upload_from_filename(local_file)\n",
" print(\"Copied {} to {}.\".format(local_file, gcs_file_path))\n",
"\n",
"\n",
"upload_local_dir_to_gcs(\n",
" os.path.join(local_balloon_data_directory, \"train\"),\n",
" os.path.join(BALLOON_DATA_GCS_PATH, \"train\"),\n",
")\n",
"upload_local_dir_to_gcs(\n",
" os.path.join(local_balloon_data_directory, \"val\"),\n",
" os.path.join(BALLOON_DATA_GCS_PATH, \"val\"),\n",
")"
]
},
{
@@ -944,26 +986,22 @@
"train_dataset_name = \"balloon_train\" # @param {type:\"string\"}\n",
"train_coco_json_file = os.path.join(\n",
" BALLOON_DATA_GCS_PATH, \"train/balloon_train_coco_format.json\"\n",
") # @param {type:\"string\"}\n",
")\n",
"train_coco_json_file = gcs_fuse_path(train_coco_json_file)\n",
"train_image_root = os.path.join(\n",
" BALLOON_DATA_GCS_PATH, \"train\"\n",
") # @param {type:\"string\"}\n",
"train_image_root = os.path.join(BALLOON_DATA_GCS_PATH, \"train\")\n",
"train_image_root = gcs_fuse_path(train_image_root)\n",
"val_dataset_name = \"balloon_val\" # @param {type:\"string\"}\n",
"val_coco_json_file = os.path.join(\n",
" BALLOON_DATA_GCS_PATH, \"val/balloon_val_coco_format.json\"\n",
") # @param {type:\"string\"}\n",
")\n",
"val_coco_json_file = gcs_fuse_path(val_coco_json_file)\n",
"val_image_root = os.path.join(BALLOON_DATA_GCS_PATH, \"val\") # @param {type:\"string\"}\n",
"val_image_root = os.path.join(BALLOON_DATA_GCS_PATH, \"val\")\n",
"val_image_root = gcs_fuse_path(val_image_root)\n",
"output_dir = os.path.join(BUCKET_URI, JOB_NAME)\n",
"\n",
"#################################################\n",
"# Model and dataset related parameters for Mask R-CNN.\n",
"config_file = (\n",
" \"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\" # @param {type:\"string\"}\n",
")\n",
"config_file = \"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml\"\n",
"config_file = gcs_fuse_path(config_file)\n",
"remainder_args_list = []\n",
"remainder_args_list += [\"DATASETS.TRAIN\"] + [\n",
@@ -982,7 +1020,7 @@
"\n",
"# #################################################\n",
"# # Model and dataset related parameters for RetinaNet.\n",
"# config_file='COCO-Detection/retinanet_R_50_FPN_3x.yaml' # @param {type:\"string\"}\n",
"# config_file='COCO-Detection/retinanet_R_50_FPN_3x.yaml'\n",
"# config_file = gcs_fuse_path(config_file)\n",
"# remainder_args_list = []\n",
"# remainder_args_list += ['DATASETS.TRAIN'] + ['(\"{train_dataset_name}\",)'.format(train_dataset_name=train_dataset_name)]\n",
@@ -998,7 +1036,7 @@
"\n",
"# #################################################\n",
"# # Model and dataset related parameters for Faster R-CNN.\n",
"# config_file='COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml' # @param {type:\"string\"}\n",
"# config_file='COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml'\n",
"# config_file = gcs_fuse_path(config_file)\n",
"# remainder_args_list = []\n",
"# remainder_args_list += ['DATASETS.TRAIN'] + ['(\"{train_dataset_name}\",)'.format(train_dataset_name=train_dataset_name)]\n",
@@ -1054,7 +1092,6 @@
"job = aiplatform.CustomContainerTrainingJob(\n",
" display_name=JOB_NAME,\n",
" container_uri=container_uri,\n",
" command=[\"python\", \"-m\", \"trainer.task\"],\n",
")\n",
"model = job.run(\n",
" args=docker_args_list,\n",
@@ -1088,17 +1125,13 @@
"# Upload models to model registry\n",
"from datetime import datetime\n",
"\n",
"PRETRAINED_MODEL_PTH_FILE = os.path.join(\n",
" output_dir, \"model_final.pth\"\n",
") # @param {type:\"string\"}\n",
"PRETRAINED_MODEL_CFG_YAML_FILE = os.path.join(\n",
" output_dir, \"config.yaml\"\n",
") # @param {type:\"string\"}\n",
"PRETRAINED_MODEL_PTH_FILE = os.path.join(output_dir, \"model_final.pth\")\n",
"PRETRAINED_MODEL_CFG_YAML_FILE = os.path.join(output_dir, \"config.yaml\")\n",
"TEST_THRESHOLD = 0.7\n",
"PREDICTION_CONTAINER_URI = SERVE_DOCKER_URI\n",
"PREDICTION_DISPLAY_NAME = \"upload_detectron2_\" + datetime.now().strftime(\n",
" \"%Y%m%d_%H%M%S\"\n",
") # @param {type:\"string\"}\n",
")\n",
"\n",
"model = upload_model(\n",
" project=PROJECT_ID,\n",
@@ -1123,9 +1156,7 @@
"# Deploy uploaded models\n",
"from datetime import datetime\n",
"\n",
"DEPLOYED_NAME = \"deploy_iod_\" + datetime.now().strftime(\n",
" \"%Y%m%d_%H%M%S\"\n",
") # @param {type:\"string\"}\n",
"DEPLOYED_NAME = \"deploy_iod_\" + datetime.now().strftime(\"%Y%m%d_%H%M%S\")\n",
"MACHINE_TYPE = \"n1-highmem-16\" # @param {type:\"string\"}\n",
"\n",
"TRAFFIC_SPLIT = {\"0\": 100}\n",
@@ -1133,13 +1164,13 @@
"MIN_NODES = 1\n",
"MAX_NODES = 1\n",
"\n",
"\n",
"endpoint = model.deploy(\n",
" deployed_model_display_name=DEPLOYED_NAME,\n",
" traffic_split=TRAFFIC_SPLIT,\n",
" machine_type=MACHINE_TYPE,\n",
" min_replica_count=MIN_NODES,\n",
" max_replica_count=MAX_NODES,\n",
" service_account=SERVICE_ACCOUNT,\n",
")\n",
"\n",
"print(\"endpoint id is: \", endpoint.name)"
@@ -1155,11 +1186,12 @@
"source": [
"# Run predictions\n",
"# Fill the \"endpoint_id\" from previous step below.\n",
"# For example 'endpoint_id = \"8211918096324100096\"'.\n",
"\n",
"endpoint_id = \"1218390824971141120\" # @param {type:\"string\"}\n",
"endpoint_id = \"\" # @param {type:\"string\"}\n",
"local_test_filepath = os.path.join(\n",
" local_balloon_data_directory, \"val/410488422_5f8991f26e_b.jpg\"\n",
") # @param {type:\"string\"}\n",
")\n",
"instances = get_prediction_instances(local_test_filepath)\n",
"api_endpoint = REGION + \"-aiplatform.googleapis.com\"\n",
"\n",
@@ -1182,7 +1214,7 @@
"boxes = prediction[\"boxes\"]\n",
"classes = prediction[\"classes\"]\n",
"scores = prediction[\"scores\"]\n",
"if \"masks_rle\" in prediction:\n",
"if prediction[\"masks_rle\"]:\n",
" masks_numpy = decode_rle_masks(prediction[\"masks_rle\"])\n",
"else:\n",
" masks_numpy = None\n",
@@ -24,6 +24,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "99c1c3fc2ca5"
@@ -48,12 +49,13 @@
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
"Open in Vertex AI Workbench\n",
" </a>\n",
" (a Python-3 CPU notebook is recommended)\n",
" (a Python-3 GPU notebook with preinstalled HuggingFace/transformer libraries is recommended)\n",
" </td>\n",
"</table>"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "3de7470326a2"
@@ -61,13 +63,15 @@
"source": [
"## Overview\n",
"\n",
"This notebook demonstrates finetuning [runwayml/stable-diffusion-v1-5](https://huggingface.co/runwayml/stable-diffusion-v1-5) with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth) and deploying it on Vertex AI for online prediction.\n",
"This notebook demonstrates running local inference on [Vertex AI Workbench](https://cloud.google.com/vertex-ai-workbench).\n",
"This notebook also demonstrates finetuning [runwayml/stable-diffusion-v1-5](https://huggingface.co/runwayml/stable-diffusion-v1-5) with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth) and deploying it on Vertex AI for online prediction.\n",
"\n",
"### Objective\n",
"\n",
"- Run local predictions for text-to-image and text-guided-image-to-image with serving dockers.\n",
"- Finetune the stable-diffusion-v1.5 model with [Dreambooth](https://huggingface.co/docs/diffusers/training/dreambooth).\n",
"- Upload the model to [Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
"- Deploy the model on [Endpoint](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
"- Upload the model to [Vertex AI Model Registry](https://cloud.google.com/vertex-ai/docs/model-registry/introduction).\n",
"- Deploy the model to a [Vertex AI Endpoint resource](https://cloud.google.com/vertex-ai/docs/predictions/using-private-endpoints).\n",
"- Run online predictions for text-to-image and text-guided-image-to-image.\n",
"\n",
"### Costs\n",
@@ -81,6 +85,114 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "e8a42fa49305"
},
"source": [
"## Local inference (Workbench only)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "1169c41b76b3"
},
"source": [
"The quickest and easiest way to use this model locally is by using Vertex AI Workbench with a pre-built custom container that has the necessary packages installed.\n",
"\n",
"\n",
"\n",
"1. Follow [this link](https://console.cloud.google.com/vertex-ai/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_stable_diffusion.ipynb) to deploy the notebook to a Vertex AI Workbench Instance.\n",
"2. Select `Create a new Notebook`.\n",
"3. Click `Advanced Options`.\n",
"4. Under **Environment**, select `Custom Container` for `Environment`. \n",
"5. Set `Docker container image` to `us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/transformers-notebook`.\n",
"6. Under **Machine configuration**, select a GPU and select `Install NVIDIA GPU driver automatically for me`.\n",
"7. Click `Create` to create the Vertex AI Workbench instance. \n",
"\n",
"Once the notebook is ready, simply execute the code block(s) below in the Workbench instance."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "1d5ebc91c786"
},
"source": [
"### Text-to-image"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "d39ed8c97cc5"
},
"outputs": [],
"source": [
"import torch\n",
"from diffusers import StableDiffusionPipeline\n",
"\n",
"model_id = \"runwayml/stable-diffusion-v1-5\"\n",
"pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)\n",
"pipe = pipe.to(\"cuda\")\n",
"\n",
"prompt = \"a photo of an astronaut riding a horse on mars\"\n",
"image = pipe(prompt).images[0]\n",
"\n",
"display(image)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "5aed5ed7b6f6"
},
"source": [
"### Text-guided image-to-image"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "faadabb7728f"
},
"outputs": [],
"source": [
"from io import BytesIO\n",
"\n",
"import requests\n",
"import torch\n",
"from diffusers import StableDiffusionImg2ImgPipeline\n",
"from PIL import Image\n",
"\n",
"device = \"cuda\"\n",
"model_id_or_path = \"runwayml/stable-diffusion-v1-5\"\n",
"pipe = StableDiffusionImg2ImgPipeline.from_pretrained(\n",
" model_id_or_path, torch_dtype=torch.float16\n",
")\n",
"pipe = pipe.to(device)\n",
"\n",
"url = \"https://raw.githubusercontent.com/CompVis/stable-diffusion/main/assets/stable-samples/img2img/sketch-mountains-input.jpg\"\n",
"\n",
"response = requests.get(url)\n",
"init_image = Image.open(BytesIO(response.content)).convert(\"RGB\")\n",
"init_image = init_image.resize((768, 512))\n",
"\n",
"prompt = \"A fantasy landscape, trending on artstation\"\n",
"\n",
"images = pipe(prompt=prompt, image=init_image, strength=0.75, guidance_scale=7.5).images\n",
"display(images[0])"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "264c07757582"
@@ -92,6 +204,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "d73ffa0c0b83"
@@ -125,6 +238,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "fb671e75ca7b"
@@ -142,12 +256,11 @@
"outputs": [],
"source": [
"# Install gdown for downloading example training images.\n",
"!pip install gdown\n",
"# Install gsutil for downloading/uploading data from/to Cloud Storage buckets.\n",
"!pip install gsutil"
"!pip install gdown"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "5244aac3d929"
@@ -171,6 +284,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "bb7adab99e41"
@@ -184,10 +298,13 @@
"\n",
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
"\n",
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs.\n",
"\n",
"1. [Create a service account](https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console) with `Vertex AI User` and `Storage Object Admin` roles for deploying fine tuned model to Vertex AI endpoint."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "6c460088b873"
@@ -211,10 +328,14 @@
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
"GCS_BUCKET = \"\" # @param {type:\"string\"}\n",
"\n",
"# The service account for deploying fine tuned model.\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "e828eb320337"
@@ -237,6 +358,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "2cc825514deb"
@@ -261,6 +383,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "0c250872074f"
@@ -278,12 +401,13 @@
"outputs": [],
"source": [
"import base64\n",
"import glob\n",
"import os\n",
"from datetime import datetime\n",
"from io import BytesIO\n",
"\n",
"import requests\n",
"from google.cloud import aiplatform\n",
"from google.cloud import aiplatform, storage\n",
"from PIL import Image\n",
"\n",
"\n",
@@ -326,8 +450,6 @@
" \"MODEL_ID\": model_id,\n",
" \"TASK\": task,\n",
" }\n",
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
" model = aiplatform.Model.upload(\n",
" display_name=model_name,\n",
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
@@ -335,7 +457,6 @@
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
" serving_container_health_route=\"/ping\",\n",
" serving_container_environment_variables=serving_env,\n",
" artifact_uri=artifact_uri,\n",
" )\n",
" model.deploy(\n",
" endpoint=endpoint,\n",
@@ -343,11 +464,35 @@
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
" accelerator_count=1,\n",
" deploy_request_timeout=1800,\n",
" service_account=SERVICE_ACCOUNT,\n",
" )\n",
" return model, endpoint"
" return model, endpoint\n",
"\n",
"\n",
"def get_bucket_and_blob_name(filepath):\n",
" # The gcs path is of the form gs://<bucket-name>/<blob-name>\n",
" gs_suffix = filepath.split(\"gs://\", 1)[1]\n",
" return tuple(gs_suffix.split(\"/\", 1))\n",
"\n",
"\n",
"def upload_local_dir_to_gcs(local_dir_path, gcs_dir_path):\n",
" \"\"\"Uploads files in a local directory to a GCS directory.\"\"\"\n",
" client = storage.Client()\n",
" bucket_name = gcs_dir_path.split(\"/\")[2]\n",
" bucket = client.get_bucket(bucket_name)\n",
" for local_file in glob.glob(local_dir_path + \"/**\"):\n",
" if not os.path.isfile(local_file):\n",
" continue\n",
" filename = local_file[1 + len(local_dir_path) :]\n",
" gcs_file_path = os.path.join(gcs_dir_path, filename)\n",
" _, blob_name = get_bucket_and_blob_name(gcs_file_path)\n",
" blob = bucket.blob(blob_name)\n",
" blob.upload_from_filename(local_file)\n",
" print(\"Copied {} to {}.\".format(local_file, gcs_file_path))"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "e70e3519ff8b"
@@ -357,6 +502,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "0dc65d8f0689"
@@ -381,11 +527,12 @@
"!gdown --folder https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ\n",
"\n",
"# Upload data to Cloud Storage bucket.\n",
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog/\n",
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog_class/"
"upload_local_dir_to_gcs(\"dog\", f\"gs://{GCS_BUCKET}/dreambooth/dog\")\n",
"upload_local_dir_to_gcs(\"dog\", f\"gs://{GCS_BUCKET}/dreambooth/dog_class\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "969cfeb79317"
@@ -455,6 +602,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "bf7f82732e61"
@@ -464,6 +612,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "1cc26e68d7b0"
@@ -475,6 +624,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "cd7b56421392"
@@ -484,6 +634,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "6d331b1ea337"
@@ -504,13 +655,14 @@
},
"outputs": [],
"source": [
"# Set the model_id to a GCS path, like \"gs://GCS_BUCKET/dreambooth/output\", to load the dreambooth finetuned model above.\n",
"# Set the model_id to \"runwayml/stable-diffusion-v1-5\" to load the OSS pre-trained model.\n",
"model, endpoint = deploy_model(\n",
" model_id=\"runwayml/stable-diffusion-v1-5\", task=\"text-to-image\"\n",
" model_id=f\"gs://{GCS_BUCKET}/dreambooth/output\", task=\"text-to-image\"\n",
")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "80b3fd2ace09"
@@ -539,6 +691,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "af21a3cff1e0"
@@ -563,6 +716,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "c1e51f764a60"
@@ -572,6 +726,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "fa686a54047c"
@@ -595,6 +750,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "80b3fd2ace09"
@@ -627,6 +783,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ed3795d474b9"
@@ -142,9 +142,7 @@
"outputs": [],
"source": [
"# Install gdown for downloading example training images.\n",
"!pip install gdown\n",
"# Install gsutil for downloading/uploading data from/to Cloud Storage buckets.\n",
"!pip install gsutil"
"!pip install gdown"
]
},
{
@@ -184,7 +182,9 @@
"\n",
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
"\n",
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs."
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs.\n",
"\n",
"1. [Create a service account](https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console) with `Vertex AI User` and `Storage Object Admin` roles for deploying fine tuned model to Vertex AI endpoint."
]
},
{
@@ -210,8 +210,14 @@
"# The region you want to launch jobs in.\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket for storing experiments output. Fill it without the 'gs://' prefix.\n",
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
"# The Cloud Storage bucket for storing experiments output.\n",
"# Fill it without the 'gs://' prefix.\n",
"GCS_BUCKET = \"\" # @param {type:\"string\"}\n",
"\n",
"# The service account for deploying fine tuned model.\n",
"# The service account looks like:\n",
"# '<account_name>@<project>.iam.gserviceaccount.com'\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
@@ -271,19 +277,20 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {
"id": "8759e624ebc0"
},
"outputs": [],
"source": [
"import base64\n",
"import glob\n",
"import os\n",
"from datetime import datetime\n",
"from io import BytesIO\n",
"\n",
"import requests\n",
"from google.cloud import aiplatform\n",
"from google.cloud import aiplatform, storage\n",
"from PIL import Image\n",
"\n",
"\n",
@@ -326,8 +333,6 @@
" \"MODEL_ID\": model_id,\n",
" \"TASK\": task,\n",
" }\n",
" # If the model_id is a GCS path, use artifact_uri to pass it to serving docker.\n",
" artifact_uri = model_id if model_id.startswith(\"gs://\") else None\n",
" model = aiplatform.Model.upload(\n",
" display_name=model_name,\n",
" serving_container_image_uri=SERVE_DOCKER_URI,\n",
@@ -335,7 +340,6 @@
" serving_container_predict_route=\"/predictions/diffusers_serving\",\n",
" serving_container_health_route=\"/ping\",\n",
" serving_container_environment_variables=serving_env,\n",
" artifact_uri=artifact_uri,\n",
" )\n",
" model.deploy(\n",
" endpoint=endpoint,\n",
@@ -343,8 +347,31 @@
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
" accelerator_count=1,\n",
" deploy_request_timeout=1800,\n",
" service_account=SERVICE_ACCOUNT,\n",
" )\n",
" return model, endpoint"
" return model, endpoint\n",
"\n",
"\n",
"def get_bucket_and_blob_name(filepath):\n",
" # The gcs path is of the form gs://<bucket-name>/<blob-name>\n",
" gs_suffix = filepath.split(\"gs://\", 1)[1]\n",
" return tuple(gs_suffix.split(\"/\", 1))\n",
"\n",
"\n",
"def upload_local_dir_to_gcs(local_dir_path, gcs_dir_path):\n",
" \"\"\"Uploads files in a local directory to a GCS directory.\"\"\"\n",
" client = storage.Client()\n",
" bucket_name = gcs_dir_path.split(\"/\")[2]\n",
" bucket = client.get_bucket(bucket_name)\n",
" for local_file in glob.glob(local_dir_path + \"/**\"):\n",
" if not os.path.isfile(local_file):\n",
" continue\n",
" filename = local_file[1 + len(local_dir_path) :]\n",
" gcs_file_path = os.path.join(gcs_dir_path, filename)\n",
" _, blob_name = get_bucket_and_blob_name(gcs_file_path)\n",
" blob = bucket.blob(blob_name)\n",
" blob.upload_from_filename(local_file)\n",
" print(\"Copied {} to {}.\".format(local_file, gcs_file_path))"
]
},
{
@@ -381,17 +408,8 @@
"!gdown --folder https://drive.google.com/drive/folders/1BO_dyz-p65qhBRRMRA4TbZ8qW4rB99JZ\n",
"\n",
"# Upload data to Cloud Storage bucket.\n",
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog/\n",
"!gsutil -m cp -r dog/* gs://{GCS_BUCKET}/dreambooth/dog_class/"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "969cfeb79317"
},
"source": [
"**NOTE**: If the upload step fails due to lacking of permission, you need to [grant the Storage Object Admin role](https://cloud.google.com/storage/docs/access-control/using-iam-permissions) for the Cloud account of the notebook."
"upload_local_dir_to_gcs(\"dog\", f\"gs://{GCS_BUCKET}/dreambooth/dog\")\n",
"upload_local_dir_to_gcs(\"dog\", f\"gs://{GCS_BUCKET}/dreambooth/dog_class\")"
]
},
{
@@ -504,9 +522,9 @@
},
"outputs": [],
"source": [
"# Set the model_id to a GCS path, like \"gs://GCS_BUCKET/dreambooth/output\", to load the dreambooth finetuned model above.\n",
"# Set the model_id to \"runwayml/stable-diffusion-inpainting\" to load the OSS pre-trained model.\n",
"model, endpoint = deploy_model(\n",
" model_id=\"runwayml/stable-diffusion-inpainting\", task=\"image-inpainting\"\n",
" model_id=f\"gs://{GCS_BUCKET}/dreambooth/output\", task=\"image-inpainting\"\n",
")"
]
},
@@ -104,7 +104,9 @@
"\n",
"1. [Create a Cloud Storage bucket](https://cloud.google.com/storage/docs/creating-buckets) for storing experiment outputs.\n",
"\n",
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component)."
"1. [Enable the Vertex AI API and Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,compute_component).\n",
"\n",
"1. [Create a service account](https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console) with `Vertex AI User` and `Storage Object Admin` roles for deploying fine tuned model to Vertex AI endpoint."
]
},
{
@@ -193,13 +195,18 @@
"# The region for running jobs.\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"\n",
"# The model you want to train and serve.\n",
"# The model you want to train and serve. Please select a model from the verified model list above.\n",
"# We use a ViT model as the example.\n",
"MODEL_NAME = \"vit_tiny_patch16_224\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket name without gs:// prefix for training outputs.\n",
"# For example: test_bucket\n",
"GCS_BUCKET = \"\" # @param {type:\"string\"}"
"GCS_BUCKET = \"\" # @param {type:\"string\"}\n",
"\n",
"# The service account for deploying fine tuned model. It looks like:\n",
"# '<account_name>@<project>.iam.gserviceaccount.com'\n",
"# Follow step 6 above to create this account.\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
@@ -225,7 +232,7 @@
},
"outputs": [],
"source": [
"# The training docker uri.\n",
"# The prebuilt training docker uri.\n",
"TRAIN_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-timm-train\"\n",
"\n",
"# The path to data directory on Cloud Storage without gs:// prefix.\n",
@@ -265,8 +272,8 @@
"# Single node with multiple GPUs.\n",
"machine_type = \"n1-highmem-32\"\n",
"num_nodes = 1\n",
"gpu_type = \"NVIDIA_TESLA_P100\"\n",
"num_gpus = 4\n",
"gpu_type = \"NVIDIA_TESLA_P100\" # @param {type:\"string\"}\n",
"num_gpus = 4 # @param {type:\"integer\"}\n",
"\n",
"# Model specific config.\n",
"job_name = f\"pytorch-{MODEL_NAME}\"\n",
@@ -336,8 +343,8 @@
"# Worker pool spec.\n",
"machine_type = \"n1-highmem-16\"\n",
"num_nodes = 1\n",
"gpu_type = \"NVIDIA_TESLA_V100\"\n",
"num_gpus = 2\n",
"gpu_type = \"NVIDIA_TESLA_V100\" # @param {type:\"string\"}\n",
"num_gpus = 2 # @param {type:\"integer\"}\n",
"worker_pool_specs = [\n",
" {\n",
" \"machine_spec\": {\n",
@@ -408,19 +415,14 @@
},
"outputs": [],
"source": [
"# The serve docker uri.\n",
"# The prebuilt serving docker uri.\n",
"SERVE_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-timm-serve\"\n",
"# The port number used by torchserve traffic.\n",
"SERVE_PORT = 7080\n",
"# The path to model checkpoint file, including gs:// prefix.\n",
"MODEL_PT_PATH = \"gs://path_to_model_best.pth.tar\" # @param {type:\"string\"}\n",
"# [Optional] the path to index_to_name.json, including gs:// prefix.\n",
"INDEX_TO_NAME_FILE = \"gs://path_to_index_to_name.json\" # @param {type:\"string\"}\n",
"\n",
"# Converts gs:// uris to /gcs/ to use GCS Fuse.\n",
"# See https://github.com/GoogleCloudPlatform/gcsfuse.\n",
"MODEL_PT_PATH = MODEL_PT_PATH.replace(\"gs://\", \"/gcs/\")\n",
"INDEX_TO_NAME_FILE = INDEX_TO_NAME_FILE.replace(\"gs://\", \"/gcs/\")"
"INDEX_TO_NAME_FILE = \"gs://path_to_index_to_name.json\" # @param {type:\"string\"}"
]
},
{
@@ -469,6 +471,7 @@
" accelerator_type=\"NVIDIA_TESLA_T4\",\n",
" accelerator_count=1,\n",
" traffic_percentage=100,\n",
" service_account=SERVICE_ACCOUNT,\n",
")"
]
},
@@ -506,10 +509,10 @@
"# endpoint = aiplatform.Endpoint('projects/816369962409/locations/us-central1/endpoints/8809168414485512192')\n",
"\n",
"# Please upload an image and enter its filename below.\n",
"IMAGE_FILENAME = \"cat.jpg\" # @param {type:\"string\"}\n",
"IMAGE_FILENAME = \"test.jpg\" # @param {type:\"string\"}\n",
"\n",
"# Alternatively, uncomment the follow line to download a cat image for demonstration.\n",
"# ! wget http://images.cocodataset.org/val2017/000000039769.jpg -O cat.jpg\n",
"# Alternatively, uncomment the following line to download a cat image for demonstration.\n",
"# ! wget http://images.cocodataset.org/val2017/000000039769.jpg -O test.jpg\n",
"\n",
"with open(IMAGE_FILENAME, \"rb\") as f:\n",
" image_b64 = base64.b64encode(f.read()).decode(\"utf-8\")\n",
@@ -118,7 +118,7 @@
},
"source": [
"### Colab Only\n",
"Run the following commands for colab and skip this section if you use workbench."
"Run the following commands for Colab and skip this section if you use Workbench."
]
},
{
@@ -181,7 +181,16 @@
"# The project and bucket are for experiments below.\n",
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
"REGION = \"us-central1\"\n",
"\n",
"# You can choose a region from https://cloud.google.com/about/locations.\n",
"# Only regions prefixed by \"us\", \"asia\", or \"europe\" are supported.\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"REGION_PREFIX = REGION.split(\"-\")[0]\n",
"assert REGION_PREFIX in (\n",
" \"us\",\n",
" \"europe\",\n",
" \"asia\",\n",
"), f'{REGION} is not supported. It must be prefixed by \"us\", \"asia\", or \"europe\".'\n",
"\n",
"! gcloud config set project $PROJECT_ID\n",
"\n",
@@ -231,13 +240,13 @@
"\n",
"# Data converter constants.\n",
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
"DATA_CONVERTER_CONTAINER = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter\"\n",
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"\n",
"# Training constants.\n",
"TRAINING_JOB_PREFIX = \"train\"\n",
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
"TRAIN_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss\"\n",
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_P100\"\n",
"TRAIN_NUM_GPU = 1\n",
@@ -247,7 +256,7 @@
"\n",
"# Export constants.\n",
"EXPORT_JOB_PREFIX = \"export\"\n",
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
"EXPORT_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving\"\n",
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"# Prediction constants.\n",
@@ -256,9 +265,7 @@
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
"# You can adjust accelerator types and machine types to get faster predictions.\n",
"PREDICTION_CONTAINER_URI = (\n",
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
")\n",
"PREDICTION_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
@@ -307,10 +314,9 @@
" endpoint_id: str,\n",
" instances: Union[Dict, List[Dict]],\n",
" location: str = \"us-central1\",\n",
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
"):\n",
" # The AI Platform services require regional API endpoints.\n",
" client_options = {\"api_endpoint\": api_endpoint}\n",
" client_options = {\"api_endpoint\": f\"{location}-aiplatform.googleapis.com\"}\n",
" # Initialize client that will be used to create and send requests.\n",
" # This client only needs to be created once, and can be reused for multiple requests.\n",
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
@@ -536,7 +542,7 @@
"# input_train_data_path = ''\n",
"# input_validation_data_path = ''\n",
"\n",
"experiment = \"ViT-s16\" # @param [\"ResNet-50\",\"ResNet-RS-50\",\"Efficientnetv2-m\",\"ViT-ti16\",\"ViT-s16\",\"ViT-b16\",\"ViT-l16\"]\n",
"experiment = \"ResNet-50\" # @param [\"ResNet-50\",\"ResNet-RS-50\",\"Efficientnetv2-m\",\"ViT-ti16\",\"ViT-s16\",\"ViT-b16\",\"ViT-l16\"]\n",
"\n",
"train_job_name = get_job_name_with_datetime(TRAINING_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
"model_dir = os.path.join(BUCKET_URI, train_job_name)\n",
@@ -562,6 +568,7 @@
" **{\n",
" \"experiment\": \"resnet_imagenet\",\n",
" \"config_file\": os.path.join(CONFIG_DIR, \"imagenet_resnet50_gpu.yaml\"),\n",
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/resnet/resnet-50-i224.tar.gz\",\n",
" },\n",
" ),\n",
" \"ResNet-RS-50\": dict(\n",
@@ -118,7 +118,7 @@
},
"source": [
"### Colab Only\n",
"Run the following commands for colab and skip this section if you use workbench."
"Run the following commands for Colab and skip this section if you are using Workbench."
]
},
{
@@ -181,27 +181,37 @@
"# The project and bucket are for experiments below.\n",
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
"REGION = \"us-central1\"\n",
"\n",
"# You can choose a region from https://cloud.google.com/about/locations.\n",
"# Only regions prefixed by \"us\", \"asia\", or \"europe\" are supported.\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"REGION_PREFIX = REGION.split(\"-\")[0]\n",
"assert REGION_PREFIX in (\n",
" \"us\",\n",
" \"europe\",\n",
" \"asia\",\n",
"), f'{REGION} is not supported. It must be prefixed by \"us\", \"asia\", or \"europe\".'\n",
"\n",
"! gcloud config set project $PROJECT_ID\n",
"\n",
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
"CHECKPOINT_BUCKET = os.path.join(BUCKET_URI, \"ckpt\")\n",
"\n",
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)\n",
"\n",
"# Download config files.\n",
"CONFIG_DIR = os.path.join(BUCKET_URI, \"config\")\n",
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet49_gpu_multiworker_mirrored.yaml\n",
"! gsutil cp coco_spinenet49_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
"! gsutil cp coco_spinenet49_gpu_multiworker_mirrored.yaml $CONFIG_DIR/\n",
"\n",
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet96_gpu_multiworker_mirrored.yaml\n",
"! gsutil cp coco_spinenet96_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
"! gsutil cp coco_spinenet96_gpu_multiworker_mirrored.yaml $CONFIG_DIR/\n",
"\n",
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/retinanet/coco_spinenet143_gpu_multiworker_mirrored.yaml\n",
"! gsutil cp coco_spinenet143_gpu_multiworker_mirrored.yaml $CONFIG_DIR\n",
"! gsutil cp coco_spinenet143_gpu_multiworker_mirrored.yaml $CONFIG_DIR/\n",
"\n",
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/projects/yolo/configs/experiments/yolov4/detection/scaled_yolov4_1280_gpu.yaml\n",
"! gsutil cp scaled_yolov4_1280_gpu.yaml $CONFIG_DIR"
"! gsutil cp scaled_yolov4_1280_gpu.yaml $CONFIG_DIR/"
]
},
{
@@ -225,13 +235,13 @@
"\n",
"# Data converter constants.\n",
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
"DATA_CONVERTER_CONTAINER = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter\"\n",
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"\n",
"# Training constants.\n",
"TRAINING_JOB_PREFIX = \"train\"\n",
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
"TRAIN_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss\"\n",
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_V100\"\n",
"TRAIN_NUM_GPU = 2\n",
@@ -251,7 +261,7 @@
"\n",
"# Export constants.\n",
"EXPORT_JOB_PREFIX = \"export\"\n",
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
"EXPORT_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving\"\n",
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"# Prediction constants.\n",
@@ -260,9 +270,7 @@
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
"# You can adjust accelerator types and machine types to get faster predictions.\n",
"PREDICTION_CONTAINER_URI = (\n",
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
")\n",
"PREDICTION_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
@@ -313,10 +321,9 @@
" endpoint_id: str,\n",
" instances: Union[Dict, List[Dict]],\n",
" location: str = \"us-central1\",\n",
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
"):\n",
" # The AI Platform services require regional API endpoints.\n",
" client_options = {\"api_endpoint\": api_endpoint}\n",
" client_options = {\"api_endpoint\": f\"{location}-aiplatform.googleapis.com\"}\n",
" # Initialize client that will be used to create and send requests.\n",
" # This client only needs to be created once, and can be reused for multiple requests.\n",
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
@@ -469,7 +476,30 @@
" font,\n",
" display_str_list=[display_str],\n",
" )\n",
" return image"
" return image\n",
"\n",
"\n",
"def upload_checkpoint_to_gcs(checkpoint_url):\n",
" filename = os.path.basename(checkpoint_url)\n",
" checkpoint_name = filename.replace(\".tar.gz\", \"\")\n",
" print(\"Download checkpoint from\", checkpoint_url, \"and store to\", CHECKPOINT_BUCKET)\n",
" ! wget $checkpoint_url -O $filename\n",
" ! mkdir -p $checkpoint_name\n",
" ! tar -xvzf $filename -C $checkpoint_name\n",
"\n",
" # Search for relative path to the checkpoint.\n",
" checkpoint_path = None\n",
" for root, dirs, files in os.walk(checkpoint_name):\n",
" for file in files:\n",
" if file.endswith(\".index\"):\n",
" checkpoint_path = os.path.join(root, os.path.splitext(file)[0])\n",
" checkpoint_path = os.path.relpath(checkpoint_path, checkpoint_name)\n",
" break\n",
"\n",
" ! gsutil cp -r $checkpoint_name $CHECKPOINT_BUCKET/\n",
" checkpoint_uri = os.path.join(CHECKPOINT_BUCKET, checkpoint_name, checkpoint_path)\n",
" print(\"Checkpoint uploaded to\", checkpoint_uri)\n",
" return checkpoint_uri"
]
},
{
@@ -621,8 +651,8 @@
" \"objective\": OBJECTIVE,\n",
" \"model_dir\": model_dir,\n",
" \"num_classes\": num_classes,\n",
" \"global_batch_size\": 4,\n",
" \"prefetch_buffer_size\": 12,\n",
" \"global_batch_size\": 2,\n",
" \"prefetch_buffer_size\": 6,\n",
" \"train_steps\": 2000,\n",
" \"input_size\": \"1024,1024\",\n",
"}\n",
@@ -661,9 +691,19 @@
" **{\n",
" \"experiment\": \"scaled_yolo\",\n",
" \"config_file\": TRAIN_YOLOV4_CONFIG,\n",
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/yolo/scaled-yolov4/scaled-yolov4-l-p6-i1280.tar.gz\",\n",
" \"input_size\": \"1280,1280\",\n",
" },\n",
" ),\n",
"}\n",
"experiment_container_args = experiment_container_args_dict[experiment]\n",
"\n",
"# Copy checkpoint to GCS bucket if specified.\n",
"init_checkpoint = experiment_container_args.get(\"init_checkpoint\")\n",
"if init_checkpoint:\n",
" experiment_container_args[\"init_checkpoint\"] = upload_checkpoint_to_gcs(\n",
" init_checkpoint\n",
" )\n",
"\n",
"params_override = \"runtime.num_gpus=%s\" % TRAIN_NUM_GPU\n",
"eval_params_override = \"runtime.num_gpus=1,runtime.distribution_strategy=mirrored\"\n",
@@ -681,10 +721,7 @@
" \"--mode=train\",\n",
" \"--params_override=%s\" % params_override,\n",
" ]\n",
" + [\n",
" \"--{}={}\".format(k, v)\n",
" for k, v in experiment_container_args_dict[experiment].items()\n",
" ],\n",
" + [\"--{}={}\".format(k, v) for k, v in experiment_container_args.items()],\n",
" },\n",
" },\n",
" {},\n",
@@ -702,10 +739,7 @@
" \"--mode=continuous_eval\",\n",
" \"--params_override=%s\" % eval_params_override,\n",
" ]\n",
" + [\n",
" \"--{}={}\".format(k, v)\n",
" for k, v in experiment_container_args_dict[experiment].items()\n",
" ],\n",
" + [\"--{}={}\".format(k, v) for k, v in experiment_container_args.items()],\n",
" },\n",
" },\n",
"]\n",
@@ -807,8 +841,7 @@
" \"args\": [\n",
" \"--objective=%s\" % OBJECTIVE,\n",
" \"--input_image_size=1024,1024\",\n",
" \"--experiment=%s\"\n",
" % experiment_container_args_dict[experiment][\"experiment\"],\n",
" \"--experiment=%s\" % experiment_container_args[\"experiment\"],\n",
" \"--config_file=%s/params.yaml\" % best_trial_dir,\n",
" \"--checkpoint_path=%s/best_ckpt\" % best_trial_dir,\n",
" \"--export_dir=%s/best_model\" % model_dir,\n",
@@ -119,7 +119,7 @@
"source": [
"### Colab Only\n",
"\n",
"Run the following commands for colab and skip this section if you use workbench."
"Run the following commands for Colab and skip this section if you use Workbench."
]
},
{
@@ -182,18 +182,28 @@
"# The project and bucket are for experiments below.\n",
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
"REGION = \"us-central1\"\n",
"\n",
"# You can choose a region from https://cloud.google.com/about/locations.\n",
"# Only regions prefixed by \"us\", \"asia\", or \"europe\" are supported.\n",
"REGION = \"europe-west4\" # @param {type:\"string\"}\n",
"REGION_PREFIX = REGION.split(\"-\")[0]\n",
"assert REGION_PREFIX in (\n",
" \"us\",\n",
" \"europe\",\n",
" \"asia\",\n",
"), f'{REGION} is not supported. It must be prefixed by \"us\", \"asia\", or \"europe\".'\n",
"\n",
"! gcloud config set project $PROJECT_ID\n",
"\n",
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
"CHECKPOINT_BUCKET = os.path.join(BUCKET_URI, \"ckpt\")\n",
"\n",
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)\n",
"\n",
"# Download config files.\n",
"CONFIG_DIR = os.path.join(BUCKET_URI, \"config\")\n",
"! wget https://raw.githubusercontent.com/tensorflow/models/master/official/vision/configs/experiments/semantic_segmentation/deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml\n",
"! gsutil cp deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml $CONFIG_DIR"
"! gsutil cp deeplabv3plus_resnet101_cityscapes_gpu_multiworker_mirrored.yaml $CONFIG_DIR/"
]
},
{
@@ -217,13 +227,13 @@
"\n",
"# Data converter constants.\n",
"DATA_CONVERTER_JOB_PREFIX = \"data_converter\"\n",
"DATA_CONVERTER_CONTAINER = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter:latest\"\n",
"DATA_CONVERTER_CONTAINER = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/data-converter\"\n",
"DATA_CONVERTER_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"\n",
"# Training constants.\n",
"TRAINING_JOB_PREFIX = \"train\"\n",
"TRAIN_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss:latest\"\n",
"TRAIN_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss\"\n",
"TRAIN_MACHINE_TYPE = \"n1-highmem-16\"\n",
"TRAIN_ACCELERATOR_TYPE = \"NVIDIA_TESLA_V100\"\n",
"TRAIN_NUM_GPU = 2\n",
@@ -236,7 +246,7 @@
"\n",
"# Export constants.\n",
"EXPORT_JOB_PREFIX = \"export\"\n",
"EXPORT_CONTAINER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving:latest\"\n",
"EXPORT_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-serving\"\n",
"EXPORT_MACHINE_TYPE = \"n1-highmem-8\"\n",
"\n",
"# Prediction constants.\n",
@@ -245,9 +255,7 @@
"# and optimized tensorflow runtime dockers: https://cloud.google.com/vertex-ai/docs/predictions/optimized-tensorflow-runtime.\n",
"# The example in this notebook uses optimized tensorflow runtime dockers.\n",
"# You can adjust accelerator types and machine types to get faster predictions.\n",
"PREDICTION_CONTAINER_URI = (\n",
" \"us-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
")\n",
"PREDICTION_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/prediction/tf_opt-gpu.2-11:latest\"\n",
"SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
@@ -298,10 +306,9 @@
" endpoint_id: str,\n",
" instances: Union[Dict, List[Dict]],\n",
" location: str = \"us-central1\",\n",
" api_endpoint: str = \"us-central1-aiplatform.googleapis.com\",\n",
"):\n",
" # The AI Platform services require regional API endpoints.\n",
" client_options = {\"api_endpoint\": api_endpoint}\n",
" client_options = {\"api_endpoint\": f\"{location}-aiplatform.googleapis.com\"}\n",
" # Initialize client that will be used to create and send requests.\n",
" # This client only needs to be created once, and can be reused for multiple requests.\n",
" client = aiplatform.gapic.PredictionServiceClient(client_options=client_options)\n",
@@ -508,7 +515,30 @@
" ]\n",
" category_image_color = Image.fromarray(category_image_color_np)\n",
"\n",
" return score_image_grayscale, category_image_color"
" return score_image_grayscale, category_image_color\n",
"\n",
"\n",
"def upload_checkpoint_to_gcs(checkpoint_url):\n",
" filename = os.path.basename(checkpoint_url)\n",
" checkpoint_name = filename.replace(\".tar.gz\", \"\")\n",
" print(\"Download checkpoint from\", checkpoint_url, \"and store to\", CHECKPOINT_BUCKET)\n",
" ! wget $checkpoint_url -O $filename\n",
" ! mkdir -p $checkpoint_name\n",
" ! tar -xvzf $filename -C $checkpoint_name\n",
"\n",
" # Search for relative path to the checkpoint.\n",
" checkpoint_path = None\n",
" for root, dirs, files in os.walk(checkpoint_name):\n",
" for file in files:\n",
" if file.endswith(\".index\"):\n",
" checkpoint_path = os.path.join(root, os.path.splitext(file)[0])\n",
" checkpoint_path = os.path.relpath(checkpoint_path, checkpoint_name)\n",
" break\n",
"\n",
" ! gsutil cp -r $checkpoint_name $CHECKPOINT_BUCKET/\n",
" checkpoint_uri = os.path.join(CHECKPOINT_BUCKET, checkpoint_name, checkpoint_path)\n",
" print(\"Checkpoint uploaded to\", checkpoint_uri)\n",
" return checkpoint_uri"
]
},
{
@@ -665,8 +695,17 @@
" \"prefetch_buffer_size\": 12,\n",
" \"train_steps\": 500,\n",
" \"output_size\": \"1024,2048\",\n",
" \"init_checkpoint\": \"https://storage.googleapis.com/tf_model_garden/vision/deeplabv3plus/dilated-resnet-101-deeplabv3plus.tar.gz\",\n",
" }\n",
"}\n",
"experiment_container_args = experiment_container_args_dict[experiment]\n",
"\n",
"# Copy checkpoint to GCS bucket if specified.\n",
"init_checkpoint = experiment_container_args.get(\"init_checkpoint\")\n",
"if init_checkpoint:\n",
" experiment_container_args[\"init_checkpoint\"] = upload_checkpoint_to_gcs(\n",
" init_checkpoint\n",
" )\n",
"\n",
"worker_pool_specs = [\n",
" {\n",
@@ -681,10 +720,7 @@
" \"args\": [\n",
" \"--mode=train_and_eval\",\n",
" ]\n",
" + [\n",
" \"--{}={}\".format(k, v)\n",
" for k, v in experiment_container_args_dict[experiment].items()\n",
" ],\n",
" + [\"--{}={}\".format(k, v) for k, v in experiment_container_args.items()],\n",
" },\n",
" },\n",
"]\n",
@@ -787,13 +823,11 @@
" \"command\": [],\n",
" \"args\": [\n",
" \"--objective=%s\" % OBJECTIVE,\n",
" \"--experiment=%s\"\n",
" % experiment_container_args_dict[experiment][\"experiment\"],\n",
" \"--experiment=%s\" % experiment_container_args[\"experiment\"],\n",
" \"--config_file=%s/params.yaml\" % best_trial_dir,\n",
" \"--checkpoint_path=%s/best_ckpt\" % best_trial_dir,\n",
" \"--export_dir=%s/best_model\" % model_dir,\n",
" \"--input_image_size=%s\"\n",
" % experiment_container_args_dict[experiment][\"output_size\"],\n",
" \"--input_image_size=%s\" % experiment_container_args[\"output_size\"],\n",
" ],\n",
" },\n",
" }\n",
@@ -1479,7 +1479,7 @@
"source": [
"For more information about VPC peering in Vertex AI, see https://cloud.google.com/vertex-ai/docs/general/vpc-peering.\n",
"\n",
"**IMPORTANT: you can only setup one VPC peering to servicenetworking.googleapis.com per project.**"
"**IMPORTANT: you can only setup one VPC peering to servicenetworking.googleapis.com per VPC network.**"
]
},
{
@@ -130,48 +130,6 @@
"to generate a cost estimate based on your projected usage."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "setup_local"
},
"source": [
"### Set up your local development environment\n",
"\n",
"**If you are using Colab or Vertex AI Workbench Notebooks**, your environment already meets\n",
"all the requirements to run this notebook.\n",
"\n",
"**Otherwise**, make sure your environment meets this notebook's requirements.\n",
"You need the following:\n",
"\n",
"* The Google Cloud SDK\n",
"* Git\n",
"* Python 3\n",
"* virtualenv\n",
"* Jupyter notebook running in a virtual environment with Python 3\n",
"\n",
"The Google Cloud guide to [Setting up a Python development\n",
"environment](https://cloud.google.com/python/setup) and the [Jupyter\n",
"installation guide](https://jupyter.org/install) provide detailed instructions\n",
"for meeting these requirements. The following steps provide a condensed set of\n",
"instructions:\n",
"\n",
"1. [Install and initialize the Cloud SDK.](https://cloud.google.com/sdk/docs/)\n",
"\n",
"1. [Install Python 3.](https://cloud.google.com/python/setup#installing_python)\n",
"\n",
"1. [Install\n",
" virtualenv](https://cloud.google.com/python/setup#installing_and_using_virtualenv)\n",
" and create a virtual environment that uses Python 3. Activate the virtual environment.\n",
"\n",
"1. To install Jupyter, run `pip3 install jupyter` on the\n",
"command-line in a terminal shell.\n",
"\n",
"1. To launch Jupyter, run `jupyter notebook` on the command-line in a terminal shell.\n",
"\n",
"1. Open this notebook in the Jupyter Notebook Dashboard."
]
},
{
"cell_type": "markdown",
"metadata": {
@@ -193,17 +151,8 @@
"source": [
"import os\n",
"\n",
"# The Vertex AI Workbench Notebook product has specific requirements\n",
"IS_WORKBENCH_NOTEBOOK = os.getenv(\"DL_ANACONDA_HOME\")\n",
"IS_USER_MANAGED_WORKBENCH_NOTEBOOK = os.path.exists(\n",
" \"/opt/deeplearning/metadata/env_version\"\n",
")\n",
"# Vertex AI Notebook requires dependencies to be installed with '--user'\n",
"USER_FLAG = \"\"\n",
"if IS_WORKBENCH_NOTEBOOK:\n",
" USER_FLAG = \"--user\"\n",
"\n",
"! pip3 install --upgrade --quiet {USER_FLAG} google-cloud-aiplatform google-cloud-storage"
"! pip3 install --upgrade --quiet google-cloud-aiplatform \\\n",
" google-cloud-storage"
]
},
{
@@ -212,65 +161,38 @@
"id": "restart"
},
"source": [
"### Restart the kernel\n",
"\n",
"After you install the additional packages, you need to restart the notebook kernel so it can find the packages."
"### Colab only: Uncomment the following cell to restart the kernel"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "restart"
"id": "D-ZBOjErv5mM"
},
"outputs": [],
"source": [
"# Automatically restart kernel after installs\n",
"import os\n",
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
"# import IPython\n",
"\n",
"if not os.getenv(\"IS_TESTING\"):\n",
" # Automatically restart kernel after installs\n",
" import IPython\n",
"\n",
" app = IPython.Application.instance()\n",
" app.kernel.do_shutdown(True)"
"# app = IPython.Application.instance()\n",
"# app.kernel.do_shutdown(True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "before_you_begin:nogpu"
"id": "yfEglUHQk9S3"
},
"source": [
"## Before you begin\n",
"\n",
"### Set up your Google Cloud project\n",
"### Set your project ID\n",
"\n",
"**The following steps are required, regardless of your notebook environment.**\n",
"\n",
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
"\n",
"1. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
"\n",
"1. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com). \n",
"\n",
"1. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk).\n",
"\n",
"1. Enter your project ID in the cell below. Then run the cell to make sure the\n",
"Cloud SDK uses the right project for all the commands in this notebook.\n",
"\n",
"**Note**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5aee4379e8e5"
},
"source": [
"#### Set your project ID\n",
"\n",
"**If you don't know your project ID**, you may be able to get your project ID using `gcloud`."
"**If you don't know your project ID**, try the following:\n",
"* Run `gcloud config list`.\n",
"* Run `gcloud projects list`.\n",
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
]
},
{
@@ -281,33 +203,10 @@
},
"outputs": [],
"source": [
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "autoset_project_id"
},
"outputs": [],
"source": [
"if PROJECT_ID == \"\" or PROJECT_ID is None or PROJECT_ID == \"[your-project-id]\":\n",
" # Get your GCP project id from gcloud\n",
" shell_output = ! gcloud config list --format 'value(core.project)' 2>/dev/null\n",
" PROJECT_ID = shell_output[0]\n",
" print(\"Project ID:\", PROJECT_ID)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "set_gcloud_project_id"
},
"outputs": [],
"source": [
"! gcloud config set project $PROJECT_ID"
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"\n",
"# Set the project id\n",
"! gcloud config set project {PROJECT_ID}"
]
},
{
@@ -318,16 +217,7 @@
"source": [
"#### Region\n",
"\n",
"You can also change the `REGION` variable, which is used for operations\n",
"throughout the rest of this notebook. Below are regions supported for Vertex AI. It is recommended that you choose the region closest to you.\n",
"\n",
"- Americas: `us-central1`\n",
"- Europe: `europe-west4`\n",
"- Asia Pacific: `asia-east1`\n",
"\n",
"You may not use a multi-regional bucket for training with Vertex AI. Not all regions provide support for all Vertex AI services.\n",
"\n",
"Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
]
},
{
@@ -338,41 +228,7 @@
},
"outputs": [],
"source": [
"REGION = \"[your-region]\" # @param {type: \"string\"}\n",
"\n",
"if REGION == \"[your-region]\":\n",
" REGION = \"us-central1\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "timestamp"
},
"source": [
"#### UUID\n",
"\n",
"If you are in a live tutorial session, you might be using a shared test account or project. To avoid name collisions between users on resources created, you create a uuid for each instance session, and append it onto the name of resources you create in this tutorial.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "timestamp"
},
"outputs": [],
"source": [
"import random\n",
"import string\n",
"\n",
"\n",
"# Generate a uuid of a specifed length(default=8)\n",
"def generate_uuid(length: int = 8) -> str:\n",
" return \"\".join(random.choices(string.ascii_lowercase + string.digits, k=length))\n",
"\n",
"\n",
"UUID = generate_uuid()"
"REGION = \"us-central1\" # @param {type: \"string\"}"
]
},
{
@@ -383,64 +239,54 @@
"source": [
"### Authenticate your Google Cloud account\n",
"\n",
"**If you are using Vertex AI Workbench Notebooks**, your environment is already\n",
"authenticated. \n",
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below.\n",
"\n",
"**If you are using Colab**, run the cell below and follow the instructions\n",
"when prompted to authenticate your account via oAuth.\n",
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated.\n",
"\n",
"**Otherwise**, follow these steps:\n",
"\n",
"1. In the Cloud Console, go to the [**Create service account key**\n",
" page](https://console.cloud.google.com/apis/credentials/serviceaccountkey).\n",
"\n",
"2. Click **Create service account**.\n",
"\n",
"3. In the **Service account name** field, enter a name, and\n",
" click **Create**.\n",
"\n",
"4. In the **Grant this service account access to project** section, click the **Role** drop-down list. Type \"Vertex AI\"\n",
"into the filter box, and select\n",
" **Vertex AI Administrator**. Type \"Storage Object Admin\" into the filter box, and select **Storage Object Admin**.\n",
"\n",
"5. Click *Create*. A JSON file that contains your key downloads to your\n",
"local environment.\n",
"\n",
"6. Enter the path to your service account key as the\n",
"`GOOGLE_APPLICATION_CREDENTIALS` variable in the cell below and run the cell."
"**2. Local JupyterLab instance, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "gcp_authenticate"
"id": "ce6043da7b33"
},
"outputs": [],
"source": [
"# If you are running this notebook in Colab, run this cell and follow the\n",
"# instructions to authenticate your GCP account. This provides access to your\n",
"# Cloud Storage bucket and lets you submit training jobs and prediction\n",
"# requests.\n",
"\n",
"import os\n",
"import sys\n",
"\n",
"# If on Vertex AI Workbench, then don't execute this code\n",
"IS_COLAB = \"google.colab\" in sys.modules\n",
"if not os.path.exists(\"/opt/deeplearning/metadata/env_version\") and not os.getenv(\n",
" \"DL_ANACONDA_HOME\"\n",
"):\n",
" if \"google.colab\" in sys.modules:\n",
" from google.colab import auth as google_auth\n",
"\n",
" google_auth.authenticate_user()\n",
"\n",
" # If you are running this notebook locally, replace the string below with the\n",
" # path to your service account key and run this cell to authenticate your GCP\n",
" # account.\n",
" elif not os.getenv(\"IS_TESTING\"):\n",
" %env GOOGLE_APPLICATION_CREDENTIALS ''"
"# ! gcloud auth login"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0367eac06a10"
},
"source": [
"**3. Colab, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "21ad4dbb4a61"
},
"outputs": [],
"source": [
"# from google.colab import auth\n",
"# auth.authenticate_user()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c13224697bfb"
},
"source": [
"**4. Service account or other**\n",
"* See how to grant Cloud Storage permissions to your service account at https://cloud.google.com/storage/docs/gsutil/commands/iam#ch-examples."
]
},
{
@@ -451,11 +297,7 @@
"source": [
"### Create a Cloud Storage bucket\n",
"\n",
"**The following steps are required, regardless of your notebook environment.**\n",
"\n",
"When you run a Vertex AI pipeline job using the Cloud SDK, your job stores the pipeline artifacts to a Cloud Storage bucket. In this tutorial, you create a Vertex AI Pipeline job that saves the artifacts like evaluation metrics and feature attributes to a Cloud Storage bucket.\n",
"\n",
"Set the name of your Cloud Storage bucket below. It must be unique across all Cloud Storage buckets."
"Create a storage bucket to store intermediate artifacts such as datasets."
]
},
{
@@ -466,27 +308,13 @@
},
"outputs": [],
"source": [
"BUCKET_NAME = \"[your-bucket-name]\" # @param {type:\"string\"}\n",
"BUCKET_URI = f\"gs://{BUCKET_NAME}\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "autoset_bucket"
},
"outputs": [],
"source": [
"if BUCKET_NAME == \"\" or BUCKET_NAME is None or BUCKET_NAME == \"[your-bucket-name]\":\n",
" BUCKET_NAME = PROJECT_ID + \"aip-\" + UUID\n",
" BUCKET_URI = f\"gs://{BUCKET_NAME}\""
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "create_bucket"
"id": "autoset_bucket"
},
"source": [
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket."
@@ -496,33 +324,13 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "create_bucket"
"id": "91c46850b49b"
},
"outputs": [],
"source": [
"! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "validate_bucket"
},
"source": [
"Finally, validate access to your Cloud Storage bucket by examining its contents:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "validate_bucket"
},
"outputs": [],
"source": [
"! gsutil ls -al $BUCKET_URI"
]
},
{
"cell_type": "markdown",
"metadata": {
@@ -653,7 +461,7 @@
"outputs": [],
"source": [
"dataset = aiplatform.VideoDataset.create(\n",
" display_name=\"Golf Swings\" + \"_\" + UUID,\n",
" display_name=\"Golf Swings\",\n",
" gcs_source=IMPORT_FILES,\n",
" import_schema_uri=aiplatform.schema.dataset.ioformat.video.action_recognition,\n",
")\n",
@@ -693,7 +501,7 @@
"outputs": [],
"source": [
"job = aiplatform.AutoMLVideoTrainingJob(\n",
" display_name=\"golf_\" + UUID,\n",
" display_name=\"golf\",\n",
" prediction_type=\"action_recognition\",\n",
")\n",
"\n",
@@ -730,7 +538,7 @@
"source": [
"model = job.run(\n",
" dataset=dataset,\n",
" model_display_name=\"golf_\" + UUID,\n",
" model_display_name=\"golf\",\n",
" training_fraction_split=0.8,\n",
" test_fraction_split=0.2,\n",
")"
@@ -876,7 +684,7 @@
"outputs": [],
"source": [
"batch_predict_job = model.batch_predict(\n",
" job_display_name=\"golf_\" + UUID,\n",
" job_display_name=\"golf\",\n",
" gcs_source=gcs_input_uri,\n",
" gcs_destination_prefix=BUCKET_URI,\n",
" sync=False,\n",
@@ -0,0 +1,669 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "ur8xi4C7S06n"
},
"outputs": [],
"source": [
"# Copyright 2022 Google LLC\n",
"#\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JAPoU8Sm5E6e"
},
"source": [
"# Delete Outdated Experiments in Vertex AI TensorBoard\n",
"\n",
"<table align=\"left\">\n",
"\n",
" <td>\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/delete_outdated_tensorboard_experiments.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/delete_outdated_tensorboard_experiments.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/vertex-ai-samples/main/notebooks/official/experiments/delete_outdated_tensorboard_experiments.ipynb\">\n",
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
" Open in Vertex AI Workbench\n",
" </a>\n",
" </td>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "24743cf4a1e1"
},
"source": [
"**_NOTE_**: This notebook has been tested in the following environment:\n",
"\n",
"* Python version = 3.9"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tvgnzT1CKxrO"
},
"source": [
"## Overview\n",
"\n",
"Vertex AI will have a new Vertex AI TensorBoard billing model. From August 2023, it will change from monthly `$300/user` to monthly `$10/GB`. In preparation for this change, users need to delete old Vertex AI TensorBoard Experiments to avoid unnecessary storage costs when the pricing change takes place.\n",
"\n",
"Learn more about [Vertex AI TensorBoard](https://cloud.google.com/vertex-ai/docs/experiments/tensorboard-overview)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "d975e698c9a4"
},
"source": [
"### Objective\n",
"\n",
"In this tutorial, you learn how to delete outdated TensorBoard Experiments to avoid unnecessary storage costs.\n",
"\n",
"This tutorial uses the following Google Cloud ML services and resources:\n",
"\n",
"- Vertex AI Tensorboard\n",
"\n",
"The steps performed include:\n",
"\n",
"- How to delete the TB Experiment with a predefined key-value label pair `<label_key, label_value>`\n",
"\n",
"- How to delete the TB Experiments created before the `create_time`\n",
"\n",
"- How to delete the TB Experiments created before the `update_time`"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "08d289fa873f"
},
"source": [
"### Dataset\n",
"\n",
"No dataset is used."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "aed92deeb4a0"
},
"source": [
"### Costs\n",
"\n",
"This tutorial uses billable components of Google Cloud:\n",
"\n",
"* Vertex AI\n",
"* Cloud Storage\n",
"\n",
"Learn about [Vertex AI pricing](https://cloud.google.com/vertex-ai/pricing), and [Cloud Storage pricing](https://cloud.google.com/storage/pricing),\n",
"and use the [Pricing Calculator](https://cloud.google.com/products/calculator/)\n",
"to generate a cost estimate based on your projected usage."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i7EUnXsZhAGF"
},
"source": [
"## Installation\n",
"\n",
"Install the following packages required to execute this notebook."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2b4ef9b72d43"
},
"outputs": [],
"source": [
"# Install the packages\n",
"import os\n",
"\n",
"if not os.getenv(\"IS_TESTING\"):\n",
" USER = \"--user\"\n",
"else:\n",
" USER = \"\"\n",
"! pip3 install {USER} --upgrade google-cloud-aiplatform"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "58707a750154"
},
"source": [
"### Colab only: Uncomment the following cell to restart the kernel."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "f200f10a1da3"
},
"outputs": [],
"source": [
"# Automatically restart kernel after installs so that your environment can access the new packages\n",
"# import IPython\n",
"\n",
"# app = IPython.Application.instance()\n",
"# app.kernel.do_shutdown(True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "BF1j6f9HApxa"
},
"source": [
"## Before you begin\n",
"\n",
"### Set up your Google Cloud project\n",
"\n",
"**The following steps are required, regardless of your notebook environment.**\n",
"\n",
"1. [Select or create a Google Cloud project](https://console.cloud.google.com/cloud-resource-manager). When you first create an account, you get a $300 free credit towards your compute/storage costs.\n",
"\n",
"2. [Make sure that billing is enabled for your project](https://cloud.google.com/billing/docs/how-to/modify-project).\n",
"\n",
"3. [Enable the Vertex AI API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com).\n",
"\n",
"4. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk)."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WReHDGG5g0XY"
},
"source": [
"#### Set your project ID\n",
"\n",
"**If you don't know your project ID**, try the following:\n",
"* Run `gcloud config list`.\n",
"* Run `gcloud projects list`.\n",
"* See the support page: [Locate the project ID](https://support.google.com/googleapi/answer/7014113)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "oM1iC_MfAts1"
},
"outputs": [],
"source": [
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"\n",
"# Set the project id\n",
"! gcloud config set project {PROJECT_ID}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "region"
},
"source": [
"#### Region\n",
"\n",
"You can also change the `REGION` variable used by Vertex AI. Learn more about [Vertex AI regions](https://cloud.google.com/vertex-ai/docs/general/locations)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "QAup21nz6LHk"
},
"outputs": [],
"source": [
"REGION = \"us-central1\" # @param {type: \"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sBCra4QMA2wR"
},
"source": [
"### Authenticate your Google Cloud account\n",
"\n",
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "74ccc9e52986"
},
"source": [
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "de775a3773ba"
},
"source": [
"**2. Local JupyterLab instance, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "254614fa0c46"
},
"outputs": [],
"source": [
"# ! gcloud auth login"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ef21552ccea8"
},
"source": [
"**3. Colab, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "603adbbf0532"
},
"outputs": [],
"source": [
"# from google.colab import auth\n",
"# auth.authenticate_user()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f6b2ccc891ed"
},
"source": [
"**4. Service account or other**\n",
"* See how to grant permissions to your service account at https://cloud.google.com/marketplace/docs/grant-service-account-access."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "960505627ddf"
},
"source": [
"### Import libraries"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "PyQmSRbKA8r-"
},
"outputs": [],
"source": [
"from google.cloud import aiplatform"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "NUJOpq7_-nt6"
},
"source": [
"### Define constants\n",
"\n",
"Define variables you use in this tutorial. In particular, you set\n",
"\n",
"- `CREATE_TIME_CUT` : delete tensorboard experiments that were created before CREATE_TIME_CUT. For example, `2022-12-31`.\n",
"\n",
"- `UPDATE_TIME_CUT` : delete tensorboard experiments that were created before UPDATE_TIME_CUT. For example, `2022-12-31`.\n",
"\n",
"- `DETAILED_LOG` : a booled variable to see Tensorboard deletion progress. If True, it shows progress by experiments. Otherwise, it reports progress per 100 experiments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0AkyoMre-qe5"
},
"outputs": [],
"source": [
"CREATE_TIME_CUT = \"\" # @param {type:\"string\"}\n",
"\n",
"UPDATE_TIME_CUT = \"\" # @param {type:\"string\"}\n",
"\n",
"DETAILED_LOG = True # @param {type: \"boolean\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "n68J5KJ4ERbF"
},
"source": [
"### Define Helpers"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "JIXC-tVrETET"
},
"outputs": [],
"source": [
"def clean_up_by_label(tensorboard_instance, label_key, label_value):\n",
" \"\"\"Delete the TB Experiment with the key-value label pair <label_key, label_value>\"\"\"\n",
" # List tensorboard experiments\n",
" tensorboard_experiments = aiplatform.TensorboardExperiment.list(\n",
" tensorboard_name=tensorboard_instance.resource_name\n",
" )\n",
" # Get the number of tensorboard experiments\n",
" num_tensorboard_experiments = len(tensorboard_experiments)\n",
" # For each experiment\n",
" for i in range(num_tensorboard_experiments):\n",
" tensorboard_experiment = tensorboard_experiments[i]\n",
" if detailed_log or (i % 100 == 0):\n",
" print(\n",
" f\">>>checking TB experiment [{i + 1}/{num_tensorboard_experiments}]: {tensorboard_experiment.resource_name}\"\n",
" )\n",
" # Get experiment labels\n",
" labels = tensorboard_experiment.labels\n",
" # Filter by label\n",
" if label_key in labels and labels[label_key] == label_value:\n",
" # Delete experiment\n",
" tensorboard_experiment.delete()\n",
"\n",
"\n",
"def clean_up_by_create_time(tensorboard_instance, create_time_cut):\n",
" \"\"\"Delete the TB Experiment with the `create_time`\"\"\"\n",
" # List tensorboard experiments\n",
" tensorboard_experiments = aiplatform.TensorboardExperiment.list(\n",
" tensorboard_name=tensorboard_instance.resource_name, order_by=\"create_time\"\n",
" )\n",
" # Get the number of tensorboard experiments\n",
" num_tensorboard_experiments = len(tensorboard_experiments)\n",
" # For each experiment\n",
" for i in range(num_tensorboard_experiments):\n",
" tensorboard_experiment = tensorboard_experiments[i]\n",
" if detailed_log or (i % 100 == 0):\n",
" print(\n",
" f\">>> checking TB experiment [{i + 1}/{num_tensorboard_experiments}]: {tensorboard_experiment.resource_name}\"\n",
" )\n",
" # Filter by create_time\n",
" if str(tensorboard_experiment.create_time) < create_time_cut:\n",
" # Delete experiment\n",
" tensorboard_experiment.delete()\n",
" else:\n",
" break\n",
"\n",
"\n",
"def clean_up_by_update_time(tensorboard_instance, update_time_cut):\n",
" \"\"\"Delete the TB Experiment with with the `update_time`\"\"\"\n",
" # List tensorboard experiments\n",
" tensorboard_experiments = aiplatform.TensorboardExperiment.list(\n",
" tensorboard_name=tensorboard_instance.resource_name, order_by=\"update_time\"\n",
" )\n",
" # Get the number of tensorboard experiments\n",
" num_tensorboard_experiments = len(tensorboard_experiments)\n",
" # For each experiment\n",
" for i in range(num_tensorboard_experiments):\n",
" tensorboard_experiment = tensorboard_experiments[i]\n",
" if detailed_log or (i % 100 == 0):\n",
" print(\n",
" f\">>> checking TB experiment [{i + 1}/{num_tensorboard_experiments}]: {tensorboard_experiment.resource_name}\"\n",
" )\n",
" # Filter by update_time\n",
" if str(tensorboard_experiment.update_time) < update_time_cut:\n",
" tensorboard_experiment.delete()\n",
" else:\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UCUOlTLYCT0B"
},
"source": [
"## Delete outdated Vertex AI TensorBoard Experiments"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EGfFVHhWDjkl"
},
"source": [
"### Initialize Vertex AI SDK for Python\n",
"\n",
"Initialize the Vertex AI SDK for Python for your project."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "G1l-7Wft3jb6"
},
"outputs": [],
"source": [
"aiplatform.init(project=PROJECT_ID, location=REGION)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e4672ef33691"
},
"source": [
"### Set delete outdated TensorBoard experiments \n",
"\n",
"Initialize a flag variable to start deleting outdated TensorBoard experiments and a flag variable to choose the deleting method. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "8cdc326c9823"
},
"outputs": [],
"source": [
"delete_tb_experiments = False # @param {type: \"boolean\"}\n",
"\n",
"delete_method = \"\" # @param [\"by_label\", \"by_create_time\", \"by_update_time\"]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "JjJVARe5V-MG"
},
"source": [
"### Delete an TensorBoard instance\n",
"\n",
"To delete a Tensorboard instance, you need `TENSORBOARD_INSTANCE` ID which uniquely identifies the Tensorboard instance where you run experiments.\n",
"\n",
"To get the Tensorboard instance ID, you can either\n",
"\n",
"- go to the cloud console UI, Vertex AI > Experiments > Tensorboard Instances, or\n",
"- use the list command below to list all TensorBoard instances for your project and region.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "eqM2pIO8_4Y7"
},
"outputs": [],
"source": [
"tensorboard_instances = aiplatform.Tensorboard.list(project=PROJECT_ID, location=REGION)\n",
"print(tensorboard_instances)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wT_uPArACMPX"
},
"source": [
"Set the tensorboard instance id for which you want to delete experiments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "hUync8E9CLcm"
},
"outputs": [],
"source": [
"if delete_tb_experiments:\n",
"\n",
" TENSORBOARD_INSTANCE_ID = \"\" # @param {type:\"string\"}\n",
"\n",
" TENSORBOARD_INSTANCE = aiplatform.Tensorboard(\n",
" project=PROJECT_ID, location=REGION, tensorboard_name=TENSORBOARD_INSTANCE_ID\n",
" )\n",
" print(TENSORBOARD_INSTANCE)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OOp22fxdHqmT"
},
"source": [
"### Delete a TensorBoard Experiment with the key-value label pair\n",
"\n",
"You delete a TensorBoard experiment using a predefined `label_key` and `label_value`. For example, you may have assigned `delete` label key and `true` label value to indicate all Tensorboard experiments you want to delete.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "N7KajCsjij1g"
},
"outputs": [],
"source": [
"LABEL_KEY = \"delete\" # @param {type:\"string\"}\n",
"LABEL_VALUE = \"true\" # @param {type:\"string\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "N45samDzWBO2"
},
"outputs": [],
"source": [
"if delete_tb_experiments and delete_method == \"by_label\":\n",
" clean_up_by_label(TENSORBOARD_INSTANCE, LABEL_KEY, LABEL_VALUE)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XrEVqlgSIL6K"
},
"source": [
"### Delete a TensorBoard Experiment with `create_time`\n",
"\n",
"You delete a TensorBoard experiment using `create_time` field"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "4_bjNeQ7p87A"
},
"outputs": [],
"source": [
"if delete_tb_experiments and delete_method == \"by_create_time\":\n",
" clean_up_by_create_time(TENSORBOARD_INSTANCE, CREATE_TIME_CUT)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZGNlSbIrIP_o"
},
"source": [
"### Delete a TensorBoard Experiment with `update_time`\n",
"\n",
"You delete a TensorBoard Experiment using a predefined `update_time` field"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "SDyc_a8XwEve"
},
"outputs": [],
"source": [
"if delete_tb_experiments and delete_method == \"by_update_time\":\n",
" clean_up_by_update_time(TENSORBOARD_INSTANCE, UPDATE_TIME_CUT)"
]
}
],
"metadata": {
"colab": {
"name": "delete_outdated_tensorboard_experiments.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -34,18 +34,18 @@
"<table align=\"left\">\n",
"\n",
" <td>\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/autologging.ipynb\">\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/get_started_with_vertex_experiments_autologging.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/colab-logo-32px.png\" alt=\"Colab logo\"> Run in Colab\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/autologging.ipynb\">\n",
" <a href=\"https://github.com/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/official/experiments/get_started_with_vertex_experiments_autologging.ipynb\">\n",
" <img src=\"https://cloud.google.com/ml-engine/images/github-logo-32px.png\" alt=\"GitHub logo\">\n",
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td>\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/official/experiments/autologging.ipynb\">\n",
" <a href=\"https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/official/experiments/get_started_with_vertex_experiments_autologging.ipynb\">\n",
" <img src=\"https://lh3.googleusercontent.com/UiNooY4LUgW_oTvpsNhPpQzsstV5W8F7rYgxgGBD85cWJoLmrOzhVs_ksK_vgx40SHs7jCqkTkCk=e14-rj-sc0xffffff-h130-w32\" alt=\"Vertex AI logo\">\n",
" Open in Vertex AI Workbench\n",
" </a>\n",
File diff suppressed because one or more lines are too long