mirror of
https://github.com/GoogleCloudPlatform/vertex-ai-samples.git
synced 2026-09-26 14:42:04 +00:00
46 KiB
46 KiB
In [ ]:
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.In [ ]:
%%writefile requirements.txt
joblib~=1.0
numpy~=1.20
scikit-learn~=0.24
google-cloud-storage>=1.26.0,<2.0.0devIn [ ]:
# Required in Docker serving container
%pip install -U --user -r requirements.txt
# For local FastAPI development and running
%pip install -U --user "uvicorn[standard]>=0.12.0,<0.14.0" fastapi~=0.63
# Vertex SDK for Python
%pip install -U --user google-cloud-aiplatformIn [ ]:
# Automatically restart kernel after installs
import os
if not os.getenv("IS_TESTING"):
# Automatically restart kernel after installs
import IPython
app = IPython.Application.instance()
app.kernel.do_shutdown(True)In [ ]:
# Get your Google Cloud project ID from gcloud
shell_output = !gcloud config list --format 'value(core.project)' 2>/dev/null
try:
PROJECT_ID = shell_output[0]
except IndexError:
PROJECT_ID = None
print("Project ID:", PROJECT_ID)In [ ]:
if PROJECT_ID == "" or PROJECT_ID is None:
PROJECT_ID = "[your-project-id]" # @param {type:"string"}In [ ]:
MODEL_ARTIFACT_DIR = "custom-container-explainablility-model" # @param {type:"string"}
REPOSITORY = "custom-container-explainablility" # @param {type:"string"}
IMAGE = "sklearn-fastapi-server" # @param {type:"string"}
MODEL_DISPLAY_NAME = "sklearn-explainable-custom-container" # @param {type:"string"}In [ ]:
BUCKET_URI = "gs://[your-bucket-name]" # @param {type:"string"}
REGION = "[your-region]" # @param {type:"string"}In [ ]:
if BUCKET_URI == "" or BUCKET_URI is None or BUCKET_URI == "gs://[your-bucket-name]":
BUCKET_URI = "gs://" + PROJECT_ID + "aip-" + TIMESTAMP
if REGION == "[your-region]":
REGION = "us-central1"In [ ]:
! gcloud storage buckets create --location=$REGION --project=$PROJECT_ID $BUCKET_URIIn [ ]:
! gcloud storage ls --all-versions --long $BUCKET_URIIn [ ]:
%mkdir appIn [ ]:
%cd app/
import joblib
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
class IrisClassifier:
def __init__(self):
self.X, self.y = load_iris(return_X_y=True)
self.clf = self.train_model()
self.iris_type = {0: "setosa", 1: "versicolor", 2: "virginica"}
def train_model(self) -> LogisticRegression:
return LogisticRegression(
solver="lbfgs", max_iter=1000, multi_class="multinomial"
).fit(self.X, self.y)
def predict(self, features: dict):
X = [
features["sepal_length"],
features["sepal_width"],
features["petal_length"],
features["petal_width"],
]
prediction = self.clf.predict_proba([X])
print(prediction)
return {
"class": self.iris_type[np.argmax(prediction)],
"probability": round(max(prediction[0]), 2),
}
model_local = IrisClassifier()
joblib.dump(model_local, "model.joblib")
%cd ..In [ ]:
model_local.predict(
features={
"sepal_length": 4.8,
"sepal_width": 3,
"petal_length": 1.4,
"petal_width": 0.3,
}
)In [ ]:
instances = [
{"sepal_length": 4.8, "sepal_width": 3, "petal_length": 1.4, "petal_width": 0.3},
{"sepal_length": 6.2, "sepal_width": 3.4, "petal_length": 5.4, "petal_width": 2.3},
]In [ ]:
%%writefile app/classifier.py
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
import numpy as np
from fastapi import FastAPI, Request
class IrisClassifier:
def __init__(self):
self.X, self.y = load_iris(return_X_y=True)
self.clf = self.train_model()
self.iris_type = {
0: 'setosa',
1: 'versicolor',
2: 'virginica'
}
def train_model(self) -> LogisticRegression:
return LogisticRegression(solver='lbfgs',
max_iter=1000,
multi_class='multinomial').fit(self.X, self.y)
def predict(self, features: dict):
X = [features['sepal_length'], features['sepal_width'], features['petal_length'], features['petal_width']]
prediction = self.clf.predict_proba([X])
return {'class': self.iris_type[np.argmax(prediction)],
'probability': round(max(prediction[0]), 2)}In [ ]:
%%writefile classifier.py
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
import numpy as np
class IrisClassifier:
def __init__(self):
self.X, self.y = load_iris(return_X_y=True)
self.clf = self.train_model()
self.iris_type = {
0: 'setosa',
1: 'versicolor',
2: 'virginica'
}
def train_model(self) -> LogisticRegression:
return LogisticRegression(solver='lbfgs',
max_iter=1000,
multi_class='multinomial').fit(self.X, self.y)
def predict(self, features: dict):
X = [features['sepal_length'], features['sepal_width'], features['petal_length'], features['petal_width']]
prediction = self.clf.predict_proba([X])
return {'class': self.iris_type[np.argmax(prediction)],
'probability': round(max(prediction[0]), 2)}In [ ]:
%cd app
with open("__init__.py", "wb") as model_f:
pass
%cd ..
with open("__init__.py", "wb") as model_f:
passIn [ ]:
!gcloud storage cp app/model.joblib {BUCKET_URI}/{MODEL_ARTIFACT_DIR}/In [ ]:
%%writefile app/main.py
from fastapi import FastAPI, Request
#from starlette.responses import JSONResponse
import joblib
import json
import numpy as np
import pickle
import os
from google.cloud import storage
from classifier import IrisClassifier
app = FastAPI()
'''
gcs_client = storage.Client()
with open("model.joblib", 'wb') as model_f:
gcs_client.download_blob_to_file(
f"{os.environ['AIP_STORAGE_URI']}/model.joblib", model_f
)
#_model = joblib.load("model.joblib")
'''
@app.get(os.environ['AIP_HEALTH_ROUTE'], status_code=200)
def health():
return {}
@app.post(os.environ['AIP_PREDICT_ROUTE'])
async def predict(request: Request):
body = await request.json()
print (body)
model = IrisClassifier()
instances = body["instances"]
output = []
for i in instances:
output.append(model.predict(i))
#return 'class' and 'probability'
return {"predictions": output}In [ ]:
%%writefile app/prestart.sh
#!/bin/bash
export PORT=$AIP_HTTP_PORTIn [ ]:
%%writefile instances.json
{
"instances": [{
"sepal_length": 4.8,
"sepal_width": 3,
"petal_length": 1.4,
"petal_width": 0.3
},{
"sepal_length": 6.2,
"sepal_width": 3.4,
"petal_length": 5.4,
"petal_width": 2.3
}]
}In [ ]:
import os
import sys
# If you are running this notebook in Colab, run this cell and follow the
# instructions to authenticate your GCP account. This provides access to your
# Cloud Storage bucket and lets you submit training jobs and prediction
# requests.
# The Google Cloud Notebook product has specific requirements
IS_GOOGLE_CLOUD_NOTEBOOK = os.path.exists("/opt/deeplearning/metadata/env_version")
# If on Google Cloud Notebooks, then don't execute this code
if not IS_GOOGLE_CLOUD_NOTEBOOK:
if "google.colab" in sys.modules:
from google.colab import auth as google_auth
google_auth.authenticate_user()
# If you are running this notebook locally, replace the string below with the
# path to your service account key and run this cell to authenticate your GCP
# account.
elif not os.getenv("IS_TESTING"):
%env GOOGLE_APPLICATION_CREDENTIALS ''In [ ]:
# NOTE: Copy in credentials to run locally, this step can be skipped for deployment
import shutil
GOOGLE_APPLICATION_CREDENTIALS = "[PATH-TO-YOUR-CREDENTIALS.json]"
shutil.copyfile(GOOGLE_APPLICATION_CREDENTIALS, "app/credentials.json")In [ ]:
%%writefile Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7
COPY ./app /app
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txtIn [ ]:
!docker build \
--tag={REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE} \
.In [ ]:
!docker stop local-iris
!docker rm local-iris
container_id = !docker run -d -p 80:8080 \
--name=local-iris \
-e AIP_HTTP_PORT=8080 \
-e AIP_HEALTH_ROUTE=/health \
-e AIP_PREDICT_ROUTE=/predict \
-e AIP_STORAGE_URI={BUCKET_URI}/{MODEL_ARTIFACT_DIR} \
-e GOOGLE_APPLICATION_CREDENTIALS=credentials.json \
{REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}In [ ]:
!curl localhost/healthIn [ ]:
!docker logs {container_id[0]}In [ ]:
!curl -X POST \
-d @instances.json \
-H "Content-Type: application/json; charset=utf-8" \
localhost/predictIn [ ]:
!docker stop local-irisIn [ ]:
!gcloud beta artifacts repositories create {REPOSITORY} \
--repository-format=docker \
--location=$REGIONIn [ ]:
!gcloud auth configure-docker {REGION}-docker.pkg.dev --quietIn [ ]:
!docker push {REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}In [ ]:
from google.cloud import aiplatform
aiplatform.init(project=PROJECT_ID, location=REGION)In [ ]:
XAI = "shapley" # [ shapley, ig, xrai ]
if XAI == "shapley":
PARAMETERS = {"sampled_shapley_attribution": {"path_count": 10}}
elif XAI == "ig":
PARAMETERS = {"integrated_gradients_attribution": {"step_count": 50}}
elif XAI == "xrai":
PARAMETERS = {"xrai_attribution": {"step_count": 50}}
parameters = aiplatform.explain.ExplanationParameters(PARAMETERS)In [ ]:
EXPLANATION_METADATA = aiplatform.explain.ExplanationMetadata(
inputs={
"sepal_length": {},
"sepal_width": {},
"petal_length": {},
"petal_width": {},
},
outputs={"probability": {}},
)In [ ]:
model = aiplatform.Model.upload(
display_name=MODEL_DISPLAY_NAME,
artifact_uri=f"{BUCKET_URI}/{MODEL_ARTIFACT_DIR}",
serving_container_image_uri=f"{REGION}-docker.pkg.dev/{PROJECT_ID}/{REPOSITORY}/{IMAGE}",
explanation_parameters=parameters,
explanation_metadata=EXPLANATION_METADATA,
)In [ ]:
endpoint = model.deploy(machine_type="n1-standard-4")In [ ]:
endpoint.predict(instances=instances)In [ ]:
endpoint.explain(instances=instances)In [ ]:
ENDPOINT_ID = endpoint.nameIn [ ]:
! curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d @instances.json \
https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:predictIn [ ]:
! curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d @instances.json \
https://{REGION}-aiplatform.googleapis.com/v1/projects/{PROJECT_ID}/locations/{REGION}/endpoints/{ENDPOINT_ID}:explainIn [ ]:
!gcloud beta ai endpoints predict $ENDPOINT_ID \
--region=$REGION \
--json-request=instances.jsonWarning:
Output truncated. This notebook contains too many cells to display efficiently.