Skip to content

Commit

Permalink
Merge pull request #359 from cliveseldon/mlflow_example
Browse files Browse the repository at this point in the history
Mlflow Example
  • Loading branch information
ukclivecox authored Jan 6, 2019
2 parents bf74240 + d31c2d2 commit 3b37b4a
Show file tree
Hide file tree
Showing 8 changed files with 388 additions and 0 deletions.
7 changes: 7 additions & 0 deletions examples/models/mlflow_model/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


.PHONY: clean
clean:
rm -rf mlflow
rm -rf mlruns
rm -rf __pycache__
17 changes: 17 additions & 0 deletions examples/models/mlflow_model/MyMlflowModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from mlflow import pyfunc
import os
import pandas as pd

class MyMlflowModel(object):

def __init__(self):
self.pyfunc_model = pyfunc.load_pyfunc("mlruns/0/"+next(os.walk('mlruns/0'))[1][0]+"/artifacts/model")

def predict(self,X,features_names):
if not features_names is None and len(features_names)>0:
df = pd.DataFrame(data=X,columns=features_names)
else:
df = pd.DataFrame(data=X)
return self.pyfunc_model.predict(df)


80 changes: 80 additions & 0 deletions examples/models/mlflow_model/contract.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"features":[
{
"name":"alcohol",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,12]
},
{
"name":"chlorides",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"citric acid",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"density",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"fixed acidity",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"free sulphur dioxide",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"pH",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,7]
},
{
"name":"residual sugar",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"sulphates",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
},
{
"name":"total sulphur dioxide",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,100]
},
{
"name":"volatile acidity",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
}
],
"targets":[
{
"name":"class",
"dtype":"FLOAT",
"ftype":"continuous",
"range":[0,1]
}
]
}


46 changes: 46 additions & 0 deletions examples/models/mlflow_model/deployment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"apiVersion": "machinelearning.seldon.io/v1alpha2",
"kind": "SeldonDeployment",
"metadata": {
"labels": {
"app": "seldon"
},
"name": "mlflow-example"
},
"spec": {
"name": "mlflow-dep",
"oauth_key": "oauth-key",
"oauth_secret": "oauth-secret",
"predictors": [
{
"componentSpecs": [{
"spec": {
"containers": [
{
"image": "mlflow_model:0.1",
"imagePullPolicy": "IfNotPresent",
"name": "model",
"resources": {
"requests": {
"memory": "1Mi"
}
}
}
],
"terminationGracePeriodSeconds": 20
}
}],
"graph": {
"children": [],
"name": "model",
"endpoint": {
"type" : "REST"
},
"type": "MODEL"
},
"name": "mlflow-pred",
"replicas": 1
}
]
}
}
4 changes: 4 additions & 0 deletions examples/models/mlflow_model/environment_rest
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MODEL_NAME=MyMlflowModel
API_TYPE=REST
SERVICE_TYPE=MODEL
PERSISTENCE=0
228 changes: 228 additions & 0 deletions examples/models/mlflow_model/mlflow.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Run MLFlow Model in Seldon Core\n",
"\n",
"This notebook shows how you can easily train a model using [MLFlow](https://mlflow.org/) and serve requests within Seldon Core on Kubernetes.\n",
"\n",
"Dependencies\n",
"\n",
" * ```pip install seldon-core```\n",
" * ```pip install mlflow```\n",
" \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Train Example MlFlow Model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!git clone https://github.com/mlflow/mlflow"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!python mlflow/examples/sklearn_elasticnet_wine/train.py"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Test Inference Locally"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pygmentize MyMlflowModel.py"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!s2i build -E environment_rest . seldonio/seldon-core-s2i-python3:0.5-SNAPSHOT mlflow_model:0.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!docker run --name \"mlflow_model\" -d --rm -p 5000:5000 mlflow_model:0.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!curl -H \"Content-Type: application/x-www-form-urlencoded\" -g 0.0.0.0:5000/predict -d 'json={\"data\":{\"names\":[\"alcohol\", \"chlorides\", \"citric acid\", \"density\", \"fixed acidity\", \"free sulfur dioxide\", \"pH\", \"residual sugar\", \"sulphates\", \"total sulfur dioxide\", \"volatile acidity\"],\"ndarray\":[[12.8, 0.029, 0.48, 0.98, 6.2, 29, 3.33, 1.2, 0.39, 75, 0.66]]}}'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!curl -H \"Content-Type: application/x-www-form-urlencoded\" -g 0.0.0.0:5000/predict -d 'json={\"data\":{\"ndarray\":[[12.8, 0.029, 0.48, 0.98, 6.2, 29, 3.33, 1.2, 0.39, 75, 0.66]]}}'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!docker rm mlflow_model --force"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Test Inference on Minikube\n",
"\n",
"**Due to a [minikube/s2i issue](https://github.com/SeldonIO/seldon-core/issues/253) you will need [s2i >= 1.1.13](https://github.com/openshift/source-to-image/releases/tag/v1.1.13)**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!minikube start --memory 4096"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm init"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl rollout status deploy/tiller-deploy -n kube-system"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!helm install ../../../helm-charts/seldon-core-crd --name seldon-core-crd --set usage_metrics.enabled=true\n",
"!helm install ../../../helm-charts/seldon-core --name seldon-core "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!eval $(minikube docker-env) && s2i build -E environment_rest . seldonio/seldon-core-s2i-python3:0.5-SNAPSHOT mlflow_model:0.1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl create -f deployment.json"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl get seldondeployments mlflow-example -o jsonpath='{.status}' "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!seldon-core-api-tester contract.json \\\n",
" `minikube ip` `kubectl get svc -l app=seldon-apiserver-container-app -o jsonpath='{.items[0].spec.ports[0].nodePort}'` \\\n",
" --oauth-key oauth-key --oauth-secret oauth-secret -p"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!minikube delete"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
3 changes: 3 additions & 0 deletions examples/models/mlflow_model/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mlflow
sklearn
pandas
Loading

0 comments on commit 3b37b4a

Please sign in to comment.