• tensorflow/serving部署keras的h5模型服务


    当我们使用keras训练好模型之后,下一步就是部署服务了,采用flask直接加载keras的h5模型,服务的并发性能会很低。如果为了追求高并发性能,就可以采用Nginx+gunicorn+gevent的方式来启动服务,这种方式服务虽然可以达到极高的并发性能,但却存在一个问题,也就是gunicorn的方式是启动了多个进程,每个进程都会加载一次模型,造成服务启动后所占用的内存很大,另外直接加载h5模型,整个进程随着使用过程中占用内存也会也逐步增大,这就是python存在了内存泄漏的问题。之前我一个项目部署到生产环境中,使用了两天,占用内存就已经达到了十几个G,因此不得不采用每天定时重启服务这种策略。因此采用tensorflow/serving的方式来部署服务。
    本文中采用的环境为:
    python 3.8.13
    TensorFlow 2.50

    1 keras的h5模型转换为pb格式

    这里以一个验证码识别模型为例进行转换,验证码识别采用crnn+ctc的形式训练,得到的模型文件为h5格式。
    在这里插入图片描述
    使用如下代码将h5模型转换为tensorflow/serving需要的pb格式文件:

    from keras import models
    import keras.backend as K
    from tensorflow.python.framework import graph_util
    
    import tensorflow._api.v2.compat.v1 as tf
    tf.disable_eager_execution()
    
    '''
    tf.saved_model.builder.SavedModelBuilder
    这种模型转换的模型可以提供给TensorFlow Serving使用
    多一个Variable文件
    '''
    
    def keras_model_to_tfs(model, export_path):
        signature = tf.saved_model.signature_def_utils.predict_signature_def(
            inputs={'input_x': model.input}, 
            outputs={'output_y': model.output}
        )
        builder = tf.saved_model.builder.SavedModelBuilder(export_path)
        legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
        builder.add_meta_graph_and_variables(
            sess=K.get_session(),
            tags=[tf.saved_model.tag_constants.SERVING],
            signature_def_map={
                tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature,
            },
            legacy_init_op=legacy_init_op)
        builder.save()
        print('转换完成!')
    
    
    if __name__=='__main__':
        network=models.load_model('./model/hebei.h5')
        export_path='pb2'
        keras_model_to_tfs(network,export_path)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    运行如上代码,得到转换好的pb文件。
    在这里插入图片描述
    重复以上过程,再转换一个模型,新建如下目录yzmModels,该目录下的树形结构为:
    在这里插入图片描述
    hebei目录下的100001目录的文件为转换的第一个模型文件;
    chongqing目录下的100001目录的文件为转换的第二个模型文件;
    在这里插入图片描述
    models.config的文件内容如下:

    model_config_list:{
    	config:{
          name:"hebei",
          base_path:"/models/multiModel/hebei",
          model_platform:"tensorflow"
        },
        config:{
          name:"chongqing",
          base_path:"/models/multiModel/chongqing",
          model_platform:"tensorflow"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2 使用docker启动tensorflow/serving服务

    将yzmModels这个目录上传到服务器里,如下所示:

    在这里插入图片描述

    拉取一个tensorflow/serving的docker镜像

    docker pull tensorflow/serving:2.5.1
    
    • 1

    接着启动docker服务:

    docker run -p 9501:8501 --mount type=bind,source=/root/hhc_etax_login/yzm/yzmModels,target=/models/multiModel -t tensorflow/serving:2.5.1 --model_config_file=/models/multiModel/models.config &
    
    
    • 1
    • 2

    9501为主机上的端口,8501为容器中的端口,容器中的端口8501这个不可更改。source=/root/hhc_etax_login/yzm/yzmModels这个目录为主机上模型文件所在目录。启动成功后,如下所示:

    在这里插入图片描述服务开启好后,我们来测试这个TensorFlow/serving服务是否运行成功,容器的服务对应于主机上的端口为9501,因此使用如下命令测试:

    curl http://localhost:9501/v1/models/hebei
    
    
    • 1
    • 2

    返回结果如下:

    {
     "model_version_status": [
      {
       "version": "100001",
       "state": "AVAILABLE",
       "status": {
        "error_code": "OK",
        "error_message": ""
       }
      }
     ]
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    使用python代码来测试hebei这个模型,TensorFlow/serving服务传的数据是矩阵形式的,代码如下:

    import numpy as np 
    import requests
    import json
    
    
    
    if __name__=='__main__':
        #(1, 32, 77, 3)
        #img_array代表图像数据,也就是传入模型的输入数据
        img_array=np.random.randn(1,32,77,3)
        #数组形式数据转为列表格式
        img_list=img_array.tolist()
        json_data={
            'instances':img_list
        }
    
        url='http://localhost:9501/v1/models/hebei:predict'
        res=requests.post(url=url,json=json_data)
        if res.status_code==200:
            #对模型的预测结果进行处理
            predictions=json.loads(res.text).get('predictions')
            if predictions:
                y_pred=np.array(predictions)
                print(y_pred.shape)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    如上所示,因为对于hebei模型的输入图片数据格式形状为(1,32,77,3),在代码里构造了一个这种数据,在使用模型进行预测验证码图片时,这个地方传入真实图片的矩阵数据即可。运行结果如下:
    在这里插入图片描述

  • 相关阅读:
    十、缓存与数据库一致性
    i711800h和i511320h哪个好
    14.Vue3过渡和动画实现
    Kettle(二):连接SQL Server数据库
    shadow复习之planar shadow
    详解TCP/IP协议第二篇:OSI参考模型详解
    C++STL详解(六)unordered_set&unordered_map介绍
    Java | 多线程综合练习
    车载电子电器架构 —— 售后诊断开发
    Arcgis 10.2.2 | arcgis license server无法启动的解决办法
  • 原文地址:https://blog.csdn.net/qq_37781464/article/details/126124501