Model Implementation for Modelscape Deploy
This example shows you how to use and implement the Modelscape™ Deploy™.
Modelscape Deploy supports a generic interface for specifying model inputs, model outputs, and a single method to execute models. This example explains the interface and shows you how a model developer must implement it.
This example uses a toy model that takes inputs x
and y
and calculates the weighted sum z = A*x + B*y
, where A
and B
are scalar weights. If x
and y
are vectors, the evaluation of the model is a batch evaluation for each pair of elements in x
and y
. The scalars A
and B
are configurable, but constant across a batch of evaluations – and are therefore regarded as parameters.
Realistic examples of inputs varying within a batch are the contract details for a book of derivative transactions, and the data corresponding to a group of credit card applicants. Examples of parameters corresponding to these inputs are the number of Monte Carlo paths used for pricing the derivatives, and certain macro-economic data used for credit-scoring the loan applicants. Note that the batch parameters are fixed for all inputs within a batch.
Work with Modelscape Deploy
Models to be executed in Modelscape Deploy must be implemented as subclasses of mrm.execution.Model
.
classdef WeightedSum < mrm.execution.Model
Both the inputs and the outputs of the model execution must be tables. Each model class defines how to interroage the input table and populate the output table.
Methods for Inputs and Outputs
Each model must implement three methods for specifying the inputs and the outputs of the model.
getInputs
: returns the definition of the variables required for each evaluation in a batch - for example, the names and types ofx
andy
above.getParameters
: returns the definition of the variables that are fixed within a batch of evaluations - that is the names and types ofA
andB
above.getOutputs
: returns the definition of the output variables - variablez
above.
The output, in each case, should be a struct with the following fields:
name
: a cell array of strings containing the names of the input/output variables.type: a cell array of structs defining the type of each input/output variable - each struct should have a field called
name
with any of the values listed inmwtype
.sizes
: a cell array of two-element arrays[a b]
defining the size of each input/output variable - useNaN
to indicate unrestricted size, e.g.[1
NaN
]
for a single column of an arbitrary height.
Define the toy model as follows.
function parameters = getInputs(~) doubleDatatype = struct( ... "name", "double"); parameters = struct( ... "name", {"X", "Y"}, ... "dataType", {doubleDatatype, doubleDatatype}); end function parameters = getParameters(~) doubleDatatype = struct( ... "name", "double"); parameters = struct( ... "name", {"A", "B"}, ... "dataType", {doubleDatatype, doubleDatatype}); end function parameters = getOutputs(~) doubleDatatype = struct( ... "name", "double"); parameters = struct( ... "name", {"Z"}, ... "dataType", {doubleDatatype}); end
Evaluation Method
Define the evaluate method as follows.
[outputs, diagnostics, batchDiagnostics] = evaluate(this, inputs, parameters)
Here inputs
should be a table, with a row for each evaluation within the batch, and parameters
should be struct, that contains the variables that apply to all evaluations within the batch.
The outputs
variable must be a table and contain a row for each row of the inputs
table. The diagnostics
output must be an array of structs, one for each row of the input table. The batchDiagnostic
output is a single diagnostic for the whole batch and must be a scalar struct.
The toy model also has the following definition.
function [outputs, diagnostics, batchDiagnostics] = evaluate(~, inputs, parameters) outputs = table( ... parameters.A * inputs.X + parameters.B * inputs.Y, ... 'VariableNames', {'Z'}, ... 'RowNames', inputs.Properties.RowNames); rawDiagnostics = [inputs.Properties.RowNames, repmat({struct()}, numel(inputs.Properties.RowNames), 1)]'; diagnostics = struct(rawDiagnostics{:}); batchDiagnostics = struct(); end
In this case the diagnostics
structs are empty. In the more complicated examples listed above, they could carry, for instance, information about the Monte Carlo noise present in the valuation.
Create an image for Deployment
To deploy a model that implements the mrm.execution.Model
interface, firstly, package the executable model code into a Docker® image suitable for deployment using MATLAB® Compiler SDK. Use the helper function mrm.execution.packageModel
to do this.
modelInstance = WeightedSum(); outputFolder = tempname(); imageName = mrm.execution.compiler.packageModel(modelInstance, ... OutputFolder=outputFolder, ... Name="weighted-sum", ... Tag="v1")
Runtime Image Already Exists Sending build context to Docker daemon 278kB Step 1/6 : FROM matlabruntime/r2023a/prerelease/update0/308000000000000000 ---> 9578d4e15248 Step 2/6 : COPY ./applicationFilesForMATLABCompiler /usr/bin/mlrtapp ---> ff0709fcec70 Step 3/6 : RUN chmod -R a+rX /usr/bin/mlrtapp/* ---> Running in c83375557f83 Removing intermediate container c83375557f83 ---> da1d6f8978b3 Step 4/6 : RUN useradd -ms /bin/bash appuser ---> Running in aab934c26070 Removing intermediate container aab934c26070 ---> 5e5490e6e58e Step 5/6 : USER appuser ---> Running in fd6d76d6d108 Removing intermediate container fd6d76d6d108 ---> 54efdb411a1b Step 6/6 : ENTRYPOINT ["/opt/matlabruntime/R2023a/bin/glnxa64/muserve", "-a", "/usr/bin/mlrtapp/weightedsum.ctf"] ---> Running in 4c6771bc9751 Removing intermediate container 4c6771bc9751 ---> 0da443f8e974 Successfully built 0da443f8e974 Successfully tagged weighted-sum:v1 DOCKER CONTEXT LOCATION: /tmp/tp984f0556_95f6_46b1_a428_473bcc9e54dc/docker FOR HELP GETTING STARTED WITH MICROSERVICE IMAGES, PLEASE READ: /tmp/tp984f0556_95f6_46b1_a428_473bcc9e54dc/docker/GettingStarted.txt Sending build context to Docker daemon 4.608kB Step 1/7 : FROM weighted-sum:v1 ---> 0da443f8e974 Step 2/7 : COPY ./routes.json /usr/bin/mlrtapp/routes.json ---> e97e7b05ec7e Step 3/7 : USER root ---> Running in 01c65af653f1 Removing intermediate container 01c65af653f1 ---> 276549f8c441 Step 4/7 : RUN useradd -u 2000 -ms /bin/bash modeluser ---> Running in e5d62f47d4fa Removing intermediate container e5d62f47d4fa ---> 206c7ad88b83 Step 5/7 : USER 2000 ---> Running in 98307802e3cb Removing intermediate container 98307802e3cb ---> 0ac44031eb4a Step 6/7 : EXPOSE 8080 ---> Running in 75b018a3bd8d Removing intermediate container 75b018a3bd8d ---> 314e6255d91e Step 7/7 : CMD ["--http", "8080","--routes-file", "/usr/bin/mlrtapp/routes.json"] ---> Running in 1549e1f467cc Removing intermediate container 1549e1f467cc ---> f703f5e9bd1b Successfully built f703f5e9bd1b Successfully tagged weighted-sum:v1
imageName = "weighted-sum:v1"
Deploy to Modelscape Deploy
The image must be pushed to a Docker registry visible to the Modelscape API. For the next steps, choose the model version for which you want to create a model version build. Create the build, a deployment environment, and deploy your build.