Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.

Commit 3542d22

Browse files
authored
Merge pull request #98 from panchul/alekp_kubeflow_install
Chapter on deploying models with Kubeflow pipelines
2 parents bb240f2 + 2eef782 commit 3542d22

File tree

6 files changed

+279
-0
lines changed

6 files changed

+279
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,9 @@ venv.bak/
104104
.mypy_cache/
105105
/.vs
106106
/staged-data-analytics
107+
108+
# VS Code
109+
.vscode
110+
111+
# vi
112+
*~

Research/kubeflow-on-azure-stack/Readme.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This module demonstrates how to create and use a Kubeflow cluster on Azure Stack
1717
- [TFjob](#TFjob) (distributed training)
1818
- [PyTorchJob](#PyTorchJob) (distributed training)
1919
- [Uninstalling Kubeflow](#uninstalling-kubeflow)
20+
- [Using Models](#using-models)
2021
- [Next Steps](#next-steps)
2122
- [Links](#links)
2223

@@ -444,6 +445,180 @@ Here is how you would connect your Tensorboard with the persistence we discuss n
444445
dnsPolicy: ClusterFirst
445446
restartPolicy: Always
446447

448+
## Using Models
449+
450+
After a model is created and trained, you have many options of how to use it. You can run inferencing directly
451+
in your script after loading the serialized parameters. Here is how it would look like in one of the
452+
demos we cover, if we de-serialize the `model` and get `data` in the correct format:
453+
454+
output = model(data)
455+
pred = output.max(1, keepdim=True)[1]
456+
print(f"data={data}, predicted={pred}")
457+
458+
it will print the input and output for your inferencing.
459+
460+
A better option would be to create a docker container that functions as an api point to get data and return the results.
461+
462+
You can run the container directly like so, for exmple, forwarding it to your machine's port 5050:
463+
464+
$ docker run -p 5050:8080 mycontaier_with_model:1.0
465+
466+
Now you can use `curl` or write a simple script to run the inferencing(this is from the MLFlow chapter's example):
467+
468+
import requests
469+
470+
predicted_qualities = requests.post('http://localhost:5050/invocations', data=test_x.to_json(orient='split'), headers={'content-type':'application/json; format=pandas-split'})
471+
parsed_predictions = list(map(float, predicted_qualities.text[1:-1].split(',')))
472+
(rmse, mae, r2) = eval_metrics(test_y, parsed_predictions)
473+
474+
print("Elasticnet model (alpha=%f, l1_ratio=%f):" % (alpha, l1_ratio))
475+
print(" RMSE: %s" % rmse)
476+
print(" MAE: %s" % mae)
477+
print(" R2: %s" % r2)
478+
479+
Here is an example of the output:
480+
481+
Elasticnet model (alpha=0.050000, l1_ratio=0.050000):
482+
RMSE: 82.16359959591213
483+
MAE: 69.52472687854122
484+
R2: -0.02072575078015859
485+
486+
A more scalable way would be to run to these instances in Kubernetes deployment, or a Kubeflow's step.
487+
488+
Here is a draft of a suitable pipeline that would be capable of sanitizing and preparing data, wrap
489+
it into a json if needed, and pass to the model in a container:
490+
491+
apiVersion: argoproj.io/v1alpha1
492+
kind: Workflow
493+
metadata:
494+
generateName: inferencing-demo-
495+
spec:
496+
entrypoint: inferencing-example
497+
templates:
498+
- name: inferencing-example
499+
steps:
500+
- - name: generate-input
501+
template: whalesay
502+
- - name: consume-input
503+
template: run-model
504+
arguments:
505+
artifacts:
506+
# bind message to the intput-art artifact
507+
# generated by the generate-input step
508+
- name: message
509+
from: "{{steps.generate-input.outputs.artifacts.input-art}}"
510+
511+
- name: whalesay
512+
container:
513+
image: docker/whalesay:latest
514+
command: [sh, -c]
515+
args: ["echo \"{\\\"x\\\":3.0}\" | tee /tmp/input_request.json"]
516+
outputs:
517+
artifacts:
518+
# generate hello-art artifact from /tmp/input_request.json
519+
# artifacts can be directories as well as files
520+
- name: input-art
521+
path: /tmp/input_request.json
522+
523+
- name: run-model
524+
inputs:
525+
artifacts:
526+
# unpack the message input artifact
527+
# and put it at /tmp/message
528+
- name: message
529+
path: /tmp/message
530+
container:
531+
image: alpine:latest
532+
command: [sh, -c]
533+
args: ["cat /tmp/message"]
534+
535+
Depending on the application, you may want to communicate with the pipeline via requests to the first
536+
step. Or you can compress it all and have your logic inside of the single container.
537+
538+
apiVersion: argoproj.io/v1alpha1
539+
kind: Workflow
540+
metadata:
541+
generateName: inferencing-demo-curl-
542+
spec:
543+
entrypoint: inferencing-example
544+
templates:
545+
- name: inferencing-example
546+
steps:
547+
- - name: run-inference-server
548+
template: run-model
549+
550+
- name: run-model
551+
container:
552+
image: nginx:alpine
553+
ports:
554+
- containerPort: 80
555+
556+
Now you can see the pod with this service(a place-holder for your model) running if you want:
557+
558+
![pics/pipeline_server.png](pics/pipeline_server.png)
559+
560+
It is, in the case above, `inferencing-demo-curl-kj6z5-2763558554`.
561+
562+
Another option is to deploy your model as Kubernetes deployment, here is an nginx server you could try:
563+
564+
apiVersion: apps/v1
565+
kind: Deployment
566+
metadata:
567+
name: my-nginx
568+
labels:
569+
app: my-nginx
570+
spec:
571+
replicas: 2
572+
selector:
573+
matchLabels:
574+
app: my-nginx
575+
template:
576+
metadata:
577+
labels:
578+
app: my-nginx
579+
spec:
580+
containers:
581+
- name: my-nginx
582+
image: nginx:alpine
583+
ports:
584+
- containerPort: 80
585+
resources:
586+
limits:
587+
memory: "128Mi" #128 MB
588+
cpu: "200m" #200 millicpu (.2 cpu or 20% of the cpu)
589+
590+
Now you can increment number of replicas and your service will be automatically scaled.
591+
592+
This is how you can forward the port for this deployment:
593+
594+
$ kubectl port-forward deployment/my-nginx 7000:80
595+
Forwarding from 127.0.0.1:7000 -> 80
596+
Forwarding from [::1]:7000 -> 80
597+
Handling connection for 7000
598+
599+
And access your server(model containers) using, for example, `curl`:
600+
601+
$ curl localhost:7000
602+
<!DOCTYPE html>
603+
<html>
604+
<head>
605+
<title>Welcome to nginx!</title>
606+
...
607+
</body>
608+
</html>
609+
610+
Here is an example of how you can connect to the model you trained:
611+
612+
$ curl --header "Content-Type: application/json" \
613+
--request POST \
614+
--data '{"X":123,"Y":568}' \
615+
http://localhost:5050/api/infere
616+
Elasticnet model (alpha=0.050000, l1_ratio=0.050000):
617+
618+
RMSE: 82.16359959591213
619+
MAE: 69.52472687854122
620+
R2: -0.02072575078015859
621+
447622
## Next Steps
448623

449624
Proceed to [TensorFlow on Kubeflow Tutorial](tensorflow-on-kubeflow/Readme.md#tensorflow-on-kubeflow-on-azure-stack)
52.3 KB
Loading
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: my-nginx
5+
labels:
6+
app: my-nginx
7+
spec:
8+
replicas: 2
9+
selector:
10+
matchLabels:
11+
app: my-nginx
12+
template:
13+
metadata:
14+
labels:
15+
app: my-nginx
16+
spec:
17+
containers:
18+
- name: my-nginx
19+
image: nginx:alpine
20+
ports:
21+
- containerPort: 80
22+
resources:
23+
limits:
24+
memory: "128Mi" #128 MB
25+
cpu: "200m" #200 millicpu (.2 cpu or 20% of the cpu)
26+
27+
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#
2+
# the pipeline to pass parameters to a model and
3+
# eventually expose the deployment port to the outside.
4+
#
5+
apiVersion: argoproj.io/v1alpha1
6+
kind: Workflow
7+
metadata:
8+
generateName: inferencing-demo-
9+
spec:
10+
entrypoint: inferencing-example
11+
templates:
12+
- name: inferencing-example
13+
steps:
14+
- - name: generate-input
15+
template: whalesay
16+
- - name: consume-input
17+
template: run-model
18+
arguments:
19+
artifacts:
20+
# bind message to the intput-art artifact
21+
# generated by the generate-input step
22+
- name: message
23+
from: "{{steps.generate-input.outputs.artifacts.input-art}}"
24+
25+
- name: whalesay
26+
container:
27+
#image: docker/whalesay:latest
28+
image: alpine:latest
29+
command: [sh, -c]
30+
args: ["echo -e \"{\\\"x\\\":3.0}\" | tee /tmp/message"]
31+
outputs:
32+
artifacts:
33+
# generate hello-art artifact from /tmp/message
34+
# artifacts can be directories as well as files
35+
- name: input-art
36+
path: /tmp/message
37+
38+
- name: run-model
39+
inputs:
40+
artifacts:
41+
# unpack the message input artifact
42+
# and put it at /tmp/message
43+
- name: message
44+
path: /tmp/message
45+
container:
46+
image: alpine:latest
47+
command: [sh, -c]
48+
args: ["cat /tmp/message"]
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
# the pipeline to create an inferencing endpoint
3+
#
4+
apiVersion: argoproj.io/v1alpha1
5+
kind: Workflow
6+
metadata:
7+
generateName: inferencing-demo-curl-
8+
spec:
9+
entrypoint: inferencing-example
10+
templates:
11+
- name: inferencing-example
12+
steps:
13+
- - name: run-inference-server
14+
template: run-model
15+
16+
- name: run-model
17+
container:
18+
image: nginx:alpine
19+
ports:
20+
- containerPort: 80
21+
#command: [sh, -c]
22+
#args: ["do stuff"]
23+

0 commit comments

Comments
 (0)