Có một bài hướng dẫn khá xịn ở đây nhưng khá dài. Mình sẽ viết 1 đoạn ngắn hơn tập trung vào thực hành serving một model cụ thể.
Hiểu đơn giản khi đưa model lên môi trường product cần serving để:
- Tách biệt model với codebase của backend
- Dễ dàng thay đổi phiên bản mới của model, hoặc rollback về phiên bản cũ
- Serving nhiều model cùng lúc với 1 file config
- Tăng hiệu năng xử lý
- Batching
Các bước triển khai
- Bước 1: convert TF model về định dạng TF Savemodel
- Bước 2: Pull tensorflow serving docker
Một ví dụ với một model đơn giản
Build/Train
# -*- coding: utf-8 -*-
"""CNNs.ipynb
Automatically generated by Colaboratory.
Original file is located at
https://colab.research.google.com/drive/1ibfKtpxC_hIhZlPbefCoqpAS7jTdyiFw
"""
import tensorflow as tf
# Load MNIST data
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# Preprocessing
x_train = x_train / 255.0
x_test = x_test / 255.0
# Add one domention to make 3D images
x_train = x_train[...,tf.newaxis]
x_test = x_test[...,tf.newaxis]
# Track the data type
dataType, dataShape = x_train.dtype, x_train.shape
print(f"Data type and shape x_train: {dataType} {dataShape}")
labelType, labelShape = y_train.dtype, y_train.shape
print(f"Data type and shape y_train: {labelType} {labelShape}")
im_list = []
n_samples_to_show = 16
c = 0
for i in range(n_samples_to_show):
im_list.append(x_train[i])
# Visualization
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
fig = plt.figure(figsize=(4., 4.))
# Ref: https://matplotlib.org/3.1.1/gallery/axes_grid1/simple_axesgrid.html
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(4, 4), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
)
# Show image grid
for ax, im in zip(grid, im_list):
# Iterating over the grid returns the Axes.
ax.imshow(im[:,:,0], 'gray')
plt.show()
"""## Training"""
# Model building
NUM_CLASSES = 10
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(NUM_CLASSES, activation='sigmoid')]
)
import os
checkpoint_path = "training/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)
# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
save_weights_only=True,
verbose=1)
# Compiling the model with the high-level keras
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['accuracy'])
# Model training
model.fit(x_train, y_train, epochs=5, callbacks=[cp_callback])
"""## Evaluation"""
eval_loss, eval_acc = model.evaluate(x_test, y_test, verbose=1)
print('Eval accuracy percentage: {:.2f}'.format(eval_acc * 100))
- Trọng số được lưu dưới dạng checkpoint
training/cp.ckpt
. Thực hiệnbước 1
(convert TF model về định dạng TF Savemodel)Build/load model
NUM_CLASSES = 10
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(16, (3, 3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),
tf.keras.layers.MaxPooling2D((2, 2)),
tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(NUM_CLASSES, activation='sigmoid')]
)
model.load_weights(checkpoint_path)
SaveModel là định dạng lưu toàn bộ trọng số và các phép tính toán, nhờ vậy khi sử dụng không cần build lại model bằng code. Muốn lưu model sang dạng này cần biết tensor đầu vào và đầu ra mà chúng ta cần. Vậy, ta xem list tensor của model
[n.name for n in tf.get_default_graph().as_graph_def().node]
output
['conv2d_input',
'conv2d/kernel/Initializer/random_uniform/shape',
'conv2d/kernel/Initializer/random_uniform/min',
'conv2d/kernel/Initializer/random_uniform/max',
'conv2d/kernel/Initializer/random_uniform/RandomUniform',
'conv2d/kernel/Initializer/random_uniform/sub',
'conv2d/kernel/Initializer/random_uniform/mul',
'conv2d/kernel/Initializer/random_uniform',
'conv2d/kernel',
'conv2d/kernel/IsInitialized/VarIsInitializedOp',
...
'dense_3/bias',
'dense_3/bias/IsInitialized/VarIsInitializedOp',
'dense_3/bias/Assign',
'dense_3/bias/Read/ReadVariableOp',
'dense_3/MatMul/ReadVariableOp',
'dense_3/MatMul',
'dense_3/BiasAdd/ReadVariableOp',
'dense_3/BiasAdd',
'dense_3/Sigmoid',
'Const_2',
'RestoreV2/tensor_names',
'RestoreV2/shape_and_slices',
...
Dựa vào model mà chúng ta build có thể nhận ra đầu vào là tensor 'conv2d_input'
và đầu ra là 'dense_3/Sigmoid'
Convert sang SaveModel bằng đoạn code sau
graph = tf.get_default_graph()
inputImgs = graph.get_tensor_by_name('conv2d_input:0')
pred_ = graph.get_tensor_by_name('dense_3/Sigmoid:0')
model_version = '1'
export_model_dir = "models/serving/versions"
export_path_base = export_model_dir
export_path = os.path.join(
tf.compat.as_bytes(export_path_base),
tf.compat.as_bytes(str(model_version)))
print('Exporting trained model to', export_path)
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
tensor_input = tf.saved_model.utils.build_tensor_info(inputImgs)
tensor_output = tf.saved_model.utils.build_tensor_info(pred_)
prediction_signature = (tf.saved_model.signature_def_utils.build_signature_def(
inputs={'image': tensor_input},
outputs={'decoded': tensor_output},
method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
with tf.Session(graph=tf.Graph()) as sess:
builder.add_meta_graph_and_variables(sess, [tf.saved_model.tag_constants.SERVING],
signature_def_map={'predict_classes':prediction_signature,})
builder.save()
Kiểm tra folder models/serving/versions/1
chúng ta đã có TFSaveModel
Bước 2: Pull tensorflow serving docker
Trong thư mục models tạo file batching_parameters.txt
max_batch_size { value: 1024 }
batch_timeout_micros { value: 1000 }
Và file models.config
model_config_list: {
config: {
name: "mobile",
base_path: "models/serving/versions",
model_platform: "tensorflow"
}
}
Cuối cùng là pull docker
#pull tensorflow serving docker
##Step 1
docker pull tensorflow/serving:1.13.0-gpu
##Step 2
#create image # run
sudo nvidia-docker run -d --name serving_base_v3 tensorflow/serving:1.13.0-gpu
##Step 3
sudo docker cp ./serving serving_base_v3:/models/mobile
sudo docker cp models.config serving_base_v3:/models/models.config
sudo docker cp batching_parameters.txt serving_base_v3:/models/batching_parameters.txt
sudo docker commit serving_base_v3 mobile_serving:v1
##Step 4
sudo docker kill serving_base_v3
#
##Step 5
sudo nvidia-docker run -d -p 8500:8500 mobile_serving:v1 --model_config_file=/models/models.config --enable_batching=true --batching_parameters_file=/models/batching_parameters.txt --per_process_gpu_memory_fraction=0.5
Mọi model bạn đều có thể làm theo các bước trên kể cả phức tạp. Nhưng nếu bạn không biết đầu vào, đầu ra của model thì chịu - đùa thôi - thì thử. Goodluck. code coclab