It is possible to deploy Python functions with Cloud Pak for Data (CP4D). The purpose is mainly before and after model execution, and error handling of try & except can be incorporated, and above all, it is possible to call (use properly) multiple models.
Excerpt from CP4D v2.5 product manual https://www.ibm.com/support/knowledgecenter/ja/SSQNUZ_2.5.0/wsj/analyze-data/ml-deploy-functions_local.html
Python functions can be deployed to Watson Machine Learning in the same way as deploying a model. Your tools and applications can use the Watson Machine Learning Python client or REST API to send data to deployed functions in the same way that they send data to a deployed model. You can deploy functions to hide details (such as credentials), preprocess data before passing it to the model, perform error handling, and incorporate calls into multiple models. All of these features are built into the deployed function, not the application.
Deploying functions in WML has preceding article, but it is the method in Watson Studio of IBM Cloud service, and the method is slightly different in CP4D. I'm addicted to it, so I'll leave an example of how it worked. This is the result of creating a simple function, deploying it as an Online type, and checking the operation.
Models and functions created in Notebook are stored in the deployment space, and each is deployed as an Online type. By setting the function to call the model deployment, the configuration is as follows: call the function deployment → call the model deployment. At the end of the Notebook, score the function deployment to see it in action.
Log in to CP4D, open your analytics project and launch a new Notebook. The confirmed CP4D version is v3.0 LA.
Create and deploy the model first. You will use this deployment ID later to call it in a function.
Create a model of a random forest using Iris data.
#Load Iris sample data
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['iris_type'] = iris.target_names[iris.target]
#Create a model in a random forest
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
X = df.drop('iris_type', axis=1)
y = df['iris_type']
X_train, X_test, y_train, y_test = train_test_split(X,y,random_state=0)
clf = RandomForestClassifier(max_depth=2, random_state=0, n_estimators=10)
model = clf.fit(X_train, y_train)
#Check the accuracy of the model
from sklearn.metrics import confusion_matrix, accuracy_score
y_test_predicted = model.predict(X_test)
print("confusion_matrix:")
print(confusion_matrix(y_test,y_test_predicted))
print("accuracy:", accuracy_score(y_test,y_test_predicted))
The above `` `model``` is a trained model.
Save the model in the deployment space and create an Online deployment. The operation uses the WML client. (Reference article)
python
#WML client initialization and authentication
from watson_machine_learning_client import WatsonMachineLearningAPIClient
import os
token = os.environ['USER_ACCESS_TOKEN']
url = "https://cp4d.host.name.com"
wml_credentials = {
"token" : token,
"instance_id" : "openshift",
"url": url,
"version": "3.0.0"
}
client = WatsonMachineLearningAPIClient(wml_credentials)
#Display deployment space ID list
# client.repository.list_spaces()
#Switch to deployment space(ID is the above list_spaces()Find out in)
space_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
client.set.default_space(space_id)
#Describe model meta information
model_name = "sample_iris_model"
meta_props={
client.repository.ModelMetaNames.NAME: model_name,
client.repository.ModelMetaNames.RUNTIME_UID: "scikit-learn_0.22-py3.6",
client.repository.ModelMetaNames.TYPE: "scikit-learn_0.22",
client.repository.ModelMetaNames.INPUT_DATA_SCHEMA:{
"id":"iris model",
"fields":[
{'name': 'sepal length (cm)', 'type': 'double'},
{'name': 'sepal width (cm)', 'type': 'double'},
{'name': 'petal length (cm)', 'type': 'double'},
{'name': 'petal width (cm)', 'type': 'double'}
]
},
client.repository.ModelMetaNames.OUTPUT_DATA_SCHEMA: {
"id":"iris model",
"fields": [
{'name': 'iris_type', 'type': 'string','metadata': {'modeling_role': 'prediction'}}
]
}
}
#Save model
model_artifact = client.repository.store_model(model, meta_props=meta_props, training_data=X, training_target=y)
model_id = model_artifact['metadata']['guid']
#Create a deployment with Online type
dep_name = "sample_iris_online"
meta_props = {
client.deployments.ConfigurationMetaNames.NAME: dep_name,
client.deployments.ConfigurationMetaNames.ONLINE: {}
}
deployment_details = client.deployments.create(model_id, meta_props=meta_props)
dep_id = deployment_details['metadata']['guid']
Make sure that the model (deployment) you created works properly. You can check the operation using WML client.
#Generate sample data and convert to JSON
scoring_x = pd.DataFrame(
data = [[5.1,3.5,1.4,0.2]],
columns=['sepal length (cm)','sepal width (cm)','petal length (cm)','petal width (cm)']
)
values = scoring_x.values.tolist()
fields = scoring_x.columns.values.tolist()
scoring_payload = {client.deployments.ScoringMetaNames.INPUT_DATA: [{'fields': fields, 'values': values}]}
#Scoring execution
prediction = client.deployments.score(dep_id, scoring_payload)
prediction
If the following result is returned, the operation check is complete.
output
{'predictions': [{'fields': ['prediction', 'probability'],
'values': [[0, [0.8131726303900102, 0.18682736960998966]]]}]}
There are various ways to create a function.
Here is the function I actually made. Please refer to Reference article for how to perform deployment using WML client.
Creating a function
# variables for function
func_variables = {
"url" : url,
"space_id" : space_id,
"dep_id" : dep_id,
"token" : token
}
# Function for scoring model only
def iris_scoring(func_vars=func_variables):
from watson_machine_learning_client import WatsonMachineLearningAPIClient
#Note: wml_credentials are defined here
wml_credentials = {
"token" : func_vars['token'],
"instance_id": "openshift",
"url": func_vars['url'],
"version" : "3.0.0"
}
client = WatsonMachineLearningAPIClient(wml_credentials)
def score(scoring_payload):
try:
client.set.default_space(func_vars['space_id'])
prediction = client.deployments.score(func_vars['dep_id'], scoring_payload)
return prediction
except Exception as e:
return {'error': repr(e)}
return score
Variables used inside the function are defined outside the function and passed to the function. url is the URL of the CP4D (up to the FQDN, without the last slash), space_id is the ID of the deployment space where you deployed the model you just created, and dep_id is the deployment ID of that model. The content of the function is simply to call the Online deployment.
As I wrote in the comment, the point is to initialize the *** WML client with an outer function ***, and to define *** wml_credentials used there *** in the outer function. If you try to receive wml_credentials defined outside the function as an argument, it will not work. This seems to be different from Watson Studio on IBM Cloud, and I was very addicted to it.
Check the operation of the created function. Continue to run the following in your Notebook to see if the function calls the deployment successfully. Input data scoring_payload uses the sample data created earlier.
Function check
#Execute function(Scoring to inner function_Pass payload)
iris_scoring()(scoring_payload)
It is OK if the following result is returned.
output
{'predictions': [{'fields': ['prediction', 'probability'],
'values': [['setosa', [0.9939393939393939, 0.006060606060606061, 0.0]]]}]}
Save the function in the deployment space.
#Create meta information
meta_props = {
client.repository.FunctionMetaNames.NAME: 'iris_scoring_func',
client.repository.FunctionMetaNames.RUNTIME_UID: "ai-function_0.1-py3.6",
client.repository.FunctionMetaNames.SPACE_UID: space_id
}
#Save function
function_details = client.repository.store_function(meta_props=meta_props, function=iris_scoring)
function_id = function_details['metadata']['guid']
In the deployment space, you can see that it is registered in the section called "Functions" under the asset.
Deploy the function saved in the deployment space with the Online type.
#Create meta information
meta_props = {
client.deployments.ConfigurationMetaNames.NAME: "iris_scoring_online",
client.deployments.ConfigurationMetaNames.ONLINE: {}
}
#Create a deployment
function_deployment_details = client.deployments.create(function_id, meta_props=meta_props)
func_dep_id = function_deployment_details['metadata']['guid']
You have now deployed the function. Ready to run.
I will check the operation at once. Make a scoring call to your deployment using the WML client.
prediction = client.deployments.score(func_dep_id, scoring_payload)
prediction
If you get the same result as before, you are successful.
output
{'predictions': [{'fields': ['prediction', 'probability'],
'values': [['setosa', [0.9939393939393939, 0.006060606060606061, 0.0]]]}]}
Now you have a simple way to make a model call using a function. I will post more applied multi-model calling patterns later.
Recommended Posts