mirror of
https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
synced 2026-09-26 14:42:04 +00:00
Vertex Prediction PyTorch Experimental: Add a sample for pre-built PyTorch deployments. (#898)
* samples: Add a new sample for pre-built Pytorch deployments. It's borrowed from the examples in community-content/pytorch_text_classification_using_vertex_sdk_and_gcloud. * samples: Removed all training related stuff in the notebooks. * samples: Fixed comments. * samples: Updated readme. * samples: Updated emails for Pytorch launch.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
* @vertex-ai-samples-contributors @GoogleCloudPlatform/cloudml-samples-owners
|
||||
/tf_agents_bandits_movie_recommendation_with_kfp_and_vertex_sdk @yinghsienwu
|
||||
/pytorch_pre_built_images_deployment @googleapis/vertex-prediction-team
|
||||
/pytorch_text_classification_using_vertex_sdk_and_gcloud @RajeshThallam
|
||||
/pytorch_text_classification_using_vertex_sdk_and_gcloud @RajeshThallam @ultrons
|
||||
/sklearn_text_classification_from_script_using_vertex_sdk @maxhardt
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# PyTorch Deployment on Google Cloud: Text Classification
|
||||
|
||||
**This is an Experimental release**, covered by the Pre-GA Offerings Terms of your Google Cloud Platform [Terms of Service](https://cloud.google.com/terms).
|
||||
|
||||
Experiments are focused on validating a prototype and are not guaranteed to be released. They are not intended for production use or covered by any SLA, support obligation, or deprecation policy and might be subject to backward-incompatible changes.
|
||||
|
||||
**Kindly drop us a note before you run any scale tests.**
|
||||
|
||||
**Do not hesitate to contact vertexai-prediction-preview-feedback@google.com if you have any questions or run into any issues.**
|
||||
|
||||
The projects need to be added to the allowlist in order to deploy PyTorch models using Vertex AI Prediction pre-built PyTorch images. If you are interested in the feature, please send an email to vertexai-prediction-preview-feedback@google.com to provide your project numbers and project ids.
|
||||
|
||||
## Overview
|
||||
|
||||
In the PyTorch on Google Cloud series of blog posts, we aim to share how to deploy PyTorch models at scale on [Vertex AI](https://cloud.google.com/vertex-ai).
|
||||
|
||||
This tutorial on text classification shows how to deploy a PyTorch based text classification model on [Vertex AI](https://cloud.google.com/vertex-ai/docs/start/client-libraries#python) using Vertex SDK and [`gcloud ai`](https://cloud.google.com/sdk/gcloud/reference/beta/ai).
|
||||
|
||||
## Notebooks
|
||||
|
||||
| <h4>Notebook</h4> | <h4>Description</h4> |
|
||||
| :-------- | :------- |
|
||||
| [pytorch-text-classification-vertex-ai-deploy.ipynb](./pytorch-text-classification-vertex-ai-deploy.ipynb) | Notebook to show deploying a PyTorch model on Vertex AI |
|
||||
|
||||
## Folders
|
||||
|
||||
|
||||
| <h4>Folder Name</h4> | <h4>Description</h4> |
|
||||
| :-------- | :------- |
|
||||
| [`predictor`](./predictor) | Folder with custom prediction handler to deploy a PyTorch model to Vertex Prediction. In the [notebook](./pytorch-text-classification-vertex-ai-deploy.ipynb), this folder is used for deploying a PyTorch model on Vertex AI using Vertex Prediction pre-built PyTorch images |
|
||||
@@ -0,0 +1,91 @@
|
||||
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
|
||||
import torch
|
||||
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
||||
from ts.torch_handler.base_handler import BaseHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TransformersClassifierHandler(BaseHandler):
|
||||
"""
|
||||
The handler takes an input string and returns the classification text
|
||||
based on the serialized transformers checkpoint.
|
||||
"""
|
||||
def __init__(self):
|
||||
super(TransformersClassifierHandler, self).__init__()
|
||||
self.initialized = False
|
||||
|
||||
def initialize(self, ctx):
|
||||
""" Loads the model.pt file and initialized the model object.
|
||||
Instantiates Tokenizer for preprocessor to use
|
||||
Loads labels to name mapping file for post-processing inference response
|
||||
"""
|
||||
self.manifest = ctx.manifest
|
||||
|
||||
properties = ctx.system_properties
|
||||
model_dir = properties.get("model_dir")
|
||||
self.device = torch.device("cuda:" + str(properties.get("gpu_id")) if torch.cuda.is_available() else "cpu")
|
||||
|
||||
# Read model serialize/pt file
|
||||
serialized_file = self.manifest["model"]["serializedFile"]
|
||||
model_pt_path = os.path.join(model_dir, serialized_file)
|
||||
if not os.path.isfile(model_pt_path):
|
||||
raise RuntimeError("Missing the model.pt or pytorch_model.bin file")
|
||||
|
||||
# Load model
|
||||
self.model = AutoModelForSequenceClassification.from_pretrained(model_dir)
|
||||
self.model.to(self.device)
|
||||
self.model.eval()
|
||||
logger.debug('Transformer model from path {0} loaded successfully'.format(model_dir))
|
||||
|
||||
# Ensure to use the same tokenizer used during training
|
||||
self.tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')
|
||||
|
||||
# Read the mapping file, index to object name
|
||||
mapping_file_path = os.path.join(model_dir, "index_to_name.json")
|
||||
|
||||
if os.path.isfile(mapping_file_path):
|
||||
with open(mapping_file_path) as f:
|
||||
self.mapping = json.load(f)
|
||||
else:
|
||||
logger.warning('Missing the index_to_name.json file. Inference output will default.')
|
||||
self.mapping = {"0": "Negative", "1": "Positive"}
|
||||
|
||||
self.initialized = True
|
||||
|
||||
def preprocess(self, data):
|
||||
""" Preprocessing input request by tokenizing
|
||||
Extend with your own preprocessing steps as needed
|
||||
"""
|
||||
text = data[0].get("data")
|
||||
if text is None:
|
||||
text = data[0].get("body")
|
||||
sentences = text.decode('utf-8')
|
||||
logger.info("Received text: '%s'", sentences)
|
||||
|
||||
# Tokenize the texts
|
||||
tokenizer_args = ((sentences,))
|
||||
inputs = self.tokenizer(*tokenizer_args,
|
||||
padding='max_length',
|
||||
max_length=128,
|
||||
truncation=True,
|
||||
return_tensors = "pt")
|
||||
return inputs
|
||||
|
||||
def inference(self, inputs):
|
||||
""" Predict the class of a text using a trained transformer model.
|
||||
"""
|
||||
prediction = self.model(inputs['input_ids'].to(self.device))[0].argmax().item()
|
||||
|
||||
if self.mapping:
|
||||
prediction = self.mapping[str(prediction)]
|
||||
|
||||
logger.info("Model predicted: '%s'", prediction)
|
||||
return [prediction]
|
||||
|
||||
def postprocess(self, inference_output):
|
||||
return inference_output
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
{
|
||||
"0": "Negative",
|
||||
"1": "Positive"
|
||||
}
|
||||
+1625
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user