Skip to content

Commit 457170d

Browse files
ospillingerdeliahu
authored andcommitted
Update docs (#620)
(cherry picked from commit ae38855)
1 parent 286b304 commit 457170d

File tree

8 files changed

+210
-41
lines changed

8 files changed

+210
-41
lines changed

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Deploy machine learning models in production
22

3-
Cortex is an open source platform for deploying machine learning models—trained with nearly any framework—as production web services.
3+
Cortex is an open source platform for deploying machine learning models as production web services.
44

55
<br>
66

@@ -11,29 +11,34 @@ Cortex is an open source platform for deploying machine learning models—traine
1111

1212
## Key features
1313

14-
* **Autoscaling:** Cortex automatically scales APIs to handle production workloads.
1514
* **Multi framework:** Cortex supports TensorFlow, PyTorch, scikit-learn, XGBoost, and more.
15+
* **Autoscaling:** Cortex automatically scales APIs to handle production workloads.
1616
* **CPU / GPU support:** Cortex can run inference on CPU or GPU infrastructure.
1717
* **Spot instances:** Cortex supports EC2 spot instances.
1818
* **Rolling updates:** Cortex updates deployed APIs without any downtime.
1919
* **Log streaming:** Cortex streams logs from deployed models to your CLI.
2020
* **Prediction monitoring:** Cortex monitors network metrics and tracks predictions.
21-
* **Minimal configuration:** Deployments are defined in a single `cortex.yaml` file.
21+
* **Minimal configuration:** deployments are defined in a single `cortex.yaml` file.
2222

2323
<br>
2424

25-
## Spinning up a Cortex cluster
25+
## Spinning up a cluster
2626

27-
Cortex is designed to be self-hosted on any AWS account. You can spin up a Cortex cluster with a single command:
27+
Cortex is designed to be self-hosted on any AWS account. You can spin up a cluster with a single command:
2828

29+
<!-- CORTEX_VERSION_README_MINOR -->
2930
```bash
31+
# install the CLI on your machine
32+
$ bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/0.11/get-cli.sh)"
33+
34+
# provision infrastructure on AWS and spin up a cluster
3035
$ cortex cluster up
3136

3237
aws region: us-west-2
3338
aws instance type: p2.xlarge
39+
spot instances: yes
3440
min instances: 0
3541
max instances: 10
36-
spot instances: yes
3742

3843
○ spinning up your cluster ...
3944
your cluster is ready!
@@ -106,9 +111,9 @@ negative 4
106111

107112
<br>
108113

109-
## What is Cortex an alternative to?
114+
## What is Cortex similar to?
110115

111-
Cortex is an open source alternative to serving models with SageMaker or building your own model deployment platform on top of AWS services like Elastic Kubernetes Service (EKS), Elastic Container Service (ECS), Lambda, Fargate, and Elastic Compute Cloud (EC2) or open source projects like Docker, Kubernetes, and TensorFlow Serving.
116+
Cortex is an open source alternative to serving models with SageMaker or building your own model deployment platform on top of AWS services like Elastic Kubernetes Service (EKS), Elastic Container Service (ECS), Lambda, Fargate, and Elastic Compute Cloud (EC2) and open source projects like Docker, Kubernetes, and TensorFlow Serving.
112117

113118
<br>
114119

docs/cluster-management/install.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ See [cluster configuration](config.md) to learn how you can customize your clust
1111

1212
<!-- CORTEX_VERSION_MINOR -->
1313
```bash
14-
# install the Cortex CLI on your machine
14+
# install the CLI on your machine
1515
bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/0.11/get-cli.sh)"
1616

17-
# provision infrastructure on AWS and install Cortex
17+
# provision infrastructure on AWS and spin up a cluster
1818
cortex cluster up
1919
```
2020

examples/sklearn/iris-classifier/README.md

Lines changed: 134 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ $ python3 trainer.py
5858
# predictor.py
5959

6060
import pickle
61-
import numpy
61+
import numpy as np
6262

6363

6464
model = None
65-
labels = ["iris-setosa", "iris-versicolor", "iris-virginica"]
65+
labels = ["setosa", "versicolor", "virginica"]
6666

6767

6868
def init(model_path, metadata):
@@ -71,16 +71,14 @@ def init(model_path, metadata):
7171

7272

7373
def predict(sample, metadata):
74-
input_array = numpy.array(
75-
[
76-
sample["sepal_length"],
77-
sample["sepal_width"],
78-
sample["petal_length"],
79-
sample["petal_width"],
80-
]
81-
)
82-
83-
label_id = model.predict([input_array])[0]
74+
measurements = [
75+
sample["sepal_length"],
76+
sample["sepal_width"],
77+
sample["petal_length"],
78+
sample["petal_width"],
79+
]
80+
81+
label_id = model.predict(np.array([measurements]))[0]
8482
return labels[label_id]
8583
```
8684

@@ -153,7 +151,7 @@ $ curl http://***.amazonaws.com/iris/classifier \
153151
-X POST -H "Content-Type: application/json" \
154152
-d '{"sepal_length": 5.2, "sepal_width": 3.6, "petal_length": 1.4, "petal_width": 0.3}'
155153
156-
"iris-setosa"
154+
"setosa"
157155
```
158156

159157
<br>
@@ -214,7 +212,7 @@ This model is fairly small but larger models may require more compute resources.
214212
tracker:
215213
model_type: classification
216214
compute:
217-
cpu: 1
215+
cpu: 0.5
218216
mem: 1G
219217
```
220218

@@ -257,7 +255,7 @@ If you trained another model and want to A/B test it with your previous model, s
257255
tracker:
258256
model_type: classification
259257
compute:
260-
cpu: 1
258+
cpu: 0.5
261259
mem: 1G
262260
263261
- kind: api
@@ -268,7 +266,7 @@ If you trained another model and want to A/B test it with your previous model, s
268266
tracker:
269267
model_type: classification
270268
compute:
271-
cpu: 1
269+
cpu: 0.5
272270
mem: 1G
273271
```
274272

@@ -286,8 +284,126 @@ creating another-classifier api
286284
$ cortex get --watch
287285
288286
api status up-to-date available requested last update
289-
another-classifier live 1 1 1 8s
290287
classifier live 1 1 1 5m
288+
another-classifier live 1 1 1 8s
289+
```
290+
291+
## Add a batch API
292+
293+
First, implement `batch-predictor.py` with a `predict` function that can process an array of samples:
294+
295+
```python
296+
# batch-predictor.py
297+
298+
import pickle
299+
import numpy as np
300+
301+
302+
model = None
303+
labels = ["setosa", "versicolor", "virginica"]
304+
305+
306+
def init(model_path, metadata):
307+
global model
308+
model = pickle.load(open(model_path, "rb"))
309+
310+
311+
def predict(sample, metadata):
312+
measurements = [
313+
[s["sepal_length"], s["sepal_width"], s["petal_length"], s["petal_width"]] for s in sample
314+
]
315+
316+
label_ids = model.predict(np.array(measurements))
317+
return [labels[label_id] for label_id in label_ids]
318+
```
319+
320+
Next, add the `api` to `cortex.yaml`:
321+
322+
```yaml
323+
- kind: deployment
324+
name: iris
325+
326+
- kind: api
327+
name: classifier
328+
predictor:
329+
path: predictor.py
330+
model: s3://cortex-examples/sklearn/iris-classifier/model.pkl
331+
tracker:
332+
model_type: classification
333+
compute:
334+
cpu: 0.5
335+
mem: 1G
336+
337+
- kind: api
338+
name: another-classifier
339+
predictor:
340+
path: predictor.py
341+
model: s3://cortex-examples/sklearn/iris-classifier/another-model.pkl
342+
tracker:
343+
model_type: classification
344+
compute:
345+
cpu: 0.5
346+
mem: 1G
347+
348+
349+
- kind: api
350+
name: batch-classifier
351+
predictor:
352+
path: batch-predictor.py
353+
model: s3://cortex-examples/sklearn/iris-classifier/model.pkl
354+
compute:
355+
cpu: 0.5
356+
mem: 1G
357+
```
358+
359+
Run `cortex deploy` to create the batch API:
360+
361+
```bash
362+
$ cortex deploy
363+
364+
creating batch-classifier api
365+
```
366+
367+
`cortex get` should show all three APIs now:
368+
369+
```bash
370+
$ cortex get --watch
371+
372+
api status up-to-date available requested last update
373+
classifier live 1 1 1 10m
374+
another-classifier live 1 1 1 5m
375+
batch-classifier live 1 1 1 8s
376+
```
377+
378+
<br>
379+
380+
## Try a batch prediction
381+
382+
```bash
383+
$ curl http://***.amazonaws.com/iris/classifier \
384+
-X POST -H "Content-Type: application/json" \
385+
-d '[
386+
{
387+
"sepal_length": 5.2,
388+
"sepal_width": 3.6,
389+
"petal_length": 1.5,
390+
"petal_width": 0.3
391+
},
392+
{
393+
"sepal_length": 7.1,
394+
"sepal_width": 3.3,
395+
"petal_length": 4.8,
396+
"petal_width": 1.5
397+
},
398+
{
399+
"sepal_length": 6.4,
400+
"sepal_width": 3.4,
401+
"petal_length": 6.1,
402+
"petal_width": 2.6
403+
}
404+
]'
405+
406+
["setosa","versicolor","virginica"]
291407
```
292408

293409
<br>
@@ -301,6 +417,7 @@ $ cortex delete
301417
302418
deleting classifier api
303419
deleting another-classifier api
420+
deleting batch-classifier api
304421
```
305422

306423
Running `cortex delete` will free up cluster resources and allow Cortex to scale down to the minimum number of instances you specified during cluster installation. It will not spin down your cluster.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pickle
2+
import numpy as np
3+
4+
5+
model = None
6+
labels = ["setosa", "versicolor", "virginica"]
7+
8+
9+
def init(model_path, metadata):
10+
global model
11+
model = pickle.load(open(model_path, "rb"))
12+
13+
14+
def predict(sample, metadata):
15+
measurements = [
16+
[s["sepal_length"], s["sepal_width"], s["petal_length"], s["petal_width"]] for s in sample
17+
]
18+
19+
label_ids = model.predict(np.array(measurements))
20+
return [labels[label_id] for label_id in label_ids]

examples/sklearn/iris-classifier/cortex.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
tracker:
1010
model_type: classification
1111
compute:
12-
cpu: 1
12+
cpu: 0.5
1313
mem: 1G
1414

1515
- kind: api
@@ -20,5 +20,14 @@
2020
tracker:
2121
model_type: classification
2222
compute:
23-
cpu: 1
23+
cpu: 0.5
24+
mem: 1G
25+
26+
- kind: api
27+
name: batch-classifier
28+
predictor:
29+
path: batch-predictor.py
30+
model: s3://cortex-examples/sklearn/iris-classifier/model.pkl
31+
compute:
32+
cpu: 0.5
2433
mem: 1G
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import pickle
2-
import numpy
2+
import numpy as np
33

44

55
model = None
6-
labels = ["iris-setosa", "iris-versicolor", "iris-virginica"]
6+
labels = ["setosa", "versicolor", "virginica"]
77

88

99
def init(model_path, metadata):
@@ -12,14 +12,12 @@ def init(model_path, metadata):
1212

1313

1414
def predict(sample, metadata):
15-
input_array = numpy.array(
16-
[
17-
sample["sepal_length"],
18-
sample["sepal_width"],
19-
sample["petal_length"],
20-
sample["petal_width"],
21-
]
22-
)
15+
measurements = [
16+
sample["sepal_length"],
17+
sample["sepal_width"],
18+
sample["petal_length"],
19+
sample["petal_width"],
20+
]
2321

24-
label_id = model.predict([input_array])[0]
22+
label_id = model.predict(np.array([measurements]))[0]
2523
return labels[label_id]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sepal_length": 5.2,
33
"sepal_width": 3.6,
4-
"petal_length": 1.4,
4+
"petal_length": 1.5,
55
"petal_width": 0.3
66
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[
2+
{
3+
"sepal_length": 5.2,
4+
"sepal_width": 3.6,
5+
"petal_length": 1.5,
6+
"petal_width": 0.3
7+
},
8+
{
9+
"sepal_length": 7.1,
10+
"sepal_width": 3.3,
11+
"petal_length": 4.8,
12+
"petal_width": 1.5
13+
},
14+
{
15+
"sepal_length": 6.4,
16+
"sepal_width": 3.4,
17+
"petal_length": 6.1,
18+
"petal_width": 2.6
19+
}
20+
]

0 commit comments

Comments
 (0)