用Docker容器自带的tensorflow serving部署模型对外服务

本文分享了安装TensorFlow Serving的迂回策略,即拉取已安装该服务的Docker镜像并替换自带模型。详细介绍了拉取镜像、获取例子模型、运行部署、调用服务、查看模型目录结构、替换模型、调用模型、参数预处理等步骤,还给出了参考地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相信很多人和我一样,在试图安装tensorflow serving的时候,翻遍了网上的博客和官网文档,安装都是以失败而告终,我也是一样,这个问题折磨了我两个星期之久,都快放弃了。幸运的是在同事的建议下,我采用了一种迂回的策略安装成功了。

 

我们采用的策略是:

        pull一个已经安装好了tensorflow serving的docker镜像,替换它自带的一些模型为我们自己的模型。

 

步骤:

1、拉取带tensorflow serving的docker镜像,这样我们服务器上就有了一个安装了ModelServer的docker容器, 这个容器就可以看做一台虚拟机,这个虚拟机上已经安装好了tensorflow serving,环境有了,就可以用它来部署我们的模型了。注意这个拉取下来后不是直接放在当前目录的,而是docker默认存储的路径,这个是个docker容器,和第2步clone下来的不是同一个东西

$docker pull tensorflow/serving
 

2、获取例子模型:(当然,也可以直接用上面容器中自带的例子),当然这里是直接拉取了tensorflow serving的源码,源码中有一些训练好的例子模型


 
  1. $cd /root/software/
  2. $git clone https: //github.com/tensorflow/serving

3、用第一步拉取的docker容器运行例子模型

第2步中clone下来的serving源码中有这样一个训练好的例子模型,路径为:

/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu
 

现在我们就要用第1步拉下来的docker容器来运行部署这个例子模型


 
  1. $docker run -p 8501:8501 \
  2. --mount type= bind,\
  3. source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu,\
  4. target=/models/half_plus_two \
  5. -e MODEL_NAME=half_plus_two -t tensorflow/serving &

参数说明:


 
  1. --mount: 表示要进行挂载
  2. source: 指定要运行部署的模型地址, 也就是挂载的源,这个是在宿主机上的模型目录
  3. target: 这个是要挂载的目标位置,也就是挂载到docker容器中的哪个位置,这是docker容器中的目录
  4. -t: 指定的是挂载到哪个容器
  5. -p: 指定主机到docker容器的端口映射
  6. docker run: 启动这个容器并启动模型服务(这里是如何同时启动容器中的模型服务的还不太清楚)
  7. 综合解释:
  8. 将source目录中的例子模型,挂载到-t指定的docker容器中的target目录,并启动

这步注意,如果执行报错无法识别type=bind, 那应该是source的路径有问题

4、调用这个服务,这里用的http接口


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

得到的结果如下:

{ "predictions": [2.5, 3.0, 4.5] }
 

这就表明服务已经部署成功了,当然你也可以用requests来模型上述http请求

5、查看启动的这个模型的目录的结构

我们可以看到启动服务的命令有一个参数:

source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/saved_model_half_plus_two_cpu
 

这实际就是模型的位置, 我们进入到这个目录下(这个目录基于自己pull时所在的目录),可以看到里面是一个名为00000123的目录,这实际是模型的版本,再进入到这个目录下可以看到一个如下两个文件:

saved_model.pb, variables
 

variable目录下有如下两个文件:

variables.data-00000-of-00001, variables.index
 

6、用自己的模型替换上述half_plus_two模型

我在和saved_model_half_plus_two_cpu模型同级的目录下创建了一个文件夹,名为textcnnrnn, 这是我模型的名称,然后


 
  1. $cd textcnnrnn
  2. $mkdir 00000123
  3. $cd 00000123
  4. $mkdir variables
  5. $cd variables

我一开始是直接用的我之前训练好的模型放到了variables目录下,我训练好的模型包含如下几个文件:

best_validation.data-00000-of-00001  best_validation.index  best_validation.meta  checkpoint
 

相信大家都看出来了,这个是用这种方式保存的:


 
  1. saver = tf.train.Saver()
  2. saver.save(sess=session, save_path=save_path)

于是我激动的去重新启动我的模型,当然这里要修改模型的地址,我也把我的模型的名字改了下:

docker run -p 8501:8501 --mount source=/root/software/serving/tensorflow_serving/servables/tensorflow/testdata/textcnnrnn,type=bind,target=/models/find_lemma_category -e MODEL_NAME=find_lemma_category -t tensorflow/serving &
 

可是这个时候报错了,做法不对。下面是正确的做法。

其实仔细比较我的模型的几个文件和half_plus_two模型的下的文件的结构根本不一样,怎么办呢? 其实应该对模型的格式进行转换。 代码如下:


 
  1. # coding: utf-8
  2. from __future__ import print_function
  3. import pdb
  4. import time
  5. import os
  6. import tensorflow as tf
  7. import tensorflow.contrib.keras as kr
  8. from cnn_rnn_model import TCNNRNNConfig, TextCNNRNN
  9. save_path = 'model_saver/textcnnrnn/best_validation'
  10. try:
  11. bool(type(unicode))
  12. except NameError:
  13. unicode = str
  14. config = TCNNRNNConfig()
  15. def build_and_saved_wdl():
  16. model = TextCNNRNN(config) #我自己的模型结构是在这个类中定义的,基于自己的模型进行替换
  17. session = tf.Session()
  18. session.run(tf.global_variables_initializer())
  19. saver = tf.train.Saver()
  20. saver.restore(sess=session, save_path=save_path)
  21. # 将训练好的模型保存在model_name下,版本为2,当然你的版本可以随便写
  22. builder = tf.saved_model.builder.SavedModelBuilder( "./model_name/2")
  23. inputs = {
  24. #注意,这里是你预测模型的时候需要传的参数,调用模型的时候,传参必须和这里一致
  25. #这里的model.input_x和model.keep_prob就是模型里面定义的输入placeholder
  26. "input_x": tf.saved_model.utils.build_tensor_info(model.input_x),
  27. "keep_prob": tf.saved_model.utils.build_tensor_info(model.keep_prob)
  28. }
  29. #model.y_pred_cls是模型的输出, 预测的时候就是计算这个表达式
  30. output = { "output": tf.saved_model.utils.build_tensor_info(model.y_pred_cls)}
  31. prediction_signature = tf.saved_model.signature_def_utils.build_signature_def(
  32. inputs=inputs,
  33. outputs=output,
  34. method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME
  35. )
  36. builder.add_meta_graph_and_variables(
  37. session,
  38. [tf.saved_model.tag_constants.SERVING],
  39. {tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: prediction_signature}
  40. )
  41. builder.save()
  42. if __name__ == '__main__':
  43. build_and_saved_wdl()

执行后,会在当前目录下生成一个名称为./model_name/2的文件夹, 这个文件夹下的文件格式和halt_plus_two中的文件格式是一致的了,这下肯定没错了。

将./model_name/2文件夹下的内容拷贝到textcnnrnn/00000123目录下即可。

重新启动模型,这次启动成功了,没有报错,说明我们的模型已经被识别成功。

7、调用模型

咋调啊?咋传参数啊?懵逼,先看看调用自带的模型怎么传参数的吧:


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

看样子instances应该是参数的名字,于是我想看看tensorflow serving源码里面是怎么解析这个参数的,所以我在源码根目录下全局搜索了这个关键字,在根目录下搜索关键词instances:

$find . -name '*.*' | xargs grep -l instances
 

可以找到一个名为json_tensor.h的文件,这个文件详细介绍了不同的传参的方式:

instances是一个list,list中每个元素是一个待预测实例,每个实例里面是所有参数的值, 所以参数按照这种方式构造就可以了。

这里json.dumps的时候可能会遇到一个序列化的错误,原因是json.dumps对于含numpy.array类型的数据无法序列化, 可以构造一个编码器, 然后作为json.dumps参数:


 
  1. class NumpyEncoder(json.JSONEncoder):
  2. def default(self, obj):
  3. if isinstance(obj, np.ndarray):
  4. return obj.tolist()
  5. return json.JSONEncoder.default( self, obj)

 
  1. p_data = { "keep_prob": 1.0, "input_x": x_test[ 0]}
  2. param = { "instances": [p_data]}
  3. param = json.dumps(param, cls=NumpyEncoder)
  4. res = requests.post( 'http://localhost:8501/v1/models/find_lemma_category:predict', data=param)

这样就大功告成了!

这里还有一个地方需要注意:其实我的模型Input_x本身是直接可以接收多个实例的,也就是上面我的参数x_test是多个实例构造的参数,但是直接传入会出错,所以我只能传入一个实例x_test[0]。 如果想同时预测多个的话只能这样构造参数:


 
  1. data1 = { "keep_prob": 1.0, "input_x": x_test[ 0]}
  2. data2 = { "keep_prob": 1.0, "input_x": x_test[ 1]}
  3. data3 = { "keep_prob": 1.0, "input_x": x_test[ 2]}
  4. param = { "instances": [data1, data2, data3]}
  5. param = json.dumps(param, cls=NumpyEncoder)
  6. res = requests.post( 'http://localhost:8501/v1/models/find_lemma_category:predict', data=param)

8、参数要预处理怎么办?

假如我们需要在将参数输入模型之前做一些预处理怎么办?比如要对大段文本进行分词等等。

解决办法: 部署一个中转服务,我采用的策略是用tornado再部署一个服务,这个服务负责对业务方传输过来的参数进行预处理,处理成模型需要的格式后,再传输给模型, 所以我的结构是这样的:

业务方 ==>  tornado服务(参数预处理) ==> 模型(tensorflow serving服务)

这里面的两次远程调用都是http协议。

 

参考地址:

    https://www.tensorflow.org/serving/docker

    https://www.jianshu.com/p/2fffd0e332bc

 

 

 

 

 

<think>嗯,用户想了解如何用云服务部署大型机器学习模型。首先,我需要确定用户的需求是什么。他们可能已经有一定的机器学习基础,现在想要将模型部署到云端,可能是为了生产环境的应用,需要处理高并发或大规模数据。接下来,我得回忆一下常见的云平台,比如AWS、GCP、Azure,这些都是主流的选择。然后,用户可能需要具体的步骤,比如环境准备、模型优化、选择部署工具等等。 用户提到的引用里提到了TensorFlow ServingDocker,这些应该是关键点。TensorFlow Serving适合部署TensorFlow模型,而Docker能解决环境依赖问题。另外,云平台通常有专门的机器学习服务,比如SageMaker、AI Platform,这些可能简化部署流程。 然后,用户可能需要考虑模型优化,比如量化、剪枝,这些技术能减少模型大小,提高推理速度。还有,分布式部署和自动扩展对于处理高流量很重要,可能需要用到Kubernetes或者云平台自带的扩展功能。 监控和维护也是部署后不可忽视的部分,需要集成日志和监控工具,比如CloudWatch或者Prometheus。此外,模型版本管理和回滚策略也是必要的,确保更新时不会影响现有服务。 用户可能还需要具体的教程链接,比如官方文档或实战项目,这能帮助他们一步步操作。同时,生成的问题需要考虑他们后续可能遇到的挑战,比如性能优化、成本控制、安全性等,这些都是部署大型模型时常见的问题。 需要确保回答结构清晰,分步骤说明,并且引用相关的资料。还要检查是否符合之前的系统级指令,比如数学公式的格式、LaTeX正确性,以及生成相关问题。最后,保持语言口语化,避免使用Markdown,让回答更自然易懂。</think>### 分步指南:利用云服务部署大规模机器学习模型 #### 一、部署前准备 1. **模型优化与压缩** 大型模型(如BERT、GPT)需通过量化、剪枝或知识蒸馏等技术降低计算和存储成本。例如,使用TensorFlow的$model\_optimization$工具可实现8位量化: ```python import tensorflow_model_optimization as tfmot quantized_model = tfmot.quantization.keras.quantize_model(original_model) ``` 2. **基础设施选择** - **云平台对比**: - AWS SageMaker:适合端到端流水线(训练-部署-监控)[^2] - Google AI Platform:集成TPU加速,适合Transformer类模型 - Azure ML:与微软生态深度整合,支持混合云部署 #### 二、核心部署流程(以AWS为例) 1. **容器化封装** 使用Docker打包模型和依赖环境: ```dockerfile FROM tensorflow/serving:latest-gpu COPY /model /models/my_model/1 ENV MODEL_NAME=my_model ``` 2. **云资源配置** - **计算实例**:选择GPU加速型(如AWS p3.8xlarge) - **存储**:挂载高IOPS SSD卷存放模型权重(>100GB时建议) - **网络**:启用VPC私有子网保障数据安全 3. **弹性部署模式** ```bash # 使用Kubernetes实现自动扩缩容 kubectl autoscale deployment model-serving --cpu-percent=70 --min=3 --max=10 ``` 通过HPA(Horizontal Pod Autoscaler)应对流量波动[^1] #### 三、性能调优关键参数 $$ QPS = \frac{N_{workers} \times Batch\_size}{Latency_{avg}} $$ 需平衡$Batch\_size$与显存占用,建议通过压力测试确定最优值 #### 四、运维监控体系 1. **指标采集** - Prometheus采集GPU利用率(>80%告警) - ELK Stack记录API调用日志 2. **模型版本管理** 使用MLflow实现模型版本回滚: ```python mlflow.register_model("runs:/<run_id>/model", "ProductionModel") ``` #### 五、成本控制策略 | 资源类型 | 按需实例 | Spot实例 | 节省计划 | |----------|----------|----------|----------| | GPU实例 | $4.56/hr | $1.23/hr | 预付折扣 | 推荐使用Spot实例运行非关键任务,结合Auto Scaling降低成本[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值