Custom Metrics Sample

Requirements

  • Authenticated to gcloud (gcloud auth application-default login)
[ ]:
!pip install --upgrade -r requirements.txt > /dev/null
[ ]:
%env GOOGLE_CLOUD_PROJECT=your-gcp-project
[ ]:
import merlin
import warnings
import os
from merlin.model import ModelType, PyFuncModel
warnings.filterwarnings('ignore')

1. Initialize

1.1 Set Server

[ ]:
merlin.set_url("http://localhost:3000")

1.2 Set Active Project

project represent a project in real life. You may have multiple model within a project.

merlin.set_project(<project_name>) will set the active project into the name matched by argument. You can only set it to an existing project. If you would like to create a new project, please do so from the MLP console at http://localhost:3000/projects/create.

[ ]:
merlin.set_project("sample")

1.3 Set Active Model

model represents an abstract ML model. Conceptually, model in Merlin is similar to a class in programming language. To instantiate a model you’ll have to create a model_version.

Each model has a type, currently model type supported by Merlin are: sklearn, xgboost, tensorflow, pytorch, and user defined model (i.e. pyfunc model).

model_version represents a snapshot of particular model iteration. You’ll be able to attach information such as metrics and tag to a given model_version as well as deploy it as a model service.

merlin.set_model(<model_name>, <model_type>) will set the active model to the name given by parameter, if the model with given name is not found, a new model will be created.

[ ]:
merlin.set_model("pyfunc-metric", ModelType.PYFUNC)

2. Create Model

In this step we are going to create an echo model which count the number of incoming request as a metrics called my_counter and return the incoming request as response.

2.1 Define PyFunc Model Class

To create a PyFunc model you’ll have to extend merlin.PyFuncModel class and implement its initialize and infer method.

initialize will be called once during model initialization. The argument to initialize is a dictionary containing a key value pair of artifact name and its URL. The artifact’s keys are the same value as received by log_pyfunc_model.

infer method is the prediction method that is need to be implemented. It accept a dictionary type argument which represent incoming request body. infer should return a dictionary object which correspond to response body of prediction result.

In following example we are creating PyFunc model called EchoModel. In its initialize method we create a prometheus counter with my_counter as metrics name. The infer method itself is just increment the counter and simply return incoming request.

[ ]:
from prometheus_client import Counter

class EchoModel(PyFuncModel):
    def initialize(self, artifacts):
        self.counter = Counter("my_counter", 'My custom counter')

    def infer(self, request):
        self.counter.inc()
        return request

Let’s test it locally

[ ]:
m = EchoModel()
m.initialize({})
m.infer({"instances": [[1,2,3,4], [2,1,2,4]] })

3. Deploy Model

To deploy the model, we will have to create an iteration of the model (by create a model_version), upload the serialized model to Merlin, and then deploy.

3.1 Create Model Version and Upload

merlin.new_model_version() is a convenient method to create a model version and start its development process. It is equal to following codes:

v = model.new_model_version()
v.start()
v.log_pyfunc_model(model_instance=EchoModel(),
                conda_env="env.yaml")
v.finish()

To upload PyFunc model you have to provide following arguments: 1. model_instance is the instance of PyFunc model, the model has to extend merlin.PyFuncModel 2. conda_env is path to conda environment yaml file. The environment yaml file must contain all dependency required by the PyFunc model. 3. (Optional) artifacts is additional artifact that you want to include in the model 4. (Optional) code_path is a list of directory containing python code that will be loaded during model initialization, this is required when model_instance depend on local python package

[ ]:
with merlin.new_model_version() as v:
    merlin.log_pyfunc_model(model_instance=EchoModel(),
                conda_env="env.yaml")

3.2 Deploy Model

Each of a deployed model version will have its own generated url

[ ]:
endpoint = merlin.deploy(v)

3.3 Send Test Request

[ ]:
%%bash -s "$endpoint.url"
curl -v -X POST $1 -d '{
  "instances": [
    [2.8,  1.0,  6.8,  0.4],
    [3.1,  1.4,  4.5,  1.6]
  ]
}'

3.4 Delete Deployment

[ ]:
merlin.undeploy(v)