In case of doubts refer to the documentation on https://clipper.ai.
This example uses matplotlib
, in case you cannot use it, please comment out a part of cell 3
In [2]:
import tensorflow as tf
import numpy
import matplotlib.pyplot as plt
rng = numpy.random
In [3]:
# Parameters
learning_rate = 0.01
training_epochs = 500
display_step = 50
# Training Data
train_X = numpy.asarray([3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.167,
7.042,10.791,5.313,7.997,5.654,9.27,3.1])
train_Y = numpy.asarray([1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.221,
2.827,3.465,1.65,2.904,2.42,2.94,1.3])
n_samples = train_X.shape[0]
# tf Graph Input
# You must name the variables and placeholders, as the names will be later used!!!
X = tf.placeholder("float", name='X')
Y = tf.placeholder("float")
# Set model weights
W = tf.Variable(rng.randn(), name="weight")
b = tf.Variable(rng.randn(), name="bias")
# Construct a linear model
pred = tf.add(tf.multiply(X, W), b, name='pred')
# Mean squared error
cost = tf.reduce_sum(tf.pow(pred-Y, 2))/(2*n_samples)
# Gradient descent
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
# Initialize the variables (i.e. assign their default value)
init = tf.global_variables_initializer()
saver = tf.train.Saver()
# Start training
# sess = tf.Session()
with tf.Session() as sess:
sess.run(init)
# Fit all training data
for epoch in range(training_epochs):
for (x, y) in zip(train_X, train_Y):
sess.run(optimizer, feed_dict={X: x, Y: y})
#Display logs per epoch step
if (epoch+1) % display_step == 0:
c = sess.run(cost, feed_dict={X: train_X, Y:train_Y})
print("Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(c), \
"W=", sess.run(W), "b=", sess.run(b))
print("Optimization Finished!")
training_cost = sess.run(cost, feed_dict={X: train_X, Y: train_Y})
print("Training cost=", training_cost, "W=", sess.run(W), "b=", sess.run(b), '\n')
# Save the variables to disk.
save_path = saver.save(sess, "/tmp/tf/model.ckpt")
print("Model saved in path: %s" % save_path)
#Graphic display - matplotlib
plt.plot(train_X, train_Y, 'ro', label='Original data')
plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
plt.legend()
plt.show()
In [4]:
# import the inspect_checkpoint library
from tensorflow.python.tools import inspect_checkpoint as chkp
# print all tensors in checkpoint file
chkp.print_tensors_in_checkpoint_file("/tmp/tf/model.ckpt", tensor_name='', all_tensors=True)
In [5]:
def predict(sess, inputs):
preds = sess.run('pred:0', feed_dict={'X:0': inputs})
# `X` is used, it must be defined in the model with that name explicitly!
return [str(p) for p in preds]
In [6]:
from clipper_admin import ClipperConnection, DockerContainerManager
from clipper_admin.deployers.tensorflow import deploy_tensorflow_model
clipper_conn = ClipperConnection(DockerContainerManager())
In [7]:
clipper_conn.start_clipper()
In [8]:
# You can see some Clipper containers by simply running:
!docker ps
In [9]:
clipper_conn.connect()
In [10]:
# List all applications
clipper_conn.get_all_apps()
Out[10]:
In [11]:
# List all models
clipper_conn.get_all_models()
Out[11]:
In [12]:
# Add an application with a name and an input type
clipper_conn.register_application(
name="tf-app", input_type="doubles", default_output="-1.0", slo_micros=100000)
In [13]:
# Deploy a model, to check what arguments you need run
# "?deploy_tensorflow_model" to let the notebook show you the definition of the method
deploy_tensorflow_model(
clipper_conn,
name="tf-mod",
version=1,
input_type="doubles",
func=predict,
tf_sess_or_saved_model_path="/tmp/tf/") # path to saved model files is used,
# session example in the next section
In [14]:
# Link the model and the app
clipper_conn.link_model_to_app(
app_name="tf-app",
model_name="tf-mod")
In [15]:
# Show the apps again, should list one
clipper_conn.get_all_apps()
Out[15]:
In [16]:
# Get query address
query_address = clipper_conn.get_query_addr()
In [17]:
# Run a query
import requests, json, numpy as np
headers = {"Content-type": "application/json"}
requests.post("http://"+query_address+"/tf-app/predict", headers=headers, data=json.dumps({
"input": [.8, 3.2]})).json()
Out[17]:
In [18]:
# Clipper allows to deploy a TensorFlow model using a session variable too
# First the model must be restored from the files
# Pay attention to the fact that variables/placeholders are restored
# with exactly the same names
tf.reset_default_graph()
W = tf.get_variable("weight", shape=[])
b = tf.get_variable("bias", shape=[])
X = tf.placeholder("float", name='X')
pred = tf.add(tf.multiply(X, W), b, name='pred')
saver = tf.train.Saver()
sess = tf.Session()
# Restore variables from disk.
saver.restore(sess, "/tmp/tf/model.ckpt")
print("Model restored.")
print("W : %s" % W.eval(session=sess))
print("b : %s" % b.eval(session=sess))
In [19]:
# Check that the session variable exists
sess
Out[19]:
In [20]:
deploy_tensorflow_model(
clipper_conn,
name="tf-mod",
version=2, # version 2 of the same model, `predict` endpoint will be updated
# automatically to the newest model version
input_type="doubles",
func=predict,
tf_sess_or_saved_model_path=sess) # `sess` variable is used here
In [21]:
# Session can be closed now
sess.close()
In [22]:
# Run a query
headers = {"Content-type": "application/json"}
requests.post("http://"+query_address+"/tf-app/predict", headers=headers, data=json.dumps({
"input": [.8, 3.2]})).json()
# The result is the same
Out[22]:
In [23]:
# You can revert to the previous model version, the query endpoint remains the same
clipper_conn.set_model_version("tf-mod", "1")
In [24]:
# Replicate the model 5 times
clipper_conn.set_num_replicas("tf-mod", 5)
In [25]:
# Back to one replica
clipper_conn.set_num_replicas("tf-mod", 1)
In [26]:
# You can also register more applications - connections to the model and link them to it
clipper_conn.register_application(
name="tf-app-extra", input_type="doubles", default_output="-1.0", slo_micros=100000)
# You have to link them the standard way. You can also link an existing application
# to another model if you wish using the same method
clipper_conn.link_model_to_app(
app_name="tf-app-extra",
model_name="tf-mod")
In [27]:
# Run a query with an endpoint `tf-app-extra/predict`
headers = {"Content-type": "application/json"}
requests.post("http://"+query_address+"/tf-app-extra/predict", headers=headers, data=json.dumps({
"input": [.8, 3.2]})).json()
Out[27]:
In [28]:
# Unlink the model and the apps
clipper_conn.unlink_model_from_app(model_name="tf-mod", app_name="tf-app")
clipper_conn.unlink_model_from_app(model_name="tf-mod", app_name="tf-app-extra")
In [29]:
# Stop the model
clipper_conn.stop_models('tf-mod')
In [30]:
# Remove the apps
clipper_conn.delete_application('tf-app')
clipper_conn.delete_application('tf-app-extra')
In [31]:
# Stop Clipper
clipper_conn.stop_all()
In [32]:
# Check that all docker processes are stopped
!docker ps
In [ ]: