1.1 web服务与技术框架

下面以ResNet50预训练模型为例,旨在展示一个轻量级的深度学习模型部署,写一个较为简单的图像分类的REST API。主要技术框架为Keras+Flask+Redis。其中Keras作为模型框架、Flask作为后端Web框架、Redis则是方便以键值形式存储图像的数据库。各主要package版本:

tensorflow 1.14keras 2.2.4flask 1.1.1redis 3.3.8

先简单说一下Web服务,一个Web应用的本质无非就是客户端发送一个HTTP请求,然后服务器收到请求后生成一个HTML文档作为响应返回给客户端的过程。在部署深度学习模型时,大多时候我们不需要搞一个前端页面出来,一般是以REST API的形式提供给开发调用。那么什么是API呢?很简单,如果一个URL返回的不是HTML,而是机器能直接解析的数据,这样的一个URL就可以看作是一个API。

先开启Redis服务:

redis-server

1.2 服务配置

定义一些配置参数:

IMAGE_WIDTH = 224IMAGE_HEIGHT = 224IMAGE_CHANS = 3IMAGE_DTYPE = "float32"IMAGE_QUEUE = "image_queue"BATCH_SIZE = 32SERVER_SLEEP = 0.25CLIENT_SLEEP = 0.25

指定输入图像大小、类型、batch_size大小以及Redis图像队列名称。

然后创建Flask对象实例,建立Redis数据库连接:

app = flask.Flask(__name__)db = redis.StrictRedis(host="localhost", port=6379, db=0)model = None

因为图像数据作为numpy数组不能直接存储到Redis中,所以图像存入到数据库之前需要将其序列化编码,从数据库取出时再将其反序列化解码即可。分别定义编码和解码函数:

def base64_encode_image(img):return base64.b64encode(img).decode("utf-8")def base64_decode_image(img, dtype, shape):if sys.version_info.major == 3:img = bytes(img, encoding="utf-8")img = np.frombuffer(base64.decodebytes(img), dtype=dtype)img = img.reshape(shape)return img

另外待预测图像还需要进行简单的预处理,定义预处理函数如下:

def prepare_image(image, target):# if the image mode is not RGB, convert itif image.mode != "RGB":image = image.convert("RGB")# resize the input image and preprocess itimage = image.resize(target)image = img_to_array(image)# expand image as one batch like shape (1, c, w, h)image = np.expand_dims(image, axis=0)image = imagenet_utils.preprocess_input(image)# return the processed imagereturn image

1.3 预测接口定义

准备工作完毕之后,接下来就是主要的两大部分:模型预测部分和app后端响应部分。先定义模型预测函数如下:

def classify_process():# 导入模型print("* Loading model...")model = ResNet50(weights="imagenet")print("* Model loaded")while True:# 从数据库中创建预测图像队列queue = db.lrange(IMAGE_QUEUE, 0, BATCH_SIZE - 1)imageIDs = []batch = None# 遍历队列for q in queue:# 获取队列中的图像并反序列化解码q = json.loads(q.decode("utf-8"))image = base64_decode_image(q["image"], IMAGE_DTYPE,(1, IMAGE_HEIGHT, IMAGE_WIDTH, IMAGE_CHANS))# 检查batch列表是否为空if batch is None:batch = image# 合并batchelse:batch = np.vstack([batch, image])# 更新图像IDimageIDs.append(q["id"])if len(imageIDs) > 0:print("* Batch size: {}".format(batch.shape))preds = model.predict(batch)results = imagenet_utils.decode_predictions(preds)# 遍历图像ID和预测结果并打印for (imageID, resultSet) in zip(imageIDs, results):# initialize the list of output predictionsoutput = []# loop over the results and add them to the list of# output predictionsfor (imagenetID, label, prob) in resultSet:r = {"label": label, "probability": float(prob)}output.append(r)# 保存结果到数据库db.set(imageID, json.dumps(output))# 从队列中删除已预测过的图像db.ltrim(IMAGE_QUEUE, len(imageIDs), -1)time.sleep(SERVER_SLEEP)

然后定义app服务:

@app.route("/predict", methods=["POST"])
def predict():# 初始化数据字典data = {"success": False}# 确保图像上传方式正确if flask.request.method == "POST":if flask.request.files.get("image"):# 读取图像数据image = flask.request.files["image"].read()image = Image.open(io.BytesIO(image))image = prepare_image(image, (IMAGE_WIDTH, IMAGE_HEIGHT))# 将数组以C语言存储顺序存储image = image.copy(order="C")# 生成图像IDk = str(uuid.uuid4())d = {"id": k, "image": base64_encode_image(image)}db.rpush(IMAGE_QUEUE, json.dumps(d))# 运行服务while True:# 获取输出结果output = db.get(k)if output is not None:output = output.decode("utf-8")data["predictions"] = json.loads(output)db.delete(k)breaktime.sleep(CLIENT_SLEEP)data["success"] = Truereturn flask.jsonify(data)

Flask使用Python装饰器在内部自动将请求的URL和目标函数关联了起来,这样方便我们快速搭建一个Web服务。

1.4 接口测试

服务搭建好了之后我们可以用一张图片来测试一下效果:

curl -X POST -F image=@test.jpg 'http://127.0.0.1:5000/predict'

模型端的返回:

预测结果返回:

最后我们可以给搭建好的服务进行一个压力测试,看看服务的并发等性能如何,定义一个压测文件stress_test.py 如下:

from threading import Thread
import requests
import time
# 请求的URL
KERAS_REST_API_URL = "http://127.0.0.1:5000/predict"
# 测试图片
IMAGE_PATH = "test.jpg"
# 并发数
NUM_REQUESTS = 500
# 请求间隔
SLEEP_COUNT = 0.05
def call_predict_endpoint(n):# 上传图像image = open(IMAGE_PATH, "rb").read()payload = {"image": image}# 提交请求r = requests.post(KERAS_REST_API_URL, files=payload).json()# 确认请求是否成功if r["success"]:print("[INFO] thread {} OK".format(n))else:print("[INFO] thread {} FAILED".format(n))
# 多线程进行
for i in range(0, NUM_REQUESTS):# 创建线程来调用apit = Thread(target=call_predict_endpoint, args=(i,))t.daemon = Truet.start()time.sleep(SLEEP_COUNT)
time.sleep(300)

测试效果如下:

基于web端的深度学习模型部署相关推荐

  1. 【深度学习】基于web端和C++的两种深度学习模型部署方式

    深度学习 Author:louwill Machine Learning Lab 本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基于C++软件集成的方式进行部署 ...

  2. pytorch基于web端和C++的两种深度学习模型部署方式

    本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基于C++软件集成的方式进行部署. 基于web服务端的模型部署,主要是通过REST API的形式来提供接口方便调用 ...

  3. 基于web端和C++的两种深度学习模型部署方式

    深度学习Author:louwillMachine Learning Lab 本文对深度学习两种模型部署方式进行总结和梳理.一种是基于web服务端的模型部署,一种是基... 深度学习 Author:l ...

  4. 为什么将表格的method改为post后就无法工作_用Python将Keras深度学习模型部署为Web应用程序...

    构建一个很棒的机器学习项目是一回事,但归根结底,你希望其他人能够看到你的辛勤工作.当然,你可以将整个项目放在GitHub上,但是怎么让你的祖父母也看到呢?我们想要的是将深度学习模型部署为世界上任何人都 ...

  5. 【项目实战课】从零掌握安卓端Pytorch原生深度学习模型部署

    欢迎大家来到我们的项目实战课,本期内容是<从零掌握安卓端Pytorch原生深度学习模型部署>.所谓项目课,就是以简单的原理回顾+详细的项目实战的模式,针对具体的某一个主题,进行代码级的实战 ...

  6. 基于TensorRT的深度学习模型部署实战教程!

    应用背景介绍 早在遥远的1989年,一家叫做ALVIVN的公司首次将神经网络用在汽车上,进行车道线检测和地面分割.时至今日,深度学习已经应用在自动驾驶系统的多个分支领域.首先是感知领域,常用的传感器有 ...

  7. 深度学习模型部署技术方案

    深度学习模型部署技术方案 训练好的深度学习模型如何进行部署的相关技术方案 1 什么是模型部署? 2 数据科学项目整个开发流程 3 使用flask 将 Keras深度学习模型部署为Web应用程序 4 T ...

  8. 面向生产环境!深度学习模型部署资源全辑

    点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:机器学习实验室   Author:louwill Machine Learning Lab AI博士笔记系列推 ...

  9. 深度学习模型部署之模型优化

    文章目录 前言 模型剪枝 MNIST 常规训练 Setup 常规训练模型 模型评估 Pruning 模型定义 训练模型 评估模型 pruning your model API prune_low_ma ...

最新文章

  1. Mix3D:大规模三维场景的数据增强(3DV2021)
  2. QIIME 2用户文档. 11元数据Metadata(2019.7)
  3. Elasticsearch中如何进行排序(中文+父子文档+嵌套文档)
  4. linux命令strip
  5. springboot-静态资源配置原理
  6. COLING 2020 | CharBERT:字符敏感的预训练语言模型
  7. 【转】vscode配置C/C++环境
  8. finally语句与return语句的执行顺序
  9. Jmeter分布式测试过程中遇到的问题及摘抄前辈问题汇总
  10. 中职 计算机原理 计算题,中职《计算机原理》测验2.doc
  11. Leetcode95. Unique Binary Search Trees II不同的二叉搜索树2
  12. 自学软件测试需要学到哪些内容?
  13. mdf文件和ldf文件是什么?
  14. 四大盈利互联网经营理念
  15. 成都最有特色的9大茶馆
  16. 迷宫问题 深度优先搜索【c++】
  17. 从玩法、叙事、主题三个角度浅要谈谈《死亡搁浅》的好与坏
  18. python将数据导出为csv文件时,出现PermissionError: [Errno 13] Permission denied:问题
  19. 实验六 医学图像的增强(二)
  20. 【kafka】连接kafka报错 partitions have leader brokers without a matching listener

热门文章

  1. Mac 配置CocoaPods
  2. 前端网络基础 - axios使用
  3. JAVA使用POI对Excel中的条件格式处理
  4. flink性能测试 (工业领域三维空间数据的重要性)
  5. 走路像踩棉花小心颈椎出问题?
  6. 李宏毅_机器学习_作业3(详解)_HW3 Image Classification
  7. 通信标准1之PUSCH 时间域重复类型 A 和重复类型 B
  8. 三人看《中国合伙人》电影感悟
  9. N026_只根据转入和转出两列来画桑基图_巡线追踪
  10. Intel处理器Family、Model、Stepping等的学习