Skip to content

Commit e93eff6

Browse files
jesterhazywinstonaws
authored andcommitted
add sagemaker cli (#32)
* add sagemaker cli * remove unnecessary close * address PR comments * tidy up imports * fix imports, flake8 errors * improve help message for bucket-name * remove default role name * fix log-level and py3 tests, add copyright * update cli example scripts
1 parent 2e0ed8f commit e93eff6

19 files changed

+838
-1
lines changed

examples/cli/host/data/model.json

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{
2+
"nodes": [
3+
{
4+
"op": "null",
5+
"name": "data",
6+
"inputs": []
7+
},
8+
{
9+
"op": "null",
10+
"name": "sequential0_dense0_weight",
11+
"attr": {
12+
"__dtype__": "0",
13+
"__lr_mult__": "1.0",
14+
"__shape__": "(128, 0)",
15+
"__wd_mult__": "1.0"
16+
},
17+
"inputs": []
18+
},
19+
{
20+
"op": "null",
21+
"name": "sequential0_dense0_bias",
22+
"attr": {
23+
"__dtype__": "0",
24+
"__init__": "zeros",
25+
"__lr_mult__": "1.0",
26+
"__shape__": "(128,)",
27+
"__wd_mult__": "1.0"
28+
},
29+
"inputs": []
30+
},
31+
{
32+
"op": "FullyConnected",
33+
"name": "sequential0_dense0_fwd",
34+
"attr": {"num_hidden": "128"},
35+
"inputs": [[0, 0, 0], [1, 0, 0], [2, 0, 0]]
36+
},
37+
{
38+
"op": "Activation",
39+
"name": "sequential0_dense0_relu_fwd",
40+
"attr": {"act_type": "relu"},
41+
"inputs": [[3, 0, 0]]
42+
},
43+
{
44+
"op": "null",
45+
"name": "sequential0_dense1_weight",
46+
"attr": {
47+
"__dtype__": "0",
48+
"__lr_mult__": "1.0",
49+
"__shape__": "(64, 0)",
50+
"__wd_mult__": "1.0"
51+
},
52+
"inputs": []
53+
},
54+
{
55+
"op": "null",
56+
"name": "sequential0_dense1_bias",
57+
"attr": {
58+
"__dtype__": "0",
59+
"__init__": "zeros",
60+
"__lr_mult__": "1.0",
61+
"__shape__": "(64,)",
62+
"__wd_mult__": "1.0"
63+
},
64+
"inputs": []
65+
},
66+
{
67+
"op": "FullyConnected",
68+
"name": "sequential0_dense1_fwd",
69+
"attr": {"num_hidden": "64"},
70+
"inputs": [[4, 0, 0], [5, 0, 0], [6, 0, 0]]
71+
},
72+
{
73+
"op": "Activation",
74+
"name": "sequential0_dense1_relu_fwd",
75+
"attr": {"act_type": "relu"},
76+
"inputs": [[7, 0, 0]]
77+
},
78+
{
79+
"op": "null",
80+
"name": "sequential0_dense2_weight",
81+
"attr": {
82+
"__dtype__": "0",
83+
"__lr_mult__": "1.0",
84+
"__shape__": "(10, 0)",
85+
"__wd_mult__": "1.0"
86+
},
87+
"inputs": []
88+
},
89+
{
90+
"op": "null",
91+
"name": "sequential0_dense2_bias",
92+
"attr": {
93+
"__dtype__": "0",
94+
"__init__": "zeros",
95+
"__lr_mult__": "1.0",
96+
"__shape__": "(10,)",
97+
"__wd_mult__": "1.0"
98+
},
99+
"inputs": []
100+
},
101+
{
102+
"op": "FullyConnected",
103+
"name": "sequential0_dense2_fwd",
104+
"attr": {"num_hidden": "10"},
105+
"inputs": [[8, 0, 0], [9, 0, 0], [10, 0, 0]]
106+
}
107+
],
108+
"arg_nodes": [0, 1, 2, 5, 6, 9, 10],
109+
"node_row_ptr": [
110+
0,
111+
1,
112+
2,
113+
3,
114+
4,
115+
5,
116+
6,
117+
7,
118+
8,
119+
9,
120+
10,
121+
11,
122+
12
123+
],
124+
"heads": [[11, 0, 0]],
125+
"attrs": {"mxnet_version": ["int", 1100]}
126+
}
428 KB
Binary file not shown.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
sagemaker mxnet host --role-name <your-sagemaker-execution-role>

examples/cli/host/script.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from __future__ import print_function
2+
3+
import json
4+
import mxnet as mx
5+
from mxnet import gluon
6+
7+
8+
def model_fn(model_dir):
9+
"""
10+
Load the gluon model. Called once when hosting service starts.
11+
12+
:param: model_dir The directory where model files are stored.
13+
:return: a model (in this case a Gluon network)
14+
"""
15+
symbol = mx.sym.load('%s/model.json' % model_dir)
16+
outputs = mx.symbol.softmax(data=symbol, name='softmax_label')
17+
inputs = mx.sym.var('data')
18+
param_dict = gluon.ParameterDict('model_')
19+
net = gluon.SymbolBlock(outputs, inputs, param_dict)
20+
net.load_params('%s/model.params' % model_dir, ctx=mx.cpu())
21+
return net
22+
23+
24+
def transform_fn(net, data, input_content_type, output_content_type):
25+
"""
26+
Transform a request using the Gluon model. Called once per request.
27+
28+
:param net: The Gluon model.
29+
:param data: The request payload.
30+
:param input_content_type: The request content type.
31+
:param output_content_type: The (desired) response content type.
32+
:return: response payload and content type.
33+
"""
34+
# we can use content types to vary input/output handling, but
35+
# here we just assume json for both
36+
parsed = json.loads(data)
37+
nda = mx.nd.array(parsed)
38+
output = net(nda)
39+
prediction = mx.nd.argmax(output, axis=1)
40+
response_body = json.dumps(prediction.asnumpy().tolist())
41+
return response_body, output_content_type
1.57 MB
Binary file not shown.
4.44 KB
Binary file not shown.
9.45 MB
Binary file not shown.
28.2 KB
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from mxnet import gluon
2+
3+
4+
def download_training_data():
5+
gluon.data.vision.MNIST('./data/training', train=True)
6+
gluon.data.vision.MNIST('./data/training', train=False)
7+
8+
9+
if __name__ == "__main__":
10+
download_training_data()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"batch_size": 100,
3+
"epochs": 10,
4+
"learning_rate": 0.1,
5+
"momentum": 0.9,
6+
"log_interval": 100
7+
}

0 commit comments

Comments
 (0)