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

秒速五厘米 2022-12-24 00:35 288阅读 0赞

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

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

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

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

安装

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

  1. 首先我们需要进行docker的安装。
  2. 拉取TensorFlow Serving的docker镜像和仓库

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

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

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

    (接口地址:http://localhost:8501/v1/models/half\_plus\_two:predict

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

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

个性定制模型

保存pb模型

  1. """ 将计算图以pb格式进行保存,用于tf-serving """
  2. import tensorflow.compat.v1 as tf
  3. # import tensorflow as tf
  4. # tf2,否则placeholde会报错
  5. tf.disable_eager_execution()
  6. ############# 在这里定义你的模型 ###########
  7. x1 = tf.placeholder(tf.float32, [None], name='x1')
  8. inputs_id = tf.placeholder(tf.int32, [None], name='x2')
  9. out = tf.add(tf.multiply(x1, 0.5), 2)
  10. embedding = tf.get_variable("embedding_table", shape=[100, 10])
  11. pre = tf.nn.embedding_lookup(embedding, inputs_id)
  12. ############# 在这里定义你的模型 ###########
  13. sess = tf.Session()
  14. sess.run(tf.global_variables_initializer())
  15. # 将张量转化为tensor_info
  16. tensor_info_x1 = tf.saved_model.utils.build_tensor_info(x1)
  17. tensor_info_inputs_id = tf.saved_model.utils.build_tensor_info(inputs_id)
  18. tensor_info_out = tf.saved_model.utils.build_tensor_info(out)
  19. tensor_info_pre = tf.saved_model.utils.build_tensor_info(pre)
  20. # 创建SavedModelBuilder,指定保存路径
  21. builder = tf.saved_model.builder.SavedModelBuilder("serving-model/1")
  22. # 定义签名,在这里指定接口的输入以及返回
  23. # 接口传参:{"instances": [{"x1": [1.0, 2.0, 5.0],"inputs_id": [1, 2, 3]}]}
  24. # 必须将输入参数传递给"instances",否则接口不通过
  25. # 返回:{"predictions":[{"out":......., "pre":......}]}
  26. prediction_signature = (
  27. tf.saved_model.signature_def_utils.build_signature_def(
  28. inputs={ 'x1': tensor_info_x1, "inputs_id": tensor_info_inputs_id},
  29. outputs={ 'out': tensor_info_out, "pre": tensor_info_pre},
  30. method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME))
  31. # 模型保存
  32. legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
  33. builder.add_meta_graph_and_variables(
  34. sess, [tf.saved_model.tag_constants.SERVING],
  35. signature_def_map={
  36. # 'predict_images':
  37. # prediction_signature,
  38. # tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
  39. # classification_signature,
  40. tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
  41. prediction_signature,
  42. },
  43. legacy_init_op=legacy_init_op)
  44. builder.save()
  45. print('Done exporting!')

模型的保存格式如下:

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

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

在这里插入图片描述

部署上线

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

  1. docker run -p 8501:8501 \
  2. --mount type=bind,source=/tmp/model,target=/models/myserving \
  3. -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的形式写入以下内容

  1. model_config_list {
  2. config {
  3. name: 'myserving'
  4. base_path: '/models/myserving/'
  5. model_platform: 'tensorflow'
  6. model_version_policy {
  7. specific {
  8. versions: 1
  9. versions: 2
  10. }
  11. }
  12. version_labels {
  13. key: 'stable'
  14. value: 1
  15. }
  16. version_labels {
  17. key: 'canary'
  18. value: 2
  19. }
  20. }
  21. config {
  22. name: 'model2'
  23. base_path: '/models/model2/'
  24. model_platform: 'tensorflow'
  25. }
  26. }

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

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

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

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

  1. docker run -p 8501:8501 \
  2. --mount type=bind,source=/tmp/model,target=/models/myserving \
  3. -e MODEL_NAME=myserving -t tensorflow/serving \
  4. --model_config_file=/models/models.config \
  5. --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

官方推荐第一种。

轮询更新

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

  1. --model_config_file_poll_wait_seconds=60

这里是设置为60秒一次。

并发和批处理

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

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

  1. max_batch_size { value: 128 }
  2. batch_timeout_micros { value: 1000 }
  3. max_enqueued_batches { value: 1000000 }
  4. num_batch_threads { value: 8 }

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

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

max_enqueued_batches:队列的最大数量

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

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

  1. docker run -p 8501:8501 \
  2. --mount type=bind,source=/tmp/model,target=/models/myserving \
  3. -e MODEL_NAME=myserving -t tensorflow/serving \
  4. --model_config_file=/models/models.config \
  5. --allow_version_labels_for_unavailable_models=true \
  6. --enable_batching=true \
  7. --batching_parameters_file=/models/batch.config

发表评论

表情:
评论列表 (有 0 条评论,288人围观)

还没有评论,来说两句吧...

相关阅读