TensorFlow Serving:深度学习模型在生产环境的部署&上线

20 篇文章 2 订阅
16 篇文章 4 订阅

TensorFlow Serving简单来说就是一个适合在生产环境中对tensorflow深度学习模型进行部署,然后可以非常方便地通过restful形式的接口进行访问。

除此之外,它拥有许多有点:

  1. 支持配置文件的定期轮询更新(periodically poll for updated),无需重新启动;
  2. 优秀的模型版本控制;
  3. 支持并发;
  4. 支持批处理;
  5. 基于docker,部署简单。

(这些优点我们在下面会逐一提到)

安装

官方极力推荐通过docker的方式进行安装,所以,

  1. 首先我们需要进行docker的安装

  2. 拉取TensorFlow Serving的docker镜像和仓库

    docker pull tensorflow/serving
    
  3. 使用tensorflow官方自带的模型进行测试。克隆相关的git仓库

    git clone https://github.com/tensorflow/serving
    
  4. 启动TensorFlow Serving的docker容器,开启tensorflow模型的接口服务

    TESTDATA="$(pwd)/serving/tensorflow_serving/servables/tensorflow/testdata"
    docker run -t --rm -p 8501:8501 \
        -v "$TESTDATA/saved_model_half_plus_two_cpu:/models/half_plus_two" \
        -e MODEL_NAME=half_plus_two \
        tensorflow/serving &
    
  5. 最后,我们就可以访问模型的接口了(该demo模型是一个简单的对输入的一半加上2)

    (接口地址:http://localhost:8501/v1/models/half_plus_two:predict

    参数:{“instances”: [1.0, 2.0, 5.0]})

    curl -d '{"instances": [1.0, 2.0, 5.0]}' \
        -X POST http://localhost:8501/v1/models/half_plus_two:predict
    

个性定制模型

保存pb模型

"""
将计算图以pb格式进行保存,用于tf-serving
"""
import tensorflow.compat.v1 as tf
# import tensorflow as tf

# tf2,否则placeholde会报错
tf.disable_eager_execution()

############# 在这里定义你的模型  ###########
x1 = tf.placeholder(tf.float32, [None], name='x1')
inputs_id = tf.placeholder(tf.int32, [None], name='x2')

out = tf.add(tf.multiply(x1, 0.5), 2)

embedding = tf.get_variable("embedding_table", shape=[100, 10])
pre = tf.nn.embedding_lookup(embedding, inputs_id)
############# 在这里定义你的模型  ###########

sess = tf.Session()
sess.run(tf.global_variables_initializer())

# 将张量转化为tensor_info
tensor_info_x1 = tf.saved_model.utils.build_tensor_info(x1)
tensor_info_inputs_id = tf.saved_model.utils.build_tensor_info(inputs_id)
tensor_info_out = tf.saved_model.utils.build_tensor_info(out)
tensor_info_pre = tf.saved_model.utils.build_tensor_info(pre)

# 创建SavedModelBuilder,指定保存路径
builder = tf.saved_model.builder.SavedModelBuilder("serving-model/1")
# 定义签名,在这里指定接口的输入以及返回
# 接口传参:{"instances": [{"x1": [1.0, 2.0, 5.0],"inputs_id": [1, 2, 3]}]}
# 必须将输入参数传递给"instances",否则接口不通过
# 返回:{"predictions":[{"out":......., "pre":......}]}
prediction_signature = (
  tf.saved_model.signature_def_utils.build_signature_def(
      inputs={'x1': tensor_info_x1, "inputs_id": tensor_info_inputs_id},
      outputs={'out': tensor_info_out, "pre": tensor_info_pre},
      method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
# 模型保存
legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
builder.add_meta_graph_and_variables(
    sess, [tf.saved_model.tag_constants.SERVING],
    signature_def_map={
        # 'predict_images':
        #     prediction_signature,
        # tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
        #     classification_signature,
        tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            prediction_signature,
    },
    legacy_init_op=legacy_init_op)

builder.save()

print('Done exporting!')

模型的保存格式如下:

一个saved_model.pb文件和variables文件夹。

这里需要注意:假如我们想要将模型保存在/tmp/model目录下,那么必须要创建一个版本号目录,如版本号为“1”,那么模型就应保存在/tmp/model/1目录下

在这里插入图片描述

部署上线

此时,我们仅仅需要执行一个docker命令即可实现模型的部署上线了

docker run -p 8501:8501 \
--mount type=bind,source=/tmp/model,target=/models/myserving \
-e MODEL_NAME=myserving -t tensorflow/serving &

解释一下:

  1. -p 8501:8501指容器中服务的端口为8501,然后映射到主机的8501端口(前为主机)
  2. –mount type=bind,source=/tmp/model,target=/models/myserving:将主机的/tmp/model目录挂载到容器/models/myserving目录,此时如果主机该目录下发生改动,那么容器也会随着改变。
  3. -e MODEL_NAME=myserving:将部署的模型命名为:myserving
  4. -t tensorflow/serving:以tensorflow/serving镜像启动该容器

接口访问

模型部署上线之后,就可以通过接口进行访问了。

接口地址:http://localhost:8501/v1/models/myserving:predict

参数为:{“instances”: [{“x1”: [1.0, 2.0, 5.0],“inputs_id”: [1, 2, 3]}]}

模型控制

前面我们提到,TensorFlow Serving有着优秀的模型版本控制功能。

默认最新

首先,TensorFlow Serving默认是加载最大版本号的模型。例如,上面我们部署了一个版本号为“1”的模型,如果之后模型又进行更新,版本号升级为“2”,那么仅需要将新的模型拷贝到相同的目录下即可。

比如,这个时候就有两个模型/tmp/model/1和/tmp/model/2,TensorFlow Serving会默认加载版本号“2”的模型。

自定义版本

如果我们想要多个版本的模型同时存在,并且多个模型同时部署,那么也是可以实现的。

在/tmp/model下创建一个models.config文件,以protocol的形式写入以下内容

model_config_list {
  config {
    name: 'myserving'
    base_path: '/models/myserving/'
    model_platform: 'tensorflow'
    model_version_policy {
      specific {
        versions: 1
        versions: 2
      }
    }
    version_labels {
      key: 'stable'
      value: 1
    }
    version_labels {
      key: 'canary'
      value: 2
    }
  }
  config {
    name: 'model2'
    base_path: '/models/model2/'
    model_platform: 'tensorflow'
  }
}

可以看到,里面有两个config,意味着我们同时上线两个模型。

看第一个config:name为模型的名称,base_path为容器中模型的位置,model_platform就设置为tensorflow即可;

model_version_policy不加的话就是默认最新的版本控制策略。specific指定上线的版本,version_labels将版本号映射为对应的key,如stable对应版本号“1”的模型。

然后,在启动容器服务的时候,需要指定配置文件路径,

docker run -p 8501:8501 \
--mount type=bind,source=/tmp/model,target=/models/myserving \
-e MODEL_NAME=myserving -t tensorflow/serving \
--model_config_file=/models/models.config \
--allow_version_labels_for_unavailable_models=true

(如果不加这个配置项–allow_version_labels_for_unavailable_models=true,那么版本号和key的映射关系不能在启动时设置,只能在启动后才能进行设置)

那么,如果访问第一个模型的stable版本,地址则为:

http://localhost:8501/v1/models/myserving/labels/stable:predict

或者

http://localhost:8501/v1/models/myserving/versions/1:predict

官方推荐第一种。

轮询更新

想要对模型的配置文件进行定期轮询更新的话,只需要加上配置项

--model_config_file_poll_wait_seconds=60

这里是设置为60秒一次。

并发和批处理

批处理简单来说就是可以将多个接口的请求合并一个batch,然后模型计算完成之后一起返回。

在/tmp/model下创建一个batcj.config文件,仍是protocol的形式写入以下内容

max_batch_size { value: 128 }
batch_timeout_micros { value: 1000 }
max_enqueued_batches { value: 1000000 }
num_batch_threads { value: 8 }

max_batch_size:一个批次允许的最大请求数量

batch_timeout_micros:合并一个批次等待的最长时间,即使该批次的数量未达到max_batch_size,也会立即进行计算(单位是微秒)

max_enqueued_batches:队列的最大数量

num_batch_threads:线程数,在这里体现并发。
这些都是全局设置,针对所有版本的模型!!!

那么,此时启动容器服务的命令就变成

docker run -p 8501:8501 \
--mount type=bind,source=/tmp/model,target=/models/myserving \
-e MODEL_NAME=myserving -t tensorflow/serving \
--model_config_file=/models/models.config \
--allow_version_labels_for_unavailable_models=true \
--enable_batching=true \
--batching_parameters_file=/models/batch.config
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值