添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

docker:

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

tf-server:

Tensorflow Serving 是一个生产级别的灵活高性能的机器学习模型服务系统。

二.docker环境配置

1.docker安装(要求docker版本) 在Ubuntu中安装Docker和docker的使用 - JaryTom - 博客园 (本人虚拟机用的是ubuntu,其他系统可参考网上教程)

执行sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && curl -fsSL https: //download . docker.com /linux/ubuntu/gpg | sudo apt-key add - && sudo add-apt-repository "deb [arch=amd64] 阿里云开源镜像站资源目录 $(lsb_release -cs) stable" && sudo apt-get update && sudo apt-get install -y docker-ce

测试 Docker 是否安装成功:

$ sudo docker run hello-world

以下为命令解释

$ sudo apt-get remove docker docker-engine docker.io containerd runc
更新 apt 包索引,安装 apt 依赖包:
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
添加 Docker 的官方 GPG 密钥:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
使用以下指令设置稳定版仓库:
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
更新 apt 包索引,并安装最新版本的 Docker Engine-Community 和 containerd:
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
可使用apt-cache madison docker-ce命令查看仓库,安装指定版本;

2.拉取tensorflow/serving镜像(由于单机训练的tf为1.12.0,所以pull 1.12.0的tf-serving镜像):

注:注意版本尽量与模型代码一致,防止api不同导致报错

$ sudo docker pull tensorflow/serving:1.12.0

三.tensorflow模型保存(saved_model格式) 如果仅是部署,可忽略该部分

模型同学离线训练模型使用tensorflow api将模型保存为saved_model格式。一个文件 里面包含pb(protocol buffer)文件 和一个文件夹 variables,这样的模型保存方式可以构建TensorFlow serving 服务。

具体的就是是利用docker来构建TensorFlow serving 的服务端,在前述环境配置操作中已完成,然后在客户端通过grpc来连接。

代码示例(tensoflow版本很多,根据具体版本api可能有调整,需要进行调试):

tensorflow-saved_mdoel保存

def save_saved_model(model_train,sess,model_dir):
    builder = tf.saved_model.builder.SavedModelBuilder(model_dir)
    # 构建 signature  为了不知道tensor name的情况,run对应的tensor
    signature = tf.saved_model.signature_def_utils.build_signature_def(
        # 获取输入输出的信息(shape,dtype等),在部署服务后请求带来的数据会喂到inputs中,服务吐的结果会以outputs的形式返回
        #signature中的key  就下面的input  dropout_keep_prob 都是curl时候的key
        inputs={"feat_index": tf.saved_model.utils.build_tensor_info(model_train.model.feat_index), \
                "feat_value": tf.saved_model.utils.build_tensor_info(model_train.model.feat_value), \
                "dropout_fm": tf.saved_model.utils.build_tensor_info(model_train.model.dropout_fm), \
                "dropout_deep": tf.saved_model.utils.build_tensor_info(model_train.model.dropout_deep), \
                "train_phase": tf.saved_model.utils.build_tensor_info(model_train.model.train_phase)},         # 获取输入tensor的信息,这个字典可以有多个key-value对
        outputs={"output": tf.saved_model.utils.build_tensor_info(model_train.model.out)},     # 获取输出tensor的信息,这个字典可以有多个key-value对
        method_name=tf.saved_model.signature_constants.PREDICT_METHOD_NAME    # 就是字符串类型 'tensorflow/serving/predict'
    #保存会话对象中的 graph 和所有变量
    builder.add_meta_graph_and_variables(sess,
        tags=[tf.saved_model.tag_constants.SERVING],         # 如果用来部署,就这样写。否则可以写其他,如["test-model"]  就是字符串类型 'serve'
        signature_def_map={"serving_default": signature},    # 如果用来部署,字典的key必须是"serving_default"。否则可以写其他
    #将内建的 savedModel protobuf 写入磁盘
    builder.save()

模型文件夹目录结构如下,1和2为版本号文件夹(附件中的模型只有1个版本)

./model

├── 1
│   ├── saved_model.pb
│   └── variables文件夹
└── 2
├── saved_model.pb
└── variables文件夹

四.模型挂载 (模型文件在附件里面,为deepfm_model文件夹,由于模型文件较大,为分片压缩包)

挂载命令:

注:source为前述模型保存路径(模型的路径,可以自定义),target为映射到docker中的路径, model_name为自定义设置的模型名( 需要设置hh_model,和预测脚本使用的模型名一致 ), tensorflow/serving:1.12.0为指定的容器,实质就是把本地模型映射到容器的模型目录(可指定gpu)

docker 启动 tf-server 服务(载入对应的 saved 模型)

sudo docker run -p 1234:8500 -p 1500:8501 --mount type=bind,source=/home/hang/Project/hh_deep_model/deepfm_model,target=/models/hh_model  -e MODEL_NAME=hh_model  -d tensorflow/serving:1.12.00

解释: 本机的 1234 端口对应 Docker 8500 端口( GRPC 端口),本机 1500 端口对应 Docker 8501 端口( HTTP 端口)

挂载成功后可测试是否curl成功(下面curl的case中input的数据不符合模型的输入格式,模型需要的特征维数较高, 直接用步骤5-模型预测部分 来测试模型是否挂载成功

线上 curl 部署在 tf-serving saved 格式的模型

curl -d '{"inputs": {"input":[[1.0, 2.0, 5.0,2.0,1.0, 2.0, 5.0,2.0,1.0, 2.0, 5.0,2.0,1.0, 2.0, 5.0,2.0,1.0, 2.0, 5.0,2.0]],"dropout_keep_prob":1.0}}' -X POST http://localhost:1500/v1/models/hh_model:predict

五.模型预测 (预测脚本需要的meta和test_type2_value.npy文件在附件压缩包里,为分片压缩包)

客户端预测(grpc协议通信),客户端需要安装tensorflow-serving-api(使用pip install 安装 pip install tensorflow-serving-api==1.12.0),GRPC端口--容器对应的端口为8500端口,对外开发的端口自定义设置(?:8500),curl(http端口)–容器对应的端口为8501端口,对外开发的端口自定义设置(?:8501)。

模型挂载成功后,可直接执行下面的代码测试是否跑通。

代码示例:

tensorflow-online-predict

#!/usr/bin/env python
#encoding: utf-8

import tensorflow as tf
import numpy as np
import sys
import os
import logging
from grpc.beta import implementations
from tensorflow_serving.apis import predict_pb2
from tensorflow.core.framework import types_pb2
from tensorflow_serving.apis import prediction_service_pb2

"server"根据需要自定义

'0.0.0.0:8500’其中ip可更换为机器ip,以进行跨机器方位

tf.app.flags.DEFINE_string(‘server’, r’127.0.0.1:1234’, ‘post of server’)

FLAGS = tf.app.flags.FLAGS

dict_set = None

def load_features_from_lines(path):
    # 读取特征列表,一行一个
    features = []
    with open(path) as o:
        for line in o:
            line_strip = line.strip()
            if line_strip:
                features.append(line_strip.decode(‘utf-8’))
    logging.info(‘load {0} cols from {1} for filter’.format(len(features), path))
    return features

def data_gen(fea_path):
    # 数据处理  test_type2_value为验证数据集  用来验证一致性 和test_res里面的预测值对比一致性
    # 真正上线时,feat_value为预处理好的特征(归一化脚本需要额外再写)。rc端输入特征(模型同学提供特征列表),然后本脚本进行预测然后返回一个score。
    feat_value = np.load(“test_type2_value.npy”)[0].astype(np.float32)
    #print feat_value.shape
    fealist = load_features_from_lines(fea_path)
    feat_index = np.array([x for x in range(len(fealist))]).astype(np.int32)
    dropout_fm = np.array([0.0]*2).astype(np.float32)
    dropout_deep = np.array([0.0]*4).astype(np.float32)
    train_phase = False
    return feat_index,feat_value,dropout_fm,dropout_deep,train_phase

def setup_stub():
    host, port = FLAGS.server.split(‘:’)
    channel = implementations.insecure_channel(host, int(port))
    return prediction_service_pb2.beta_create_PredictionService_stub(channel)

def setup_request():
    request = predict_pb2.PredictRequest()
    # 模型名称与挂载模型时设置的model_name一致(即docker run …命令中的model_name)
    request.model_spec.name = ‘hh_model’
    request.model_spec.signature_name = tf.saved_model.signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY
    return request

def predict(data):
#    if os.environ.get(‘https_proxy’):
#        del os.environ[‘https_proxy’]
#    if os.environ.get(‘http_proxy’):
#        del os.environ[‘http_proxy’]
    stub = setup_stub()
    request = setup_request()
    feat_index,feat_value,dropout_fm,dropout_deep,train_phase = data_gen(data)
    request.inputs[‘feat_index’].CopyFrom(tf.contrib.util.make_tensor_proto(feat_index))
    request.inputs[‘feat_value’].CopyFrom(tf.contrib.util.make_tensor_proto(feat_value))
    request.inputs[‘dropout_fm’].CopyFrom(tf.contrib.util.make_tensor_proto(dropout_fm))
    request.inputs[‘dropout_deep’].CopyFrom(tf.contrib.util.make_tensor_proto(dropout_deep))
    request.inputs[‘train_phase’].CopyFrom(tf.contrib.util.make_tensor_proto(train_phase))
    result_future = stub.Predict.future(request, 5.0)  # 5 seconds
    #.float_val
    response_out_score = np.array(result_future.result().outputs[‘output’].float_val)  # 300
    print("response_out_score: ", response_out_score)

if name == ‘main’:
    # fea_path为特征列表路径,可见附件中的meta文件
    fea_path = sys.argv[1]
    predict(fea_path)

docker常用命令

Docker常用操作

docker version 查看docker的版本信息

docker info 显示 Docker 系统信息,包括镜像和容器数

docker --help Docker的帮助命令

docker images 列出本地主机上的镜像

docker search 从仓库中搜索指定的镜像

docker rmi –f 删除镜像id   docker rmi -f $(docker images -qa) 删除全部 –q表示静默模式,只显示容器编号

docker rm 删除容器ID docker rm -f $(docker ps -aq)删除全部

docker pull下载镜像

docker run [option] image [command] 新建并启动容器—具体参数可以查看

docker ps 列出当前所有正在运行的容器

启动容器:docker start 容器ID或者容器名

重启容器:docker restart 容器ID或者容器名

停止容器:docker stop 容器ID或者容器名

强制停止容器:docker kill 容器ID或者容器名

docker top 容器ID查看容器内运行的进程

docker inspect 容器ID查看容器内部细节

docker exec -it 容器ID bashShell 在容器中打开新的终端,并且可以启动新的进程--进入正在运行的容器并以命令行交互 docker exec -it <CONTAINER ID> /bin/bash对指定的容器执行bash,进入容器

docker cp 容器ID:容器内路径 目标主机路径 从容器内拷贝文件到主机上

docker部署flaskA brief guide to building an app to serve a natural language processing model, containerizing it and deploying it. 构建用于服务自然语言处理模型,将其容器化和部署的应用程序的简要指南。 By: Edward Krueger and Douglas Frank...
最近发现模型在更新的一瞬间容易产生超时的问题,于是就了解了一下tf-serving 中有个warmup主要是通过模型启动时加载${model}/${version}/assets.extra/tf_serving_warmup_requests达到热启动的目的,使得模型更新时不易产生超时的问题 首先根据自己的模型字段进行编写形成tf_serving_warmup_requests文件,在导出模型时和warmup文件一起导出 以下是我warmup文件生成代码 #!/usr/bin/env pytho.