深度学习模型被训练后,需要将model部署为一个服务。本文给出一个利用flask部署keras model服务的demo。这个网络的Demo来自于TF的官网,首先引入相应的包:
# Tensorflow classification
from __future__ import absolute_import, division, print_function, unicode_literals
import os
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
import tensorflow as tf
from tensorflow import keras
import numpy as np
%matplotlib inline
import matplotlib.pyplot as plt
print(tf.__version__)
# 1.12.0
加载数据
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# 数据预处理
train_images = train_images / 255.0
test_images = test_images / 255.0
构建网络结构
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation=tf.nn.relu),
keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# 训练
model.fit(train_images, train_labels, epochs=5)
模型评价
test_loss, test_acc = model.evaluate(test_images, test_labels)
# 10000/10000 [==============================] - 0s 27us/step
# Test acc: 0.8732
保存权重为.h5文件
model.save_weights('./model/weights.h5')
部署部分
# 引入包,构建网络并加载训练好的参数
from flask import Flask, render_template, request
from scipy.misc import imsave, imread, imresize
import numpy as np
import tensorflow as tf
from tensorflow import keras
import re, sys, os
import base64
import cv2
sys.path.append(os.path.abspath('./model'))
model = keras.Sequential([
keras.layers.Flatten(input_shape=(28, 28)),
keras.layers.Dense(128, activation=tf.nn.relu),
keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.load_weights('./model/weights.h5')
graph = tf.get_default_graph()
定义数据转化的方法
def b64_to_ndarray(image_b64):
img_bytes = base64.b64decode(image_b64)
nparr = np.frombuffer(img_bytes, np.uint8)
arr = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
assert arr.shape == (28, 28)
arr = arr[None, :, :] / 255.0
return arr
定义flask服务方法
app = Flask(__name__)
# global model, graph
@app.route('/predict', methods=['POST'])
def predict():
b64 = request.get_data()
arr = b64_to_ndarray(b64)
print(arr.shape)
with graph.as_default():
ret = model.predict(arr)
resp = np.array_str(np.argmax(ret, axis=1))
return resp
启动web app
port = int(os.environ.get('PORT', 5060))
app.run(host='0.0.0.0', port=port)
# Running on http://0.0.0.0:5060/ (Press CTRL+C to quit)
测试服务调用,我们选择fashion_mnist的一张图片进行测试。
from tensorflow import keras
fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
im = test_images[1]
gt = test_labels[1]
对图片进行编码,因为在server端我们用到了cv2进行解码,所以客户端需要用cv2进行编码
import cv2, base64
bb = cv2.imencode('.jpg', im)
im_b64 = base64.b64encode(bb)
调用服务
import requests
import numpy as np
# 注意这里是http服务, not https。
# data参数传进图片的b64编码
ret = requests.post('http://localhost:5060/predict', data=im_b64)
# '[2]'
pred = np.fromstring(ret.text)[0]
print('Prediction right? {}'.format(pred == gt))