Compare commits

...
Author SHA1 Message Date
Andrew FerlitschandGitHub cb6fd7fd07 fix: branding 2023-07-21 11:46:24 -07:00
7200238f4f Update deploy machine information. (#2107)
Co-authored-by: minwoopark <minwoopark@google.com>
2023-07-21 15:34:09 +00:00
genquan9andGitHub d9058c2e4e add a sperate notebook for openllama peft to be more specific (#2106) 2023-07-21 15:33:08 +00:00
dstnluong-googleandGitHub 1b6e663af0 Move frames_to_video_bytes to handler.py (#2104) 2023-07-20 15:30:28 +00:00
Andrew FerlitschandGitHub 5887f400c8 feat: KFP2 pipeline example (#2096)
* feat: KFP2 pipeline example

* Update kfp2_pipeline.ipynb

remove hardwired project ID

* fix: review
2023-07-19 21:12:45 +00:00
dstnluong-googleandGitHub 5e509423a6 support yolov7 (#2037) 2023-07-19 16:55:41 +00:00
dstnluong-googleandGitHub bb61d92f80 Add train/serve files for keras (#2077)
* Add train/serve files for keras

* Fix comment and typo.

* Fix dockerfile commands

* Fix dockerfile comment.
2023-07-18 15:42:07 +00:00
genquan9andGitHub 34431b6511 Fix typos in peft notebooks (#2100)
* fix typos in keras model deployment

* fix types in peft notebook
2023-07-18 15:31:30 +00:00
dstnluong-googleandGitHub ec3ec5a2c1 import urllib in timm notebook (#2101)
* import urllib

* lint
2023-07-18 15:30:59 +00:00
d9f5a40088 fix: boilerplate reduction 76 - training failed - bug filed (#1947)
* fix: boilerplate reduction 77

* fix: lint

* fix: syntax error

* fix: GCS bucket

* Fix GCS bucket

* fix: bucket

* fix: bucket

* fix: correct the model GSC output path (#2102)

---------

Co-authored-by: Eric Dong <itseric@google.com>
2023-07-18 14:18:21 +00:00
713a54815b debug: check if passes 30 - Training failed (#2054)
* debug: check if passes 30

* fix: service account

* fix: pin protobuff version for dependency compatibility (#2097)

---------

Co-authored-by: Eric Dong <itseric@google.com>
2023-07-17 16:10:22 +00:00
Andrew FerlitschandGitHub 06c87bc24d debug: regression failure (#2093)
* debug: internal error

* debug: install dbdtypes

* debug: create repo
2023-07-17 15:57:06 +00:00
Andrew FerlitschandGitHub 75c37416d8 debug: internal error (#2092) 2023-07-17 15:46:49 +00:00
dstnluong-googleandGitHub ad99d0d0c0 Fix local inference when loading weights from GCS (#2090)
* Fix local inference when loading weights from GCS

* remove extra <td>
2023-07-14 22:37:31 +00:00
dstnluong-googleandGitHub c7b3e67989 Remove COCA from available models (#2091) 2023-07-14 22:36:54 +00:00
20 changed files with 2821 additions and 401 deletions
+1
View File
@@ -12,4 +12,5 @@
/prediction_featurestore_integration @googleapis/vertex-prediction-team
/vertex_vision_model_garden/model_oss/util @weigary
/vertex_vision_model_garden/model_oss/diffusers @weigary
/vertex_vision_model_garden/model_oss/keras @dstnluong-google
/vertex_vision_model_garden/model_oss/transformers @dstnluong-google
@@ -4,9 +4,10 @@
# pylint: disable=logging-fstring-interpolation
import base64
import io
import logging
import os
from typing import Any, List, Tuple
from typing import Any, List, Sequence, Tuple
from diffusers import ControlNetModel
from diffusers import DiffusionPipeline
@@ -20,6 +21,7 @@ from diffusers import StableDiffusionPipeline
from diffusers import StableDiffusionUpscalePipeline
from diffusers import TextToVideoZeroPipeline
from diffusers import UniPCMultistepScheduler
import imageio
import numpy as np
from PIL import Image
import torch
@@ -43,6 +45,13 @@ TEXT_TO_VIDEO_ZERO_SHOT = "text-to-video-zero-shot"
TEXT_TO_VIDEO = "text-to-video"
def frames_to_video_bytes(frames: Sequence[np.ndarray], fps: int) -> bytes:
images = [Image.fromarray(array) for array in frames]
io_obj = io.BytesIO()
imageio.mimsave(io_obj, images, format=".mp4", fps=fps)
return io_obj.getvalue()
class DiffusersHandler(BaseHandler):
"""Custom handler for TIMM models."""
@@ -214,7 +223,7 @@ class DiffusersHandler(BaseHandler):
numpy_arrays = self.pipeline(prompt=prompt).images
numpy_arrays = [(i * 255).astype("uint8") for i in numpy_arrays]
videos.append(
video_format_converter.frames_to_video_bytes(numpy_arrays, fps=4)
frames_to_video_bytes(numpy_arrays, fps=4)
)
return videos
elif self.task == TEXT_TO_VIDEO:
@@ -224,7 +233,7 @@ class DiffusersHandler(BaseHandler):
# Therefore we need to split the output into different videos.
predicted_images = np.array_split(predicted_images, len(prompts), axis=2)
videos = [
video_format_converter.frames_to_video_bytes(images, fps=8)
frames_to_video_bytes(images, fps=8)
for images in predicted_images
]
return videos
@@ -0,0 +1,118 @@
# Dockerfile for basic serving dockers with Keras.
#
# To build:
# docker build -f model_oss/keras/dockerfile/serve.Dockerfile . -t ${YOUR_IMAGE_TAG}
#
# To push to gcr:
# docker tag ${YOUR_IMAGE_TAG} gcr.io/${YOUR_PROJECT}/${YOUR_IMAGE_TAG}
# docker push gcr.io/${YOUR_PROJECT}/${YOUR_IMAGE_TAG}
FROM tensorflow/tensorflow:2.12.0-gpu
ENV DEBIAN_FRONTEND=noninteractive
# This is added to fix docker build error related to Nvidia key update.
RUN rm -f /etc/apt/sources.list.d/cuda.list
RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
# Install basic libs.
RUN apt-get update && apt-get install -y --no-install-recommends \
cmake \
curl \
wget \
sudo \
gnupg \
libsm6 \
libxext6 \
libxrender-dev \
lsb-release \
ca-certificates \
build-essential \
git \
vim \
screen \
libtcmalloc-minimal4
# Install google cloud SDK.
RUN wget -q https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-359.0.0-linux-x86_64.tar.gz
RUN tar xzf google-cloud-sdk-359.0.0-linux-x86_64.tar.gz
RUN ./google-cloud-sdk/install.sh -q
# Make sure gsutil will use the default service account.
RUN echo '[GoogleCompute]\nservice_account = default' > /etc/boto.cfg
# Install required libs.
RUN pip install --upgrade pip
RUN pip install cloud-tpu-client==0.10
RUN pip install pyyaml==5.4.1
RUN pip install fsspec==2021.10.1
RUN pip install gcsfs==2021.10.1
RUN pip install tensorflow-text==2.11.0
RUN pip install pyglove==0.1.0
RUN pip install cloudml-hypertune==0.1.0.dev6
RUN pip install pylint==2.17.2
RUN pip install keras-cv==0.4.0
RUN pip install tensorflow-datasets==4.8.3
RUN pip install protobuf==3.20.3
RUN pip install Pillow==9.5.0
RUN pip install flask==2.3.2
RUN pip install waitress==2.1.2
# Installs Reduction Server NCCL plugin.
RUN echo "deb https://packages.cloud.google.com/apt google-fast-socket main" | tee /etc/apt/sources.list.d/google-fast-socket.list \
&& curl -s -L https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
&& apt update && apt install -y google-reduction-server
# Downloading gcloud package
RUN curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz
# Installing the package
RUN mkdir -p /usr/local/gcloud \
&& tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz \
&& /usr/local/gcloud/google-cloud-sdk/install.sh
RUN wget https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/LICENSE
# Adding the package path to local
ENV PATH $PATH:/usr/local/gcloud/google-cloud-sdk/bin
ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
# Lower the memory fragmentation, and speed up the training.
# https://github.com/tensorflow/tensorflow/issues/44176#issuecomment-783768033
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4
# Enable userspace DNS cache
ENV GCS_RESOLVE_REFRESH_SECS=60
ENV GCS_REQUEST_CONNECTION_TIMEOUT_SECS=300
ENV GCS_METADATA_REQUEST_TIMEOUT_SECS=300
ENV GCS_READ_REQUEST_TIMEOUT_SECS=300
ENV GCS_WRITE_REQUEST_TIMEOUT_SECS=600
# Each opened GCS file takes GCS_READ_CACHE_BLOCK_SIZE_MB of RAM, reduce the
# value from the default 64MB to 8MB to decrease memory footprint.
ENV GCS_READ_CACHE_BLOCK_SIZE_MB=8
EXPOSE 8501
WORKDIR /usr/local/lib/python3.8/dist-packages/official/vision
COPY model_oss/keras /automl_vision/keras
COPY model_oss/util /automl_vision/util
WORKDIR /automl_vision
ENV PYTHONPATH "${PYTHONPATH}:/automl_vision/util"
ENV MODEL_PATH ""
ENV IMAGE_WIDTH "512"
ENV IMAGE_HEIGHT "512"
COPY model_oss/keras/serve.py ./app.py
# Run pylint to validate code.
COPY .pylintrc /automl_vision/.pylintrc
RUN find . -type f -name "*.py" | xargs pylint --rcfile=./.pylintrc --errors-only
ENTRYPOINT ["flask","run"]
CMD ["--host=0.0.0.0", "--port=8501"]
@@ -0,0 +1,111 @@
# Dockerfile for basic training dockers with Keras.
#
# To build:
# docker build -f model_oss/keras/dockerfile/train.Dockerfile . -t ${YOUR_IMAGE_TAG}
#
# To push to gcr:
# docker tag ${YOUR_IMAGE_TAG} gcr.io/${YOUR_PROJECT}/${YOUR_IMAGE_TAG}
# docker push gcr.io/${YOUR_PROJECT}/${YOUR_IMAGE_TAG}
FROM tensorflow/tensorflow:2.12.0-gpu
ENV DEBIAN_FRONTEND=noninteractive
# This is added to fix docker build error related to Nvidia key update.
RUN rm -f /etc/apt/sources.list.d/cuda.list
RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
# Install basic libs.
RUN apt-get update && apt-get install -y --no-install-recommends \
cmake \
curl \
wget \
sudo \
gnupg \
libsm6 \
libxext6 \
libxrender-dev \
lsb-release \
ca-certificates \
build-essential \
git \
vim \
screen \
libtcmalloc-minimal4
# Install google cloud SDK.
RUN wget -q https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-359.0.0-linux-x86_64.tar.gz
RUN tar xzf google-cloud-sdk-359.0.0-linux-x86_64.tar.gz
RUN ./google-cloud-sdk/install.sh -q
# Make sure gsutil will use the default service account.
RUN echo '[GoogleCompute]\nservice_account = default' > /etc/boto.cfg
# Install required libs.
RUN pip install --upgrade pip
RUN pip install cloud-tpu-client==0.10
RUN pip install pyyaml==5.4.1
RUN pip install fsspec==2021.10.1
RUN pip install gcsfs==2021.10.1
RUN pip install tensorflow-text==2.11.0
RUN pip install pyglove==0.1.0
RUN pip install cloudml-hypertune==0.1.0.dev6
RUN pip install pylint==2.17.2
RUN pip install keras-cv==0.4.0
RUN pip install tensorflow-datasets==4.8.3
RUN pip install tensorflow-estimator==2.12.0
RUN pip install tensorflow-gcs-config==2.12.0
RUN pip install tensorflow-hub==0.13.0
RUN pip install tensorflow-io-gcs-filesystem==0.32.0
RUN pip install tensorflow-metadata==1.13.1
RUN pip install tensorflow-probability==0.19.0
RUN pip install tensorboard==2.12.2
RUN pip install tensorboard-data-server==0.7.0
RUN pip install tensorboard-plugin-wit==1.8.1
RUN pip install protobuf==3.20.3
RUN pip install pandas==1.5.3
RUN pip install pandas-datareader==0.10.0
RUN pip install pandas-gbq==0.17.9
RUN pip install pycocotools==2.0.6
# Installs Reduction Server NCCL plugin.
RUN echo "deb https://packages.cloud.google.com/apt google-fast-socket main" | tee /etc/apt/sources.list.d/google-fast-socket.list \
&& curl -s -L https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - \
&& apt update && apt install -y google-reduction-server
RUN wget https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/LICENSE
ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
# Lower the memory fragmentation, and speed up the training.
# https://github.com/tensorflow/tensorflow/issues/44176#issuecomment-783768033
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4
# Enable userspace DNS cache
ENV GCS_RESOLVE_REFRESH_SECS=60
ENV GCS_REQUEST_CONNECTION_TIMEOUT_SECS=300
ENV GCS_METADATA_REQUEST_TIMEOUT_SECS=300
ENV GCS_READ_REQUEST_TIMEOUT_SECS=300
ENV GCS_WRITE_REQUEST_TIMEOUT_SECS=600
# Each opened GCS file takes GCS_READ_CACHE_BLOCK_SIZE_MB of RAM, reduce the
# value from the default 64MB to 8MB to decrease memory footprint.
ENV GCS_READ_CACHE_BLOCK_SIZE_MB=8
WORKDIR /usr/local/lib/python3.8/dist-packages/official/vision
COPY model_oss/keras /automl_vision/keras
COPY model_oss/util /automl_vision/util
WORKDIR /automl_vision
# Keras stable diffusion training codes set width and height as RESOLUTION.
ENV RESOLUTION "512"
ENV PYTHONPATH "${PYTHONPATH}:/automl_vision/util"
# Run pylint to validate code.
COPY .pylintrc /automl_vision/.pylintrc
RUN find . -type f -name "*.py" | xargs pylint --rcfile=./.pylintrc --errors-only
ENTRYPOINT ["python3","keras/train.py"]
@@ -0,0 +1,184 @@
r"""Servers Keras Stable Diffusion models.
python serve.py --model_path=<model path in gcs>
curl -d \
'{"prompt":"Hello Kitty"}' \
-H "Content-Type: application/json" \
-X POST http://localhost:8501/predict
"""
import base64
import io
import json
import os
from typing import List, Tuple
from absl import app
# The docker builds could not find flask and waitress.
# pylint: disable=import-error
from flask import Flask
from flask import request
from flask import Response
import keras_cv
from PIL import Image
from waitress import serve
from util import constants
from util import fileutils
flask_app = Flask(__name__)
stable_diffusion_model = None
model_path = os.environ.get('MODEL_PATH', '')
if model_path.startswith(constants.GCS_URI_PREFIX):
print('Downloading models from gcs to local.')
os.makedirs(constants.LOCAL_MODEL_DIR, exist_ok=True)
fileutils.download_gcs_dir_to_local(
os.path.dirname(model_path), constants.LOCAL_MODEL_DIR
)
model_path = os.path.join(
constants.LOCAL_MODEL_DIR, os.path.basename(model_path)
)
image_width = int(os.environ.get('IMAGE_WIDTH', 512))
image_height = int(os.environ.get('IMAGE_HEIGHT', 512))
print('image_width=', image_width, 'image_height=', image_height)
print('Create Keras stable diffusion models.')
stable_diffusion_model = keras_cv.models.StableDiffusion(
img_width=image_width,
img_height=image_height,
jit_compile=True,
)
if model_path:
# We just reload the weights of the fine-tuned diffusion model.
print('Initialize finetuned models from: ', model_path)
stable_diffusion_model.diffusion_model.load_weights(model_path)
def error(message: str) -> str:
"""Returns a JSON representing an error response."""
return json.dumps({
'success': False,
'error': message,
})
def check_key_in_json(content: str, keys: List[str]) -> str:
for key in keys:
if key not in content:
return error('No {} in request {}.'.format(key, content))
return None
def validate_json_key(json_key_string: str) -> Tuple[str, bool]:
try:
json_key = json.loads(json_key_string)
except (ValueError, TypeError):
return (error('Invalid key found in request'), False)
return (json_key, True)
# The health check route is required for docker deployment in google cloud.
@flask_app.route('/ping')
def ping() -> Response:
"""Health checks."""
return Response(status=200)
# The return should be `Response` for docker deployment in google cloud.
@flask_app.route('/predict', methods=['GET', 'POST'])
def predict_model() -> Response:
"""Predictions."""
if request.method == 'POST':
contents = request.get_json(force=True)
print('The input contents are:', contents)
batch_size = 1
num_steps = 25
seed = 1234
if 'parameters' in contents:
parameters = contents['parameters']
if 'batch_size' in parameters:
batch_size = int(parameters['batch_size'])
if 'num_steps' in parameters:
num_steps = int(parameters['num_steps'])
if 'seed' in parameters:
seed = int(parameters['seed'])
print('batch_size=', batch_size, 'num_steps=', num_steps, 'seed=', seed)
if batch_size < 1:
return Response(
response=error('The batch size must be a positive integar.'),
status=200,
mimetype='text/plain',
)
if num_steps < 1:
return Response(
response=error('The num steps must be a positive integar.'),
status=200,
mimetype='text/plain',
)
predictions = []
for content in contents['instances']:
print('Processing:', content)
prompt = content['prompt']
generated_image_array = stable_diffusion_model.text_to_image(
prompt=prompt,
batch_size=batch_size,
num_steps=num_steps,
seed=seed,
)
generated_image_bytes_array = []
for i in range(batch_size):
generated_image = Image.fromarray(generated_image_array[i])
# Converts the image to a base64-encoded string.
buffered_image = io.BytesIO()
generated_image.save(buffered_image, format='JPEG')
generated_image_bytes = base64.b64encode(
buffered_image.getvalue()
).decode('utf-8')
generated_image_bytes_array.append(generated_image_bytes)
prediction = {
'prompt': prompt,
'predicted_image': generated_image_bytes_array,
}
predictions.append(prediction)
return Response(
response=json.dumps({
'success': True,
'predictions': predictions,
}),
status=200,
mimetype='text/plain',
)
else:
return Response(
response=json.dumps({
'success': True,
'isalive': stable_diffusion_model is not None,
}),
status=200,
mimetype='text/plain',
)
def serve_main(unused_argv):
"""The main function to serve Keras models."""
del unused_argv
# This is used when running locally only. When deploying to Google App
# Engine, a webserver process such as Gunicorn will serve the app.
# # Debug deployment.
# flask_app.run(host='0.0.0.0', port=8501, debug=True)
# Prod deployment.
serve(flask_app, host='0.0.0.0', port=8501)
if __name__ == '__main__':
app.run(serve_main)
@@ -0,0 +1,363 @@
"""Train Keras Stable Diffusion.
Most the codes below are from
https://keras.io/examples/generative/finetune_stable_diffusion/.
"""
import os
from absl import app
from absl import flags
from absl import logging
import keras_cv
# pylint: disable=g-importing-member
from keras_cv.models.stable_diffusion.clip_tokenizer import SimpleTokenizer
from keras_cv.models.stable_diffusion.diffusion_model import DiffusionModel
from keras_cv.models.stable_diffusion.image_encoder import ImageEncoder
from keras_cv.models.stable_diffusion.noise_scheduler import NoiseScheduler
from keras_cv.models.stable_diffusion.text_encoder import TextEncoder
import numpy as np
# The docker builds could not find pandas.
# pylint: disable=import-error
import pandas as pd
import tensorflow as tf
from tensorflow import keras
import tensorflow.experimental.numpy as tnp
from util import constants
from util import fileutils
_INPUT_CSV_PATH = flags.DEFINE_string(
'input_csv_path',
None,
'The input csv path.',
required=True,
)
_USE_MP = flags.DEFINE_bool(
'use_mp',
True,
'Enable mixed-precision training if the underlying GPU has tensor cores.',
)
_EPOCHS = flags.DEFINE_integer('epochs', 1, 'The number of epochs.')
_OUTPUT_MODEL_DIR = flags.DEFINE_string(
'output_model_dir',
None,
'The output model dir.',
required=True,
)
# These hyperparameters defaults come from this tutorial by Hugging Face:
# https://huggingface.co/docs/diffusers/training/text2image
_LEARNING_RATE = flags.DEFINE_float(
'learning_rate', 1e-5, 'The learning rate parameter for AdamW optimizer.'
)
_BETA_1 = flags.DEFINE_float(
'beta_1', 0.9, 'The beta_1 parameter for AdamW optimizer.'
)
_BETA_2 = flags.DEFINE_float(
'beta_2', 0.999, 'The beta_2 parameter for AdamW optimizer.'
)
_WEIGHT_DECAY = flags.DEFINE_float(
'weight_decay', 1e-2, 'The weight decay parameter for AdamW optimizer.'
)
_EPSILON = flags.DEFINE_float(
'epsilon', 1e-08, 'The epsilon parameter for AdamW optimizer.'
)
RESOLUTION = int(os.environ.get('RESOLUTION', 512))
# The padding token and maximum prompt length are specific to the text encoder.
# If you're using a different text encoder be sure to change them accordingly.
PADDING_TOKEN = 49407
MAX_PROMPT_LENGTH = 77
AUTO = tf.data.AUTOTUNE
POS_IDS = tf.convert_to_tensor([list(range(MAX_PROMPT_LENGTH))], dtype=tf.int32)
augmenter = keras.Sequential(
layers=[
keras_cv.layers.CenterCrop(RESOLUTION, RESOLUTION),
keras_cv.layers.RandomFlip(),
tf.keras.layers.Rescaling(scale=1.0 / 127.5, offset=-1),
]
)
text_encoder = TextEncoder(MAX_PROMPT_LENGTH)
def process_image(image_path, tokenized_text):
image = tf.io.read_file(image_path)
image = tf.io.decode_png(image, 3)
image = tf.image.resize(image, (RESOLUTION, RESOLUTION))
return image, tokenized_text
def apply_augmentation(image_batch, token_batch):
return augmenter(image_batch), token_batch
def run_text_encoder(image_batch, token_batch):
return (
image_batch,
token_batch,
text_encoder([token_batch, POS_IDS], training=False),
)
def prepare_dict(image_batch, token_batch, encoded_text_batch):
return {
'images': image_batch,
'tokens': token_batch,
'encoded_text': encoded_text_batch,
}
def prepare_dataset(image_paths, tokenized_texts, batch_size=1):
dataset = tf.data.Dataset.from_tensor_slices((image_paths, tokenized_texts))
dataset = dataset.shuffle(batch_size * 10)
dataset = dataset.map(process_image, num_parallel_calls=AUTO).batch(
batch_size
)
dataset = dataset.map(apply_augmentation, num_parallel_calls=AUTO)
dataset = dataset.map(run_text_encoder, num_parallel_calls=AUTO)
dataset = dataset.map(prepare_dict, num_parallel_calls=AUTO)
return dataset.prefetch(AUTO)
def prepare_training_dataset(dataset_csv):
"""Prepares training datasets."""
if dataset_csv.startswith(constants.GCS_URI_PREFIX):
if not os.path.exists(constants.LOCAL_DATA_DIR):
os.makedirs(constants.LOCAL_DATA_DIR)
logging.info(
'Start to download data from %s to %s.',
os.path.dirname(dataset_csv),
constants.LOCAL_DATA_DIR,
)
fileutils.download_gcs_dir_to_local(
os.path.dirname(dataset_csv), constants.LOCAL_DATA_DIR
)
data_frame = pd.read_csv(
os.path.join(constants.LOCAL_DATA_DIR, os.path.basename(dataset_csv))
)
data_frame['image_path'] = data_frame['image_path'].apply(
lambda x: os.path.join(constants.LOCAL_DATA_DIR, x)
)
else:
# Keeps the following codes for experiments with
# https://keras.io/examples/generative/finetune_stable_diffusion/.
data_path = tf.keras.utils.get_file(origin=dataset_csv, untar=True)
data_frame = pd.read_csv(os.path.join(data_path, 'data.csv'))
data_frame['image_path'] = data_frame['image_path'].apply(
lambda x: os.path.join(data_path, x)
)
data_frame.head()
# Load the tokenizer.
tokenizer = SimpleTokenizer()
# Method to tokenize and pad the tokens.
def process_text(caption):
tokens = tokenizer.encode(caption)
tokens = tokens + [PADDING_TOKEN] * (MAX_PROMPT_LENGTH - len(tokens))
return np.array(tokens)
# Collate the tokenized captions into an array.
tokenized_texts = np.empty((len(data_frame), MAX_PROMPT_LENGTH))
all_captions = list(data_frame['caption'].values)
for i, caption in enumerate(all_captions):
tokenized_texts[i] = process_text(caption)
# Prepare the dataset.
training_dataset = prepare_dataset(
np.array(data_frame['image_path']), tokenized_texts, batch_size=4
)
return training_dataset
class Trainer(tf.keras.Model):
"""The trainer for Keras Stable Diffusion."""
# Reference:
# https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image.py
def __init__(
self,
diffusion_model,
vae,
noise_scheduler,
use_mixed_precision=False,
max_grad_norm=1.0,
**kwargs,
):
super().__init__(**kwargs)
self.diffusion_model = diffusion_model
self.vae = vae
self.noise_scheduler = noise_scheduler
self.max_grad_norm = max_grad_norm
self.use_mixed_precision = use_mixed_precision
self.vae.trainable = False
def train_step(self, inputs):
images = inputs['images']
encoded_text = inputs['encoded_text']
batch_size = tf.shape(images)[0]
with tf.GradientTape() as tape:
# Project image into the latent space and sample from it.
latents = self.sample_from_encoder_outputs(
self.vae(images, training=False)
)
# Know more about the magic number here:
# https://keras.io/examples/generative/fine_tune_via_textual_inversion/
latents = latents * 0.18215
# Sample noise that we'll add to the latents.
noise = tf.random.normal(tf.shape(latents))
# Sample a random timestep for each image.
timesteps = tnp.random.randint(
0, self.noise_scheduler.train_timesteps, (batch_size,)
)
# Add noise to the latents according to the noise magnitude at each
# timestep (this is the forward diffusion process).
noisy_latents = self.noise_scheduler.add_noise(
tf.cast(latents, noise.dtype), noise, timesteps
)
# Get the target for loss depending on the prediction type
# just the sampled noise for now.
target = noise # noise_schedule.predict_epsilon == True
# Predict the noise residual and compute loss.
# pylint: disable=unnecessary-lambda
timestep_embedding = tf.map_fn(
lambda t: self.get_timestep_embedding(t), timesteps, dtype=tf.float32
)
timestep_embedding = tf.squeeze(timestep_embedding, 1)
model_pred = self.diffusion_model(
[noisy_latents, timestep_embedding, encoded_text], training=True
)
loss = self.compiled_loss(target, model_pred)
if self.use_mixed_precision:
loss = self.optimizer.get_scaled_loss(loss)
# Update parameters of the diffusion model.
trainable_vars = self.diffusion_model.trainable_variables
gradients = tape.gradient(loss, trainable_vars)
if self.use_mixed_precision:
gradients = self.optimizer.get_unscaled_gradients(gradients)
gradients = [tf.clip_by_norm(g, self.max_grad_norm) for g in gradients]
self.optimizer.apply_gradients(zip(gradients, trainable_vars))
return {m.name: m.result() for m in self.metrics}
def get_timestep_embedding(self, timestep, dim=320, max_period=10000):
half = dim // 2
log_max_preiod = tf.math.log(tf.cast(max_period, tf.float32))
# The docker builds could not support unary `-`.
# pylint: disable=invalid-unary-operand-type
freqs = tf.math.exp(
-log_max_preiod * tf.range(0, half, dtype=tf.float32) / half
)
args = tf.convert_to_tensor([timestep], dtype=tf.float32) * freqs
embedding = tf.concat([tf.math.cos(args), tf.math.sin(args)], 0)
embedding = tf.reshape(embedding, [1, -1])
return embedding
def sample_from_encoder_outputs(self, outputs):
mean, logvar = tf.split(outputs, 2, axis=-1)
logvar = tf.clip_by_value(logvar, -30.0, 20.0)
std = tf.exp(0.5 * logvar)
sample = tf.random.normal(tf.shape(mean), dtype=mean.dtype)
return mean + std * sample
def save_weights(
self, filepath, overwrite=True, save_format=None, options=None
):
# Overriding this method will allow us to use the `ModelCheckpoint`
# callback directly with this trainer class. In this case, it will
# only checkpoint the `diffusion_model` since that's what we're training
# during fine-tuning.
self.diffusion_model.save_weights(
filepath=filepath,
overwrite=overwrite,
save_format=save_format,
options=options,
)
def main(_) -> None:
# _INPUT_CSV_PATH and _OUTPUT_MODEL_DIR should have the format as
# gs://<bucket_name>/<object_name>.
if _INPUT_CSV_PATH.value:
if not _INPUT_CSV_PATH.value.startswith(constants.GCS_URI_PREFIX):
raise ValueError('The input csv path should be a gcs path like gs://<>')
if _OUTPUT_MODEL_DIR.value:
if not _OUTPUT_MODEL_DIR.value.startswith(constants.GCS_URI_PREFIX):
raise ValueError('The output model dir should be a gcs path like gs://<>')
if _USE_MP.value:
keras.mixed_precision.set_global_policy('mixed_float16')
image_encoder = ImageEncoder(RESOLUTION, RESOLUTION)
diffusion_ft_trainer = Trainer(
diffusion_model=DiffusionModel(RESOLUTION, RESOLUTION, MAX_PROMPT_LENGTH),
# Remove the top layer from the encoder, which cuts off the variance and
# only returns the mean.
vae=tf.keras.Model(
image_encoder.input,
image_encoder.layers[-2].output,
),
noise_scheduler=NoiseScheduler(),
use_mixed_precision=_USE_MP.value,
)
optimizer = tf.keras.optimizers.experimental.AdamW(
learning_rate=_LEARNING_RATE.value,
weight_decay=_WEIGHT_DECAY.value,
beta_1=_BETA_1.value,
beta_2=_BETA_2.value,
epsilon=_EPSILON.value,
)
diffusion_ft_trainer.compile(optimizer=optimizer, loss='mse')
training_dataset = prepare_training_dataset(_INPUT_CSV_PATH.value)
# Note: gcsfuse does not work for Keras. We saves the trained models locally
# first, and then copy to gcs storages.
if not os.path.exists(constants.LOCAL_MODEL_DIR):
os.makedirs(constants.LOCAL_MODEL_DIR)
# The default saved model is in HDF5.
ckpt_path = os.path.join(constants.LOCAL_MODEL_DIR, 'saved_model.h5')
ckpt_callback = tf.keras.callbacks.ModelCheckpoint(
ckpt_path,
save_weights_only=True,
monitor='loss',
mode='min',
)
diffusion_ft_trainer.fit(
training_dataset, epochs=_EPOCHS.value, callbacks=[ckpt_callback]
)
# Copies the files in constants.LOCAL_MODEL_DIR to output_model_dir.
fileutils.upload_local_dir_to_gcs(
constants.LOCAL_MODEL_DIR, _OUTPUT_MODEL_DIR.value
)
return
if __name__ == '__main__':
app.run(main)
@@ -1,14 +0,0 @@
"""Video format converter util lib."""
import io
from typing import Sequence
import imageio
import numpy as np
from PIL import Image
def frames_to_video_bytes(frames: Sequence[np.ndarray], fps: int) -> bytes:
images = [Image.fromarray(array) for array in frames]
io_obj = io.BytesIO()
imageio.mimsave(io_obj, images, format=".mp4", fps=fps)
return io_obj.getvalue()
+1
View File
@@ -74,3 +74,4 @@
/notebooks/community/model_garden/model_garden_keras_stable_diffusion.ipynb @genquan9
/notebooks/community/model_garden/model_garden_pytorch_sam.ipynb @huguensjean
/notebooks/community/model_garden/model_garden_pytorch_peft.ipynb @genquan9
/notebooks/community/model_garden/model_garden_pytorch_openllama_peft.ipynb @genquan9
@@ -44,7 +44,7 @@
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td> <td>\n",
" <td>\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_keras_stable_diffusion.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",
@@ -282,8 +282,11 @@
"from io import BytesIO\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from google.cloud import storage\n",
"from PIL import Image\n",
"\n",
"GCS_URI_PREFIX = \"gs://\"\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/keras-train:latest\"\n",
@@ -317,6 +320,21 @@
" return gcs_path\n",
"\n",
"\n",
"def download_gcs_file_to_local(gcs_uri: str, local_path: str):\n",
" \"\"\"Download a gcs file to a local path.\n",
"\n",
" Args:\n",
" gcs_uri: A string of file path on GCS.\n",
" local_path: A string of local file path.\n",
" \"\"\"\n",
" if not gcs_uri.startswith(GCS_URI_PREFIX):\n",
" raise ValueError(f\"{gcs_uri} is not a GCS path starting with {GCS_URI_PREFIX}.\")\n",
" client = storage.Client()\n",
" os.makedirs(os.path.dirname(local_path), exist_ok=True)\n",
" with open(local_path, \"wb\") as f:\n",
" client.download_blob_to_file(gcs_uri, f)\n",
"\n",
"\n",
"def deploy_model(model_path, service_account):\n",
"\n",
" deploy_model_name = get_job_name_with_datetime(DEPLOY_JOB_PREFIX)\n",
@@ -420,7 +438,11 @@
"from keras_cv.models import StableDiffusion\n",
"\n",
"model = StableDiffusion(img_height=RESOLUTION, img_width=RESOLUTION, jit_compile=True)\n",
"if model_path:\n",
"if model_path.startswith(GCS_URI_PREFIX):\n",
" local_model_path = \"/tmp/saved_model.h5\"\n",
" download_gcs_file_to_local(model_path, local_model_path)\n",
" model.diffusion_model.load_weights(local_model_path)\n",
"elif model_path:\n",
" model.diffusion_model.load_weights(model_path)"
]
},
@@ -568,7 +590,7 @@
},
"source": [
"## Finetune models\n",
"This section shows how to finetune Keras Stable diffusion models with trainig dockers.\n",
"This section shows how to finetune Keras Stable diffusion models with training dockers.\n",
"\n",
"If you would like to use finetuned models, please go to the section `Run inferences`."
]
@@ -24,7 +24,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TirJ-SGQseby"
@@ -55,7 +54,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "dwGLvtIeECLK"
@@ -67,7 +65,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "tvgnzT1CKxrO"
@@ -107,7 +104,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "KEukV6uRk_S3"
@@ -138,7 +134,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "BF1j6f9HApxa"
@@ -196,7 +191,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "n6IFz75WGCam"
@@ -229,16 +223,13 @@
"# Evaluation constants.\n",
"EVALUATION_METRIC = \"accuracy\"\n",
"\n",
"# Prediction constants.\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_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
"# Prediction constant.\n",
"# Model does not support dedicated deployment resources.\n",
"# An n1-standard-4 machine with 1 P100 GPU will be used.\n",
"DEPLOY_JOB_PREFIX = \"deploy\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ZZFPe_GezXg8"
@@ -301,7 +292,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "Q149N3V6Uynm"
@@ -330,7 +320,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "8yfBZ1_8VZvq"
@@ -363,7 +352,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "RB_xY9ipr7ZU"
@@ -389,7 +377,6 @@
"- `model_type`: The type of model for deployment.\n",
" - `EFFICIENTNET`: A model that is available in Vertex Model Garden image classification training with customizable hyperparameters. Best tailored to be used within Google Cloud, and cannot be exported externally.\n",
" - `MAXVIT`: A model that is available in Vertex Model Garden image classification training with customizable hyperparameters. Best tailored to be used within Google Cloud, and cannot be exported externally.\n",
" - `COCA`: A model that is available in Vertex Model Garden image classification training with customizable hyperparameters. Best tailored to be used within Google Cloud, and cannot be exported externally.\n",
"- `checkpoint_name`: Optional. The field is reserved for Model Garden model training, based on the provided pre-trained model checkpoint.\n",
"- `trainer_config`: Optional. The field is usually used together with the Model Garden model training when passing the customized configs for the trainer.\n",
"\n",
@@ -457,7 +444,9 @@
"METRIC_SPEC_VALUE = \"maximize\"\n",
"SEARCH_ALGORITHM = \"random\"\n",
"MEASUREMENT_SELECTION = \"best\"\n",
"MODEL_TYPE = \"COCA\" # @param {type:\"string\"} one of the values [\"COCA\", \"MAXVIT\", \"EFFICIENTNET\"]\n",
"MODEL_TYPE = (\n",
" \"MAXVIT\" # @param {type:\"string\"} one of the values [\"MAXVIT\", \"EFFICIENTNET\"]\n",
")\n",
"\n",
"job = aiplatform.AutoMLImageTrainingJob(\n",
" display_name=get_job_name_with_datetime(TRAINING_JOB_PREFIX),\n",
@@ -478,7 +467,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "HwcCjwlBTQIz"
@@ -523,7 +511,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "g0BGaofgsMsy"
@@ -550,9 +537,9 @@
"\n",
"endpoint = model.deploy(\n",
" deployed_model_display_name=deploy_model_name,\n",
" machine_type=PREDICTION_MACHINE_TYPE,\n",
" machine_type=\"\",\n",
" traffic_split={\"0\": 100},\n",
" accelerator_type=PREDICTION_ACCELERATOR_TYPE,\n",
" accelerator_type=None,\n",
" accelerator_count=1,\n",
" min_replica_count=1,\n",
" max_replica_count=1,\n",
@@ -589,7 +576,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "kkH2nrpdp4sp"
@@ -24,7 +24,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TirJ-SGQseby"
@@ -55,7 +54,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "dwGLvtIeECLK"
@@ -67,7 +65,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "tvgnzT1CKxrO"
@@ -107,7 +104,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "KEukV6uRk_S3"
@@ -138,7 +134,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "BF1j6f9HApxa"
@@ -181,11 +176,11 @@
"# You can choose a region from https://cloud.google.com/about/locations.\n",
"# Only regions prefixed by \"us\", \"europe\", or \"asia\" are supported.\n",
"REGION = \"us-central1\" # @param {type:\"string\"}\n",
"REGION_PREFIX = REGION.split('-')[0]\n",
"REGION_PREFIX = REGION.split(\"-\")[0]\n",
"assert REGION_PREFIX in (\n",
" \"us\",\n",
" \"europe\",\n",
" \"asia\"\n",
" \"asia\",\n",
"), f'{REGION} is not supported. It must be prefixed by \"us\", \"europe\", or \"asia\".'\n",
"\n",
"! gcloud config set project $PROJECT_ID\n",
@@ -196,7 +191,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "n6IFz75WGCam"
@@ -227,14 +221,11 @@
"EVALUATION_METRIC = \"AP50\"\n",
"\n",
"# Prediction constants.\n",
"# You can adjust accelerator types and machine types to get faster predictions.\n",
"PREDICTION_ACCELERATOR_TYPE = \"NVIDIA_TESLA_T4\"\n",
"PREDICTION_MACHINE_TYPE = \"n1-standard-4\"\n",
"# An n1-standard-4 machine with 1 P100 GPU will be used.\n",
"DEPLOY_JOB_PREFIX = \"deploy\""
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ZZFPe_GezXg8"
@@ -357,7 +348,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "nZLVI9TtUuif"
@@ -386,7 +376,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "SZEdBfNZUxQn"
@@ -419,7 +408,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "RB_xY9ipr7ZU"
@@ -550,7 +538,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "HwcCjwlBTQIz"
@@ -595,7 +582,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "g0BGaofgsMsy"
@@ -622,9 +608,9 @@
"\n",
"endpoint = model.deploy(\n",
" deployed_model_display_name=deploy_model_name,\n",
" machine_type=PREDICTION_MACHINE_TYPE,\n",
" machine_type=\"\",\n",
" traffic_split={\"0\": 100},\n",
" accelerator_type=PREDICTION_ACCELERATOR_TYPE,\n",
" accelerator_type=None,\n",
" accelerator_count=1,\n",
" min_replica_count=1,\n",
" max_replica_count=1,\n",
@@ -661,7 +647,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "frcGP5HFX1XN"
@@ -0,0 +1,610 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7d9bbf86da5e"
},
"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": "99c1c3fc2ca5"
},
"source": [
"# Vertex AI Model Garden - OpenLLaMA (PEFT)\n",
"\n",
"<table align=\"left\">\n",
" <td>\n",
" <a href=\"https://colab.research.google.com/github/GoogleCloudPlatform/vertex-ai-samples/blob/main/notebooks/community/model_garden/model_garden_pytorch_openllama_peft.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_pytorch_openllama_peft.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/notebooks/deploy-notebook?download_url=https://raw.githubusercontent.com/GoogleCloudPlatform/vertex-ai-samples/main/notebooks/community/model_garden/model_garden_pytorch_openllama_peft.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> (A Python-3 CPU notebook is recommended)\n",
" </td>\n",
"</table>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3de7470326a2"
},
"source": [
"## Overview\n",
"\n",
"This notebook demonstrates deploying prebuilt OpenLLaMA, and also finetuning and deploying OpenLLaMA with performance efficient finetuning libraries ([PEFT](https://github.com/huggingface/peft)) in Vertex AI.\n",
"\n",
"### Objective\n",
"\n",
"- Deploy prebuilt OpenLLaMA\n",
"- Finetune and deploy OpenLLaMA with PEFT, supporting\n",
"\n",
"| Models | LoRA |\n",
"| :- | :- |\n",
"| [openlm-research/open_llama_3b](https://huggingface.co/openlm-research/open_llama_3b) | Y |\n",
"| [openlm-research/open_llama_7b](https://huggingface.co/openlm-research/open_llama_7b) | Y |\n",
"| [openlm-research/open_llama_13b](https://huggingface.co/openlm-research/open_llama_13b) | Y |\n",
"\n",
"### 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), and use the [Pricing Calculator](https://cloud.google.com/products/calculator/) to generate a cost estimate based on your projected usage."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "264c07757582"
},
"source": [
"## Before you begin\n",
"\n",
"**NOTE**: Jupyter runs lines prefixed with `!` as shell commands, and it interpolates Python variables prefixed with `$` into these commands."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ioensNKM8ned"
},
"source": [
"### Colab only\n",
"Run the following commands for Colab and skip this section if you are using Workbench."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2707b02ef5df"
},
"outputs": [],
"source": [
"import sys\n",
"\n",
"if \"google.colab\" in sys.modules:\n",
" ! pip3 install --upgrade google-cloud-aiplatform\n",
" from google.colab import auth as google_auth\n",
"\n",
" google_auth.authenticate_user()\n",
" # Install gdown for downloading example training images.\n",
" ! pip3 install gdown\n",
"\n",
" # Restart the notebook kernel after installs.\n",
" import IPython\n",
"\n",
" app = IPython.Application.instance()\n",
" app.kernel.do_shutdown(True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bb7adab99e41"
},
"source": [
"### Setup Google Cloud project\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 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.\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."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6c460088b873"
},
"source": [
"Fill following variables for experiments environment:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "855d6b96f291"
},
"outputs": [],
"source": [
"# Cloud project id.\n",
"PROJECT_ID = \"\" # @param {type:\"string\"}\n",
"\n",
"# The region you want to launch jobs in.\n",
"REGION = \"\" # @param {type:\"string\"}\n",
"\n",
"# The Cloud Storage bucket for storing experiments output.\n",
"BUCKET_URI = \"\" # @param {type:\"string\"}\n",
"\n",
"! gcloud config set project $PROJECT_ID\n",
"\n",
"import os\n",
"\n",
"STAGING_BUCKET = os.path.join(BUCKET_URI, \"temporal\")\n",
"EXPERIMENT_BUCKET = os.path.join(BUCKET_URI, \"peft\")\n",
"DATA_BUCKET = os.path.join(EXPERIMENT_BUCKET, \"data\")\n",
"MODEL_BUCKET = os.path.join(EXPERIMENT_BUCKET, \"model\")\n",
"\n",
"# The service account looks like:\n",
"# '@.iam.gserviceaccount.com'\n",
"# Please go to https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console\n",
"# and create service account with `Vertex AI User` and `Storage Object Admin` roles.\n",
"# The service account for deploying fine tuned model.\n",
"SERVICE_ACCOUNT = \"\" # @param {type:\"string\"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e828eb320337"
},
"source": [
"### Initialize Vertex AI API"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "12cd25839741"
},
"outputs": [],
"source": [
"from google.cloud import aiplatform\n",
"\n",
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=STAGING_BUCKET)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2cc825514deb"
},
"source": [
"### Define constants"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "b42bd4fa2b2d"
},
"outputs": [],
"source": [
"# The pre-built training and serving docker images.\n",
"TRAIN_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-peft-train\"\n",
"PREDICTION_DOCKER_URI = \"us-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/pytorch-peft-serve\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0c250872074f"
},
"source": [
"### Define common functions"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "354da31189dc"
},
"outputs": [],
"source": [
"import os\n",
"from datetime import datetime\n",
"\n",
"from google.cloud import aiplatform\n",
"\n",
"\n",
"def get_job_name_with_datetime(prefix: str):\n",
" \"\"\"Gets the job name with date time when triggering training or deployment\n",
" jobs in Vertex AI.\n",
" \"\"\"\n",
" return prefix + datetime.now().strftime(\"_%Y%m%d_%H%M%S\")\n",
"\n",
"\n",
"def deploy_model(\n",
" model_name,\n",
" base_model_id,\n",
" finetuned_lora_model_path,\n",
" service_account,\n",
" task,\n",
" machine_type=\"n1-standard-8\",\n",
" accelerator_type=\"NVIDIA_TESLA_V100\",\n",
"):\n",
" \"\"\"Deploys trained models into Vertex AI.\"\"\"\n",
" endpoint = aiplatform.Endpoint.create(display_name=f\"{model_name}-endpoint\")\n",
" serving_env = {\n",
" \"BASE_MODEL_ID\": base_model_id,\n",
" \"TASK\": task,\n",
" }\n",
" if finetuned_lora_model_path:\n",
" serving_env[\"FINETUNED_LORA_MODEL_PATH\"] = finetuned_lora_model_path\n",
" model = aiplatform.Model.upload(\n",
" display_name=model_name,\n",
" serving_container_image_uri=PREDICTION_DOCKER_URI,\n",
" serving_container_ports=[7080],\n",
" serving_container_predict_route=\"/predictions/peft_serving\",\n",
" serving_container_health_route=\"/ping\",\n",
" serving_container_environment_variables=serving_env,\n",
" )\n",
" model.deploy(\n",
" endpoint=endpoint,\n",
" machine_type=machine_type,\n",
" accelerator_type=accelerator_type,\n",
" accelerator_count=1,\n",
" deploy_request_timeout=1800,\n",
" service_account=service_account,\n",
" )\n",
" return model, endpoint"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8neJc8CnDDpu"
},
"source": [
"## Deploy Prebuilt OpenLLaMA\n",
"\n",
"This section deploys prebuilt OpenLLaMA models on the Endpoint. The model deployment step will take ~15 minutes to complete.\n",
"\n",
"The peak GPU memory usages for [openlm-research/open_llama_3b](https://huggingface.co/openlm-research/open_llama_3b), [openlm-research/open_llama_7b](https://huggingface.co/openlm-research/open_llama_7b), and [openlm-research/open_llama_13b](https://huggingface.co/openlm-research/open_llama_13b) are ~5.3G, ~8.7G and ~15.2G separately with the default settings. We use V100 in deployments for simplicity."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2MjaORIIFDVu"
},
"source": [
"Set the prebuilt model id."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "E8OiHHNNE_wj"
},
"outputs": [],
"source": [
"prebuilt_model_id = \"openlm-research/open_llama_3b\" # @param [\"openlm-research/open_llama_3b\", \"openlm-research/open_llama_7b\", \"openlm-research/open_llama_13b\"]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dHFW7yvjaVFV"
},
"source": [
"We use the PEFT serving images to deploy prebuilt OpenLLaMA models, by setting finetuning LoRA model paths as empty."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Uak1pyEeExYM"
},
"outputs": [],
"source": [
"model_without_peft, endpoint_without_peft = deploy_model(\n",
" model_name=get_job_name_with_datetime(prefix=\"openllama-serve\"),\n",
" base_model_id=prebuilt_model_id,\n",
" finetuned_lora_model_path=\"\", # This will avoid override finetuning models.\n",
" service_account=SERVICE_ACCOUNT,\n",
" task=\"causal-language-modeling-lora\",\n",
")\n",
"print(\"endpoint_name:\", endpoint_without_peft.name)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sGKIjgmDFRW2"
},
"source": [
"NOTE: The prebuilt model weights will be downloaded on the fly from the orginal location after the deployment succeeds. Thus additional 5 minutes of waiting time is needed **after** the above model deployment step succeeds and before you run the next step below. Otherwise you might see a `ServiceUnavailable: 503 502:Bad Gateway` error when you send requests to the endpoint.\n",
"\n",
"Once deployment succeeds, you can send requests to the endpoint with text prompts."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "rDHsCOqvFYBi"
},
"outputs": [],
"source": [
"# # Loads an existing endpoint as below.\n",
"# endpoint_name = endpoint_without_peft.name\n",
"# aip_endpoint_name = (\n",
"# f\"projects/{PROJECT_ID}/locations/{REGION}/endpoints/{endpoint_name}\"\n",
"# )\n",
"# endpoint_without_peft = aiplatform.Endpoint(aip_endpoint_name)\n",
"instances = [\n",
" {\"prompt\": \"Hi, Google.\"},\n",
"]\n",
"response = endpoint_without_peft.predict(instances=instances)\n",
"\n",
"for prediction in response.predictions[0]:\n",
" print(prediction[\"generated_text\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e70e3519ff8b"
},
"source": [
"## Finetune and deploy OpenLLaMA with PEFT\n",
"\n",
"This section demonstrates how to finetune and dpeloy OpenLLaMA with PEFT LoRA."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5qCrm_kJH5cz"
},
"source": [
"Set the base model id."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "N3UBLiYrM3sU"
},
"outputs": [],
"source": [
"base_model_id = \"openlm-research/open_llama_3b\" # @param [\"openlm-research/open_llama_3b\", \"openlm-research/open_llama_7b\", \"openlm-research/open_llama_13b\"]"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iWGwJHqI7LMs"
},
"source": [
"### Finetune"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KKEYoRfiHDVv"
},
"source": [
"Use the Vertex AI SDK to create and run the custom training jobs with Vertex AI Model Garden training images.\n",
"\n",
"This example uses the dataset [Abirate/english_quotes](https://huggingface.co/datasets/Abirate/english_quotes).\n",
"\n",
"In order to make the finetuning efficiently, we enabled quantization (8bits) when loading pretrained models for finetuning LoRA models. The peak GPU memory usages are ~7G, ~10G and ~16G for finetuning LoRA models for [openlm-research/open_llama_3b](https://huggingface.co/openlm-research/open_llama_3b), [openlm-research/open_llama_7b](https://huggingface.co/openlm-research/open_llama_7b), and [openlm-research/open_llama_13b](https://huggingface.co/openlm-research/open_llama_13b) separately with default training parameters and the example dataset. In theory, open_llama_3b and open_llama_7b can be finetuned on 1 V100, and open_llama_13b can be finetuned on 1 A100 (40G). We choose to use 1 A100 (40G) by default to support all these models in this notebook for simplicity."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "65467b361315"
},
"outputs": [],
"source": [
"dataset_name = \"Abirate/english_quotes\" # @param {type:\"string\"}\n",
"\n",
"# Worker pool spec.\n",
"# machine_type = \"n1-standard-8\"\n",
"# accelerator_type = \"NVIDIA_TESLA_V100\"\n",
"machine_type = \"a2-highgpu-1g\"\n",
"accelerator_type = \"NVIDIA_TESLA_A100\"\n",
"replica_count = 1\n",
"accelerator_count = 1\n",
"\n",
"# Setup training job.\n",
"job_name = get_job_name_with_datetime(\"openllama-lora-train\")\n",
"train_job = aiplatform.CustomContainerTrainingJob(\n",
" display_name=job_name,\n",
" container_uri=TRAIN_DOCKER_URI,\n",
")\n",
"output_dir = os.path.join(MODEL_BUCKET, job_name)\n",
"output_dir_gcsfuse = output_dir.replace(\"gs://\", \"/gcs/\")\n",
"\n",
"# Pass training arguments and launch job.\n",
"train_job.run(\n",
" args=[\n",
" \"--task=causal-language-modeling-lora\",\n",
" f\"--pretrained_model_id={base_model_id}\",\n",
" f\"--dataset_name={dataset_name}\",\n",
" f\"--output_dir={output_dir_gcsfuse}\",\n",
" \"--lora_rank=16\",\n",
" \"--lora_alpha=32\",\n",
" \"--lora_dropout=0.05\",\n",
" \"--warmup_steps=10\",\n",
" \"--max_steps=10\",\n",
" \"--learning_rate=2e-4\",\n",
" ],\n",
" replica_count=replica_count,\n",
" machine_type=machine_type,\n",
" accelerator_type=accelerator_type,\n",
" accelerator_count=accelerator_count,\n",
" boot_disk_size_gb=500,\n",
")\n",
"\n",
"print(\"Trained models were saved in: \", output_dir)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jqmCtkGnhDmp"
},
"source": [
"### Deploy\n",
"This section uploads the model to Model Registry and deploys it on the Endpoint.\n",
"\n",
"The model deployment step will take ~15 minutes to complete.\n",
"\n",
"The peak GPU memory usages for [openlm-research/open_llama_3b](https://huggingface.co/openlm-research/open_llama_3b), [openlm-research/open_llama_7b](https://huggingface.co/openlm-research/open_llama_7b), and [openlm-research/open_llama_13b](https://huggingface.co/openlm-research/open_llama_13b) with LoRA weights are ~5.3G, ~8.7G and ~15.2G separately with the default settings. We use V100 in deployments for simplicity."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bf55e38815dc"
},
"outputs": [],
"source": [
"model_with_peft, endpoint_with_peft = deploy_model(\n",
" model_name=get_job_name_with_datetime(prefix=\"openllama-peft-serve\"),\n",
" base_model_id=base_model_id,\n",
" finetuned_lora_model_path=output_dir,\n",
" service_account=SERVICE_ACCOUNT,\n",
" task=\"causal-language-modeling-lora\",\n",
")\n",
"print(\"endpoint_name:\", endpoint_with_peft.name)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "80b3fd2ace09"
},
"source": [
"NOTE: After the deployment succeeds, the base model weights will be downloaded one the fly from the original location and LoRA model weights will be downloaded from the GCS bucket used in training above. Thus additional 5 minutes of waiting time is needed **after** the above model deployment step succeeds and before you run the next step below. Otherwise you might see a `ServiceUnavailable: 503 502:Bad Gateway` error when you send requests to the endpoint.\n",
"\n",
"Once deployment succeeds, you can send requests to the endpoint with text prompts."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "4ab04da3ec9a"
},
"outputs": [],
"source": [
"# # Loads an existing endpoint as below.\n",
"# endpoint_name = endpoint_with_peft.name\n",
"# aip_endpoint_name = (\n",
"# f\"projects/{PROJECT_ID}/locations/{REGION}/endpoints/{endpoint_name}\"\n",
"# )\n",
"# endpoint_with_peft = aiplatform.Endpoint(aip_endpoint_name)\n",
"instances = [\n",
" {\"prompt\": \"Hi, Google.\"},\n",
"]\n",
"response = endpoint_with_peft.predict(instances=instances)\n",
"\n",
"for prediction in response.predictions[0]:\n",
" print(prediction[\"generated_text\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "af21a3cff1e0"
},
"source": [
"## Clean up resources"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "911406c1561e"
},
"outputs": [],
"source": [
"# Delete custom train jobs.\n",
"train_job.delete()\n",
"\n",
"# Undeploy model and delete endpoint.\n",
"endpoint_without_peft.delete(force=True)\n",
"endpoint_with_peft.delete(force=True)\n",
"\n",
"# Delete models.\n",
"model_without_peft.delete()\n",
"model_with_peft.delete()"
]
}
],
"metadata": {
"colab": {
"name": "model_garden_pytorch_openllama_peft.ipynb",
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@@ -649,14 +649,13 @@
"# # If deploy finetuned falcon-40b-instruct models, please set\n",
"# machine_type = \"a2-highgpu-1g\",\n",
"# accelerator_type = \"NVIDIA_TESLA_A100\"\n",
"machine_type = \"n1-standard-8\",\n",
"machine_type = \"n1-standard-8\"\n",
"accelerator_type = \"NVIDIA_TESLA_V100\"\n",
"\n",
"accelerator_type =\n",
"model, endpoint = deploy_model(\n",
" model_name=get_job_name_with_datetime(prefix=\"falcon-peft-serve\"),\n",
" base_model_id=base_model_id,\n",
" finetuned_lora_model_path=os.path.join(output_dir, \"checkpoint-\"+str(max_steps)),\n",
" finetuned_lora_model_path=os.path.join(output_dir, \"checkpoint-\" + str(max_steps)),\n",
" service_account=SERVICE_ACCOUNT,\n",
" task=\"instruct-lora\",\n",
" machine_type=machine_type,\n",
@@ -262,6 +262,8 @@
},
"outputs": [],
"source": [
"import urllib\n",
"\n",
"import timm\n",
"import torch\n",
"from PIL import Image\n",
@@ -24,7 +24,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TirJ-SGQseby"
@@ -45,7 +44,7 @@
" View on GitHub\n",
" </a>\n",
" </td>\n",
" <td> <td>\n",
" <td>\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_tfvision_image_object_detection.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",
@@ -55,7 +54,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "dwGLvtIeECLK"
@@ -67,7 +65,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "tvgnzT1CKxrO"
@@ -106,7 +103,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "KEukV6uRk_S3"
@@ -116,7 +112,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "z__i0w0lCAsW"
@@ -149,7 +144,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "BF1j6f9HApxa"
@@ -217,11 +211,13 @@
"! 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/\n",
"\n",
"! wget https://github.com/tensorflow/models/blob/master/official/projects/yolo/configs/experiments/yolov7/detection/yolov7_gpu.yaml\n",
"! gsutil cp yolov7_gpu.yaml $CONFIG_DIR/"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "n6IFz75WGCam"
@@ -262,6 +258,7 @@
" CONFIG_DIR, \"coco_spinenet143_gpu_multiworker_mirrored.yaml\"\n",
")\n",
"TRAIN_YOLOV4_CONFIG = os.path.join(CONFIG_DIR, \"scaled_yolov4_1280_gpu.yaml\")\n",
"TRAIN_YOLOV7_CONFIG = os.path.join(CONFIG_DIR, \"yolov7_gpu.yaml\")\n",
"\n",
"# Evaluation constants.\n",
"EVALUATION_METRIC = \"AP50\"\n",
@@ -285,7 +282,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ZZFPe_GezXg8"
@@ -510,7 +506,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "RB_xY9ipr7ZU"
@@ -526,7 +521,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "zgPO1eR3CYjk"
@@ -603,7 +597,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "SA8DVTn7j69v"
@@ -615,7 +608,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "aaff6f5be7f6"
@@ -649,7 +641,7 @@
"\n",
"# Refer to https://github.com/tensorflow/models/blob/master/official/vision/MODEL_GARDEN.md\n",
"# for more model details.\n",
"experiment = \"retinanet_spinenet96\" # @param ['retinanet_spinenet49', \"retinanet_spinenet96\", 'retinanet_spinenet143', 'scaled_yolo_v4']\n",
"experiment = \"retinanet_spinenet96\" # @param ['retinanet_spinenet49', \"retinanet_spinenet96\", 'retinanet_spinenet143', 'scaled_yolo_v4', 'yolov7']\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",
@@ -706,6 +698,15 @@
" \"input_size\": \"1280,1280\",\n",
" },\n",
" ),\n",
" # yolov7 experiment args.\n",
" \"yolov7\": dict(\n",
" common_args,\n",
" **{\n",
" \"experiment\": \"coco_yolov7\",\n",
" \"config_file\": TRAIN_YOLOV7_CONFIG,\n",
" \"input_size\": \"640,640\",\n",
" },\n",
" ),\n",
"}\n",
"experiment_container_args = experiment_container_args_dict[experiment]\n",
"\n",
@@ -715,6 +716,8 @@
" experiment_container_args[\"init_checkpoint\"] = upload_checkpoint_to_gcs(\n",
" init_checkpoint\n",
" )\n",
"if \"yolov7\" in experiment:\n",
" TRAIN_CONTAINER_URI = f\"{REGION_PREFIX}-docker.pkg.dev/vertex-ai-restricted/vertex-vision-model-garden-dockers/tfvision-oss-v2\"\n",
"\n",
"params_override = \"runtime.num_gpus=%s\" % TRAIN_NUM_GPU\n",
"eval_params_override = \"runtime.num_gpus=1,runtime.distribution_strategy=mirrored\"\n",
@@ -768,7 +771,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "HwcCjwlBTQIz"
@@ -817,7 +819,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "mV-Djz-frBni"
@@ -878,7 +879,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "g0BGaofgsMsy"
@@ -904,11 +904,12 @@
"\n",
"upload_job_name = get_job_name_with_datetime(UPLOAD_JOB_PREFIX + \"_\" + OBJECTIVE)\n",
"\n",
"if 'yolo' in experiment:\n",
"if \"yolo\" in experiment:\n",
" SERVING_CONTAINER_ARGS = [\"--allow_precompilation\"]\n",
"else:\n",
" SERVING_CONTAINER_ARGS = [\"--allow_precompilation\", \"--allow_compression\"]\n",
"\n",
"\n",
"model = aiplatform.Model.upload(\n",
" display_name=upload_job_name,\n",
" artifact_uri=trained_model_dir,\n",
@@ -982,7 +983,6 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "kkH2nrpdp4sp"
@@ -88,8 +88,8 @@
"- Make a batch prediction with the BigQuery ML model.\n",
"- Create a Vertex AI `Dataset` resource.\n",
"- Train the Vertex AI Forecasting model.\n",
"- View the Model evaluation.\n",
"- Make a batch prediction with the Model.\n"
"- View the Vertex AI Model Evaluation results.\n",
"- Make a batch prediction with the Vertex AI Forecasting model.\n"
]
},
{
@@ -29,7 +29,7 @@
"id": "JAPoU8Sm5E6e"
},
"source": [
"# Vertex AI Pipelines: Evaluating BatchPrediction results from a Custom Tabular classification model\n",
"# Vertex AI Pipelines: Evaluating BatchPrediction results from a custom tabular classification model\n",
"\n",
"<table align=\"left\">\n",
"\n",
@@ -151,15 +151,16 @@
"outputs": [],
"source": [
"# Install the latest versions of the following packages\n",
"! pip3 install --upgrade google-cloud-aiplatform \\\n",
" google-cloud-pipeline-components==1.0.26 \\\n",
" matplotlib \\\n",
" pyarrow -q\n",
"! pip3 install --upgrade --quiet google-cloud-aiplatform \\\n",
" google-cloud-pipeline-components==1.0.26 \\\n",
" matplotlib \\\n",
" pyarrow \n",
"# Install the specified versions of the following packages\n",
"! pip3 install scikit-learn==1.0 \\\n",
" pandas \\\n",
" joblib==1.2.0 \\\n",
" numpy==1.23.3 -q"
"! pip3 install --quiet scikit-learn==1.0 \\\n",
" pandas \\\n",
" joblib==1.2.0 \\\n",
" numpy==1.23.3 \\\n",
" db-dtypes"
]
},
{
@@ -401,12 +402,25 @@
},
"outputs": [],
"source": [
"if SERVICE_ACCOUNT == \"[your-service-account]\":\n",
" shell_output = ! gcloud projects list --filter=\"PROJECT_ID:'{PROJECT_ID}'\" --format='value(PROJECT_NUMBER)'\n",
" PROJECT_NUMBER = shell_output[0]\n",
" SERVICE_ACCOUNT = f\"{PROJECT_NUMBER}-compute@developer.gserviceaccount.com\"\n",
"import sys\n",
"\n",
"print(\"Service Account:\", SERVICE_ACCOUNT)"
"IS_COLAB = \"google.colab\" in sys.modules\n",
"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",
" else: # 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)"
]
},
{
@@ -1035,6 +1049,34 @@
"RUN pip install -r requirements.txt"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OrpUIkAIs_uQ"
},
"source": [
"#### Create a private Docker repository\n",
"\n",
"Your first step is to create your own Docker repository in Google Artifact Registry."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "0amu4063tDnG"
},
"outputs": [],
"source": [
"import os\n",
"\n",
"! gcloud services enable artifactregistry.googleapis.com\n",
"\n",
"if os.getenv(\"IS_TESTING\"):\n",
" ! sudo apt-get update --yes && sudo apt-get --only-upgrade --yes install google-cloud-sdk-cloud-run-proxy google-cloud-sdk-harbourbridge google-cloud-sdk-cbt google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-sdk-kpt google-cloud-sdk-local-extract google-cloud-sdk-minikube google-cloud-sdk-app-engine-java google-cloud-sdk-app-engine-go google-cloud-sdk-app-engine-python google-cloud-sdk-spanner-emulator google-cloud-sdk-bigtable-emulator google-cloud-sdk-nomos google-cloud-sdk-package-go-module google-cloud-sdk-firestore-emulator kubectl google-cloud-sdk-datastore-emulator google-cloud-sdk-app-engine-python-extras google-cloud-sdk-cloud-build-local google-cloud-sdk-kubectl-oidc google-cloud-sdk-anthos-auth google-cloud-sdk-app-engine-grpc google-cloud-sdk-pubsub-emulator google-cloud-sdk-datalab google-cloud-sdk-skaffold google-cloud-sdk google-cloud-sdk-terraform-tools google-cloud-sdk-config-connector\n",
" ! gcloud components update --quiet"
]
},
{
"cell_type": "markdown",
"metadata": {
File diff suppressed because one or more lines are too long
@@ -24,6 +24,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "eBEO2w9My9py"
@@ -50,10 +51,11 @@
" </a>\n",
" </td>\n",
"</table>\n",
"<br/><br/><br/>"
"<br/><br/><br/>\n"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "VL7XCFV7yCBU"
@@ -95,6 +97,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "UE8vLw7SlpwE"
@@ -118,6 +121,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "fbF2lF8rlp3I"
@@ -129,6 +133,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "yajq2millpnu"
@@ -145,39 +150,7 @@
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lAcDYZfslpeF"
},
"source": [
"### Set up your local development environment\n",
"\n",
"**If you are using Colab or Vertex AI Workbench**, your environment already meets all the requirements to run this notebook. You can skip this step.\n",
"\n",
"Otherwise, make sure your environment meets this notebook's requirements. You need the following:\n",
"\n",
"- The Cloud Storage SDK\n",
"- Git\n",
"- Python 3\n",
"- virtualenv\n",
"- Jupyter notebook running in a virtual environment with Python 3\n",
"\n",
"The Cloud Storage guide to [Setting up a Python development environment](https://cloud.google.com/python/setup) and the [Jupyter installation guide](https://jupyter.org/install) provide detailed instructions for meeting these requirements. The following steps provide a condensed set of instructions:\n",
"\n",
"1. [Install and initialize the SDK](https://cloud.google.com/sdk/docs/).\n",
"\n",
"2. [Install Python 3](https://cloud.google.com/python/setup#installing_python).\n",
"\n",
"3. [Install virtualenv](https://cloud.google.com/python/setup#installing_and_using_virtualenv) and create a virtual environment that uses Python 3. Activate the virtual environment.\n",
"\n",
"4. To install Jupyter, run `pip3 install jupyter` on the command-line in a terminal shell.\n",
"\n",
"5. To launch Jupyter, run `jupyter notebook` on the command-line in a terminal shell.\n",
"\n",
"6. Open this notebook in the Jupyter Notebook Dashboard."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "s3moH5AexXpk"
@@ -196,343 +169,221 @@
},
"outputs": [],
"source": [
"import os\n",
"\n",
"# The Vertex AI Workbench Notebook product has specific requirements\n",
"IS_WORKBENCH_NOTEBOOK = os.getenv(\"DL_ANACONDA_HOME\")\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 google-cloud-aiplatform {USER_FLAG} -q\n",
"\n",
"# Automatically restart kernel after installs\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)"
"! pip3 install --upgrade --quiet google-cloud-aiplatform "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "cczxMMkYK9a4"
"id": "restart"
},
"source": [
"## Before you begin"
"### Colab only: Uncomment the following cell to restart the kernel.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bzPxhxS5lugp"
},
"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)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "64BZ1jL5GEi0"
"id": "d2qpIurSjmpT"
},
"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",
"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 APIs and Cloud Storage.](https://console.cloud.google.com/flows/enableapi?apiid=ml.googleapis.com,storage-component.googleapis.com)\n",
"3. [Enable the following APIs: Vertex AI API, Cloud Resource Manager API](https://console.cloud.google.com/flows/enableapi?apiid=aiplatform.googleapis.com,cloudresourcemanager.googleapis.com).\n",
"\n",
"4. If you are running this notebook locally, you will need to install the [Cloud SDK](https://cloud.google.com/sdk).\n",
"\n",
"\n",
"5. 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 `$`."
"4. If you are running this notebook locally, you need to install the [Cloud SDK](https://cloud.google.com/sdk)."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "UIl_kn1pGH_T"
"id": "project_id"
},
"source": [
"### Set your project ID"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Maw6BYbPA0kn"
},
"source": [
"**If you don't know your project ID**, you may be able to get your project ID using `gcloud`.\n"
"#### 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": "sw4J6j5tBZWp"
"id": "wsePm9c4jmpT"
},
"outputs": [],
"source": [
"PROJECT_ID = \"\"\n",
"PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}\n",
"\n",
"import os\n",
"\n",
"# Get your Google Cloud project ID from gcloud\n",
"if not os.getenv(\"IS_TESTING\"):\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)"
"# Set the project id\n",
"! gcloud config set project {PROJECT_ID}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "EJj3d9GxBd3b"
"id": "a54f9d7c1876"
},
"source": [
"Otherwise, set your project ID here."
"#### 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": "75C2px4XtS5l"
"id": "3aaadaaf9b30"
},
"outputs": [],
"source": [
"if PROJECT_ID == \"\" or PROJECT_ID is None:\n",
" PROJECT_ID = \"[your-project-id]\" # @param {type:\"string\"}"
"REGION = \"us-central1\" # @param {type: \"string\"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "Z36ycwA4IjYC"
"id": "5c0404984792"
},
"source": [
"### Timestamp"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MngMavafIrQa"
},
"source": [
"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 timestamp for each instance session, and append it onto the name of resources you create in this tutorial."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "uddA3D7yIn-L"
},
"outputs": [],
"source": [
"from datetime import datetime\n",
"### Authenticate your Google Cloud account\n",
"\n",
"TIMESTAMP = datetime.now().strftime(\"%Y%m%d%H%M%S\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6yPUOueCF3pI"
},
"source": [
"### Set your region"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "gzEibeHGF1jb"
},
"outputs": [],
"source": [
"REGION = \"[your-region]\" # @param {type: \"string\"}\n",
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below.\n",
"\n",
"if REGION == \"[your-region]\":\n",
" REGION = \"us-central1\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jetPysDMtV1-"
},
"source": [
"### Login to your Google Cloud account"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "IK8eOR8tt6TI"
},
"outputs": [],
"source": [
"# The Google Cloud Notebook product has specific requirements\n",
"import os\n",
"import sys\n",
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated.\n",
"\n",
"IS_GOOGLE_CLOUD_NOTEBOOK = os.path.exists(\"/opt/deeplearning/metadata/env_version\")\n",
"**2. Local JupyterLab instance, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Nt8cEM2GjmpU"
},
"outputs": [],
"source": [
"# ! gcloud auth login"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "XUSL_JcpjmpU"
},
"source": [
"**3. Colab, uncomment and run:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_2zemfGvjmpU"
},
"outputs": [],
"source": [
"# from google.colab import auth\n",
"# auth.authenticate_user()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TCPJ38n7jmpU"
},
"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."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "bucket:custom"
},
"source": [
"### Create a Cloud Storage bucket\n",
"\n",
"IS_COLAB = \"google.colab\" in sys.modules\n",
"# If on Google Cloud Notebooks, then don't execute this code\n",
"if not IS_GOOGLE_CLOUD_NOTEBOOK:\n",
" if IS_COLAB:\n",
" from google.colab import auth as google_auth\n",
"Create a storage bucket to store intermediate artifacts such as datasets.\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 ''"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tU1OEt8ibhLS"
},
"source": [
"###Create Cloud Storage bucket\n",
"A Cloud Storage bucket will be used to a) store your training code distribution (details below), and b) the outputs (including TensorBoard logs) your training code generates. The bucket must be regional that is, not multi-region or dual-region, and the following resources must be in same region:\n",
"\n",
"* the Cloud Storage bucket\n",
"* the Vertex AI training job\n",
"* the Vertex AI TensorBoard instance"
"When you submit a training job using the Cloud SDK, you upload a Python package\n",
"containing your training code to a Cloud Storage bucket. Vertex AI runs\n",
"the code from this package. In this tutorial, Vertex AI also saves the\n",
"trained model that results from your job in the same bucket. Using this model artifact, you can then\n",
"create Vertex AI Model resource and use for prediction."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "HYu2_qM9b3Cn"
"id": "bucket"
},
"outputs": [],
"source": [
"BUCKET_URI = \"gs://[your-bucket-name]\" # @param {type:\"string\"}\n",
"\n",
"if BUCKET_URI == \"\" or BUCKET_URI is None or BUCKET_URI == \"gs://[your-bucket-name]\":\n",
" BUCKET_URI = \"gs://\" + PROJECT_ID + \"aip-\" + TIMESTAMP"
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "qo1KHfJ2b83V"
"id": "create_bucket"
},
"source": [
"**Only if your bucket doesn't already exist**: Run the following cell to create your Cloud Storage bucket. The created bucket will be deleted in the cleaning up section in the end. "
"**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": "imVC-rXxb8A1"
"id": "Oz8J0vmSlugt"
},
"outputs": [],
"source": [
"! gsutil mb -l {REGION} -p {PROJECT_ID} {BUCKET_URI}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1VU7ukLOcCa1"
},
"source": [
"Finally, validate access to your Cloud Storage bucket by examining its contents:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "_wil_Y9lcHhZ"
},
"outputs": [],
"source": [
"! gsutil ls -al {BUCKET_URI}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lx8UKHsccMDe"
},
"source": [
"Set up the GCS paths for traing code and outputs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "phyaIjuHcPdH"
},
"outputs": [],
"source": [
"GCS_BUCKET_TRAINING = BUCKET_URI + \"/training/\"\n",
"GCS_BUCKET_OUTPUT = BUCKET_URI + \"/output/\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KIPcg_Xhwvsn"
},
"source": [
"### Import aiplatform"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "p4w8c1pHw2Yt"
},
"outputs": [],
"source": [
"import google.cloud.aiplatform as aiplatform"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "cVmlv9sRbCSs"
},
"source": [
"### Initialize Vertex AI SDK for Python\n",
"Initialize the Vertex AI SDK for Python for your project and corresponding bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "JmEsq1fda_1N"
},
"outputs": [],
"source": [
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_URI)"
"! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "hwXxa4Qgnh4Y"
@@ -542,6 +393,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "7qXFUiHLoFRw"
@@ -569,6 +421,9 @@
},
"outputs": [],
"source": [
"import sys\n",
"\n",
"IS_COLAB = \"google.colab\" in sys.modules\n",
"if (\n",
" SERVICE_ACCOUNT == \"\"\n",
" or SERVICE_ACCOUNT is None\n",
@@ -616,6 +471,50 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "KIPcg_Xhwvsn"
},
"source": [
"### Import libraries"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "p4w8c1pHw2Yt"
},
"outputs": [],
"source": [
"import google.cloud.aiplatform as aiplatform"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "cVmlv9sRbCSs"
},
"source": [
"### Initialize Vertex AI SDK for Python\n",
"Initialize the Vertex AI SDK for Python for your project and corresponding bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "JmEsq1fda_1N"
},
"outputs": [],
"source": [
"aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_URI)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "dR2mOCllvlqN"
@@ -664,6 +563,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "vjdLIqYyDZFS"
@@ -790,6 +690,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "L067Jw_QFcZ3"
@@ -814,6 +715,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "a7Gt9WPFG9V7"
@@ -830,10 +732,12 @@
},
"outputs": [],
"source": [
"GCS_BUCKET_TRAINING = f\"{BUCKET_URI}/data/\"\n",
"! gsutil cp dist/hello-custom-training-3.0.tar.gz {GCS_BUCKET_TRAINING}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "IaQjIPvuKLwW"
@@ -843,6 +747,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "svUGBOow_Obj"
@@ -866,7 +771,7 @@
" or TENSORBOARD_NAME is None\n",
" or TENSORBOARD_NAME == \"[your-tensorboard-name]\"\n",
"):\n",
" TENSORBOARD_NAME = PROJECT_ID + \"-tb-\" + TIMESTAMP\n",
" TENSORBOARD_NAME = PROJECT_ID + \"-tb\"\n",
"\n",
"tensorboard = aiplatform.Tensorboard.create(\n",
" display_name=TENSORBOARD_NAME, project=PROJECT_ID, location=REGION\n",
@@ -876,6 +781,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "mudxBDal_a_k"
@@ -892,8 +798,9 @@
},
"outputs": [],
"source": [
"JOB_NAME = \"tensorboard-example-job-{}\".format(TIMESTAMP)\n",
"BASE_OUTPUT_DIR = \"{}{}\".format(GCS_BUCKET_OUTPUT, JOB_NAME)\n",
"JOB_NAME = \"tensorboard-example-job\"\n",
"GCS_BUCKET_OUTPUT = BUCKET_URI\n",
"BASE_OUTPUT_DIR = \"{}/{}\".format(GCS_BUCKET_OUTPUT, JOB_NAME)\n",
"\n",
"job = aiplatform.CustomPythonPackageTrainingJob(\n",
" display_name=JOB_NAME,\n",
@@ -914,6 +821,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "VfMsn_RnEtnj"
@@ -923,6 +831,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TFEriiywMZga"
@@ -24,6 +24,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "l2mMvIUG9meX"
@@ -91,6 +92,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "zfXf0r-K81Y-"
@@ -102,6 +104,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "I3KFLvpq87rs"
@@ -122,6 +125,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ze4-nDLfK4pw"
@@ -144,6 +148,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "aUw6ibN-n5Za"
@@ -168,6 +173,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "LgFWLeJfoGQu"
@@ -189,6 +195,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "8ckyxpX_oSzD"
@@ -217,6 +224,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "mSQjVQmMosMl"
@@ -239,6 +247,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "IfJRIMBpo5Pg"
@@ -246,25 +255,11 @@
"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": "acFN0s3So9-Y"
},
"source": [
"Depending on your Jupyter environment, you may have to manually authenticate. Follow the relevant instructions below.\n",
"\n",
"**1. Vertex AI Workbench**\n",
"* Do nothing as you are already authenticated."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dQ_mNwuapE5T"
},
"source": [
"* Do nothing as you are already authenticated.\n",
"\n",
"**2. Local JupyterLab instance, uncomment and run:**"
]
},
@@ -280,6 +275,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "h-MuVI_ypJfw"
@@ -301,6 +297,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "3ivZkPUjpaFz"
@@ -322,6 +319,35 @@
"SERVICE_ACCOUNT = \"[your-service-account]\" # @param {type:\"string\"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "autoset_service_account"
},
"outputs": [],
"source": [
"import sys\n",
"\n",
"IS_COLAB = \"google.colab\" in sys.modules\n",
"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": "code",
"execution_count": null,
@@ -347,6 +373,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "OKtKGmr9pfr6"
@@ -365,10 +392,11 @@
},
"outputs": [],
"source": [
"BUCKET_URI = \"gs://your-bucket-name-unique\" # @param {type:\"string\"}"
"BUCKET_URI = f\"gs://your-bucket-name-{PROJECT_ID}-unique\" # @param {type:\"string\"}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "GOaOsIjxp0oB"
@@ -385,10 +413,11 @@
},
"outputs": [],
"source": [
"! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI"
"! gsutil mb -l {REGION} -p {PROJECT_ID} {BUCKET_URI}"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ankcS-vtp7Wv"
@@ -405,10 +434,13 @@
},
"outputs": [],
"source": [
"import os\n",
"\n",
"from google.cloud import aiplatform"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "OMrAJ8RGqBQu"
@@ -431,6 +463,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "-ayTbNdi62_t"
@@ -442,6 +475,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "9c3QrDTZdaxk"
@@ -462,6 +496,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "vJrWKK0mY7H7"
@@ -507,6 +542,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "syw3GabNGgJz"
@@ -573,6 +609,7 @@
"\n",
"REQUIRED_PACKAGES = [\n",
" 'google-cloud-aiplatform[cloud_profiler]>=1.20.0',\n",
" 'protobuf==3.20.2',\n",
"]\n",
"\n",
"setup(\n",
@@ -587,6 +624,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "hyAwgsoQmaYI"
@@ -706,6 +744,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "ihYFahRAr6sj"
@@ -732,6 +771,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "k4e6OYmimqTR"
@@ -779,6 +819,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "51hKGTbU32Eg"
@@ -810,6 +851,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "JkEe2Nb_85UD"
@@ -823,6 +865,7 @@
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"id": "TpV-iwP9qw9c"
@@ -849,7 +892,7 @@
"job.delete()\n",
"tensorboard.delete()\n",
"\n",
"if delete_bucket and \"BUCKET_URI\" in globals():\n",
"if delete_bucket or os.getenv(\"IS_TESTING\"):\n",
" ! gsutil -m rm -r $BUCKET_URI"
]
}