kubeflow系列(三):模型即服务,关于tensorflow serving的使用

简介: 模型即服务(Model as a service)作为算法模型最优雅的价值变现,也是最佳的tf算法部署实践,Tensorflow Serving 作为Tensorflow官方的模型部署方案,也是kubeflow默认的一种tensorflow部署形式,本文介绍如何用 Tensorflow Serving 部署算法模型。

kubeflow 中采用了 tensorflow serving 作为官方的tensorflow模型接口, TensorFlow Serving是GOOGLE开源的一个服务系统,适用于部署机器学习模型,灵活、性能高、可用于生产环境。 TensorFlow Serving可以轻松部署新算法和实验,同时保持相同的服务器架构和API。

Tensorflow Serving 直接加载模型即可生成接口,不过 serving 支持的模型只有 SaveModel,因此这里主要介绍 SaveModel。

SaveModel

SaveModel 是一种专门用于tf模型 拓扑结构(topology)权重(weights) ,基于 SaveModel 不需要运行原始的模型构建代码,这样非常利于共享或部署模型,因此一般模型部署都用 SaveModel

  • 拓扑结构(Topology): 这是一个描述模型结构的文件(例如它使用的了哪些操作)。它包含对存储在外部的模型权重的引用。
  • 权重(Weights): 这些是以有效格式存储给定模型权重的二进制文件。它们通常存储在与拓扑结构相同的文件夹中。

SaveModel文件目录:

assets  saved_model.pb  variables

查看MetaGraphDefsSignatureDefs:

saved_model_cli show --dir <SaveModel路径> --all

生成模型需要模型的MetaGraphDefsSignatureDefsMetaGraphDefs就是我们常见的meta graph,其中包含了四种主要的信息:

  • MetaInfoDef: 存放了一些元信息,例如版本和其他用户信息;
  • GraphDef: 描述的Graph中序列化得到的图,由Protocol Buffer组成;
  • SaverDef: 图的Saver信息,例如最多同时保存的checkpoint数量,需要保存的Tensor名字等,不保存Tensor中的实际内容;
  • CollectionDef: 任何需要特殊注意的python对象,需要特殊的标注以方便import_meta_graph后取回,如"prediction"。

SignatureDefs则是模型的签名定义,定义了 输入 和 输出函数`。

SignatureDefs

SignatureDef 定义了 TensorFlow graph 计算的签名,定义了 输入 和 输出函数,SignatureDef 结构 :

inputs as a map of string to TensorInfo.

outputs as a map of string to TensorInfo.
method_name (which corresponds to a supported method name in the loading tool/system).

Classification SignatureDef例子

必须要一个输入 Tensors inputs 和两个输出Tensors: classesscores

signature_def: {
  key  : "my_classification_signature"
  value: {
    inputs: {
      key  : "inputs"
      value: {
        name: "tf_example:0"
        dtype: DT_STRING
        tensor_shape: ...
      }
    }
    outputs: {
      key  : "classes"
      value: {
        name: "index_to_string:0"
        dtype: DT_STRING
        tensor_shape: ...
      }
    }
    outputs: {
      key  : "scores"
      value: {
        name: "TopKV2:0"
        dtype: DT_FLOAT
        tensor_shape: ...
      }
    }
    method_name: "tensorflow/serving/classify"
  }
}

Predict SignatureDef例子

signature_def: {
  key  : "my_prediction_signature"
  value: {
    inputs: {
      key  : "images"
      value: {
        name: "x:0"
        dtype: ...
        tensor_shape: ...
      }
    }
    outputs: {
      key  : "scores"
      value: {
        name: "y:0"
        dtype: ...
        tensor_shape: ...
      }
    }
    method_name: "tensorflow/serving/predict"
  }
}

Regression SignatureDef例子

signature_def: {
  key  : "my_regression_signature"
  value: {
    inputs: {
      key  : "inputs"
      value: {
        name: "x_input_examples_tensor_0"
        dtype: ...
        tensor_shape: ...
      }
    }
    outputs: {
      key  : "outputs"
      value: {
        name: "y_outputs_0"
        dtype: DT_FLOAT
        tensor_shape: ...
      }
    }
    method_name: "tensorflow/serving/regress"
  }
}

生成 SaveModel 文件

生成 SaveModel文件的方式:

  • (1)tf.saved_model # 最直接简单
  • (2)Estimator的export_savedmodel # 高级API Estimator模型导出
classifier = classifier = tf.estimator.Estimator(
        model_fn=conv_model, model_dir=args.tf_model_dir,
        config=training_config, params=model_params)
classifier.export_savedmodel(args.tf_export_dir, serving_input_receiver_fn=serving_fn)
  • (3)keras.Model.save(output_path)

将 checkpoint 模型文件 改为 SaveModel 文件

import sys, os, io
import tensorflow as tf

model_version = "1"
model_name = "object"

def restore_and_save(input_checkpoint, export_path_base):
    checkpoint_file = tf.train.latest_checkpoint(input_checkpoint)
    graph = tf.Graph()

    with graph.as_default():
        session_conf = tf.ConfigProto(allow_soft_placement=True, log_device_placement=False)
        sess = tf.Session(config=session_conf)

        with sess.as_default():
            # 载入保存好的meta graph,恢复图中变量,通过SavedModelBuilder保存可部署的模型
            saver = tf.train.import_meta_graph("{}.meta".format(checkpoint_file))
            saver.restore(sess, checkpoint_file)
            print ("name scope: ",graph.get_name_scope())

            export_path_base = export_path_base
            export_path = os.path.join(
                tf.compat.as_bytes(export_path_base),
                tf.compat.as_bytes(model_name+"/"+model_version))
            print('Exporting trained model to', export_path)

            builder = tf.saved_model.builder.SavedModelBuilder(export_path)
            # 模型的各种operator 可以通过 graph.get_operations() 获得
            # input 为输入层operator
            inputs = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("Placeholder").outputs[0])
            print(inputs)
            # output 为输出层operator, 这里的输出层 type 为 Softmax
            outputs = tf.saved_model.utils.build_tensor_info(graph.get_operation_by_name("final_result").outputs[0])
            print(outputs)
            """
            signature_constants:SavedModel保存和恢复操作的签名常量。
            在序列标注的任务中,这里的method_name是"tensorflow/serving/predict"
            """
            # 定义模型的输入输出,建立调用接口与tensor签名之间的映射
            labeling_signature = (
                tf.saved_model.signature_def_utils.build_signature_def(
                    inputs={
                        "Placeholder":
                            inputs,
                    },
                    outputs={
                        "final_result":
                            outputs,
                    },
                    method_name="tensorflow/serving/predict"))
            
            """
            tf.group : 创建一个将多个操作分组的操作,返回一个可以执行所有输入的操作
            """
            legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')

            """
            add_meta_graph_and_variables:建立一个Saver来保存session中的变量,
                                          输出对应的原图的定义,这个函数假设保存的变量已经被初始化;
                                          对于一个SavedModelBuilder,这个API必须被调用一次来保存meta graph;
                                          对于后面添加的图结构,可以使用函数 add_meta_graph()来进行添加
            """
            # 建立模型名称与模型签名之间的映射
            builder.add_meta_graph_and_variables(
                sess, [tf.saved_model.tag_constants.SERVING],
                signature_def_map={
                    tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
                       labeling_signature},
                legacy_init_op=legacy_init_op
            )
            builder.save()

            print("Build Done")

Run server

生成好 SaveModel 模型文件,就可以直接运行 serving 来实现模型服务:

(1)用DOCKER运行:

docker run --rm -it -p 8500:8500 \
--mount type=bind,source=/root/inception/models,target=/models \
-e MODEL_NAME=1 tensorflow/serving

挂载的默认目录为两级目录:./<模型名称>/<版本号>/save_model.pb, 版本号必须为数字。

(2)或者可以用k8s运行deployment(kubeflow):

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: inception
  name: inception-service-local
  namespace: kubeflow
spec:
  template:
    metadata:
      labels:
        app: inception
        version: v1
    spec:
      containers:
      - args:
        - --port=9000
        - --rest_api_port=8500
        - --model_name=1
        - --model_base_path=/mnt/export
        command:
        - /usr/bin/tensorflow_model_server
        env:
        - name: modelBasePath
          value: /mnt/export
        image: tensorflow/serving:1.11.1
        imagePullPolicy: IfNotPresent
        livenessProbe:
          initialDelaySeconds: 30
          periodSeconds: 30
          tcpSocket:
            port: 9000
        name: mnist
        ports:
        - containerPort: 9000
        - containerPort: 8500
        volumeMounts:
        - mountPath: /mnt
          name: local-storage

构建请求测试

测试模型接口

import requests
from PIL import Image
import numpy as np

filename = "./CES/astra_mini/1576210854440.png" # 图片
img=Image.open(filename)   
img_arr=np.array(img,dtype=np.uint8)
print(img_arr.shape) # (299, 299, 3)

data = json.dumps({"instances": [img_arr.tolist()]})
headers = {"content-type": "application/json"}
json_response = requests.post('http://127.0.0.1:8501/v1/models/object:predict', data=data, headers=headers)
print(json_response.text) 

参考文献

https://www.tensorflow.org/tfx/tutorials/serving/rest_simple

目录
相关文章
|
29天前
|
机器学习/深度学习 人工智能 PyTorch
AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比
AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比
53 1
|
11天前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
34 0
|
11天前
|
C# 开发者 前端开发
揭秘混合开发新趋势:Uno Platform携手Blazor,教你一步到位实现跨平台应用,代码复用不再是梦!
【8月更文挑战第31天】随着前端技术的发展,混合开发日益受到开发者青睐。本文详述了如何结合.NET生态下的两大框架——Uno Platform与Blazor,进行高效混合开发。Uno Platform基于WebAssembly和WebGL技术,支持跨平台应用构建;Blazor则让C#成为可能的前端开发语言,实现了客户端与服务器端逻辑共享。二者结合不仅提升了代码复用率与跨平台能力,还简化了项目维护并增强了Web应用性能。文中提供了从环境搭建到示例代码的具体步骤,并展示了如何创建一个简单的计数器应用,帮助读者快速上手混合开发。
22 0
|
11天前
|
开发者 算法 虚拟化
惊爆!Uno Platform 调试与性能分析终极攻略,从工具运用到代码优化,带你攻克开发难题成就完美应用
【8月更文挑战第31天】在 Uno Platform 中,调试可通过 Visual Studio 设置断点和逐步执行代码实现,同时浏览器开发者工具有助于 Web 版本调试。性能分析则利用 Visual Studio 的性能分析器检查 CPU 和内存使用情况,还可通过记录时间戳进行简单分析。优化性能涉及代码逻辑优化、资源管理和用户界面简化,综合利用平台提供的工具和技术,确保应用高效稳定运行。
25 0
|
11天前
|
前端开发 开发者 设计模式
揭秘Uno Platform状态管理之道:INotifyPropertyChanged、依赖注入、MVVM大对决,帮你找到最佳策略!
【8月更文挑战第31天】本文对比分析了 Uno Platform 中的关键状态管理策略,包括内置的 INotifyPropertyChanged、依赖注入及 MVVM 框架。INotifyPropertyChanged 方案简单易用,适合小型项目;依赖注入则更灵活,支持状态共享与持久化,适用于复杂场景;MVVM 框架通过分离视图、视图模型和模型,使状态管理更清晰,适合大型项目。开发者可根据项目需求和技术栈选择合适的状态管理方案,以实现高效管理。
23 0
|
22天前
|
缓存 Linux TensorFlow
更改 TensorFlow Hub 模型的缓存位置
更改 TensorFlow Hub 模型的缓存位置
27 0
|
3月前
|
机器学习/深度学习 人工智能 算法
海洋生物识别系统+图像识别+Python+人工智能课设+深度学习+卷积神经网络算法+TensorFlow
海洋生物识别系统。以Python作为主要编程语言,通过TensorFlow搭建ResNet50卷积神经网络算法,通过对22种常见的海洋生物('蛤蜊', '珊瑚', '螃蟹', '海豚', '鳗鱼', '水母', '龙虾', '海蛞蝓', '章鱼', '水獭', '企鹅', '河豚', '魔鬼鱼', '海胆', '海马', '海豹', '鲨鱼', '虾', '鱿鱼', '海星', '海龟', '鲸鱼')数据集进行训练,得到一个识别精度较高的模型文件,然后使用Django开发一个Web网页平台操作界面,实现用户上传一张海洋生物图片识别其名称。
156 7
海洋生物识别系统+图像识别+Python+人工智能课设+深度学习+卷积神经网络算法+TensorFlow
|
3月前
|
机器学习/深度学习 人工智能 算法
【乐器识别系统】图像识别+人工智能+深度学习+Python+TensorFlow+卷积神经网络+模型训练
乐器识别系统。使用Python为主要编程语言,基于人工智能框架库TensorFlow搭建ResNet50卷积神经网络算法,通过对30种乐器('迪吉里杜管', '铃鼓', '木琴', '手风琴', '阿尔卑斯号角', '风笛', '班卓琴', '邦戈鼓', '卡萨巴', '响板', '单簧管', '古钢琴', '手风琴(六角形)', '鼓', '扬琴', '长笛', '刮瓜', '吉他', '口琴', '竖琴', '沙槌', '陶笛', '钢琴', '萨克斯管', '锡塔尔琴', '钢鼓', '长号', '小号', '大号', '小提琴')的图像数据集进行训练,得到一个训练精度较高的模型,并将其
50 0
【乐器识别系统】图像识别+人工智能+深度学习+Python+TensorFlow+卷积神经网络+模型训练
|
2天前
|
机器学习/深度学习 数据挖掘 TensorFlow
从数据小白到AI专家:Python数据分析与TensorFlow/PyTorch深度学习的蜕变之路
【9月更文挑战第10天】从数据新手成长为AI专家,需先掌握Python基础语法,并学会使用NumPy和Pandas进行数据分析。接着,通过Matplotlib和Seaborn实现数据可视化,最后利用TensorFlow或PyTorch探索深度学习。这一过程涉及从数据清洗、可视化到构建神经网络的多个步骤,每一步都需不断实践与学习。借助Python的强大功能及各类库的支持,你能逐步解锁数据的深层价值。
10 0
|
11天前
|
持续交付 测试技术 jenkins
JSF 邂逅持续集成,紧跟技术热点潮流,开启高效开发之旅,引发开发者强烈情感共鸣
【8月更文挑战第31天】在快速发展的软件开发领域,JavaServer Faces(JSF)这一强大的Java Web应用框架与持续集成(CI)结合,可显著提升开发效率及软件质量。持续集成通过频繁的代码集成及自动化构建测试,实现快速反馈、高质量代码、加强团队协作及简化部署流程。以Jenkins为例,配合Maven或Gradle,可轻松搭建JSF项目的CI环境,通过JUnit和Selenium编写自动化测试,确保每次构建的稳定性和正确性。
36 0

热门文章

最新文章