>  기사  >  백엔드 개발  >  제품 환경 모델 배포, Docker 이미지, Bazel 작업 공간, 내보내기 모델, 서버, 클라이언트

제품 환경 모델 배포, Docker 이미지, Bazel 작업 공간, 내보내기 모델, 서버, 클라이언트

巴扎黑
巴扎黑원래의
2017-06-23 15:11:381295검색

제품 환경 모델 배포, 간단한 Web APP 생성, 사용자가 이미지 업로드, Inception 모델 실행 및 자동 이미지 분류 실현.

TensorFlow 서비스 개발 환경을 구축하세요. 도커를 설치하세요. 구성 파일을 사용하여 Docker 이미지를 로컬로 생성합니다( docker build --pull -t $USER/tensorflow-serving-devel ). 이미지에서 컨테이너를 실행하려면 docker run -v $HOME:/mnt/home -p 9999:9999 -it $USER/tensorflow-serving-devel 을 실행하고 이를 홈 디렉터리의 컨테이너/mnt/home 경로에 로드합니다. 그리고 터미널에서 일하세요. IDE나 편집기를 사용하여 코드를 편집하고, 컨테이너를 사용하여 빌드 도구를 실행하고, 서버를 빌드하기 위해 포트 9999를 통해 호스트에 액세스합니다. 종료 명령은 컨테이너 터미널을 종료하고 실행을 중지합니다.

TensorFlow 서비스 프로그램은 C++로 작성되었으며 Google의 Bazel 빌드 도구를 사용합니다. 컨테이너는 Bazel을 실행합니다. Bazel은 코드 수준에서 타사 종속성을 관리합니다. Bazel은 자동으로 빌드를 다운로드합니다. 프로젝트 라이브러리 루트 디렉토리는 WORKSPACE 파일을 정의합니다. TensorFlow 모델 라이브러리에는 Inception 모델 코드가 포함되어 있습니다.

TensorFlow 서비스는 프로젝트에서 Git 하위 모듈로 제공됩니다. mkdir ~/serving_example, cd ~/serving_example, git init, git submodule add, tf_serving, git submodule update --init --recursive.

WORKSPACE 파일 local_repository 규칙은 타사 종속성을 로컬 저장소 파일로 정의합니다. 프로젝트는 TensorFlow 종속성을 초기화하기 위해 tf_workspace 규칙을 가져옵니다.

workspace(name = "serving")

local_repository(
name = "tf_serving",
path = __workspace_dir__ + "/tf_serving",
)

local_repository(
name = "org _tensorflow",
path = __workspace_dir__ + " /tf_serving/tensorflow",
)

load('//tf_serving/tensorflow/tensorflow:workspace.bzl', 'tf_workspace')
tf_workspace("tf_serving/tensorflow/", "@org_tensorflow")

bind(
이름 = "libssl",
실제 = "@boringssl_git//:ssl",
)

bind(
) 이름 = "zlib",
실제 = "@zlib_archive//:zlib",
)

local_repository (
이름 = "inception_model",
경로 = __workspace_dir__ + "/tf_serving/tf_models/inception",
)

제품 사용을 위해 학습된 모델, 데이터 흐름도 및 변수를 내보냅니다. 모델 데이터 흐름 그래프는 자리 표시자로부터 입력을 받고 단일 추론 단계에서 출력을 계산해야 합니다. Inception 모델(또는 일반적인 이미지 인식 모델), JPEG로 인코딩된 이미지 문자열 입력은 TFRecord 파일에서 입력을 읽는 것과 다릅니다. 입력 자리 표시자를 정의하고, 외부 입력을 나타내기 위해 자리 표시자를 원래 추론 모델 입력 형식으로 변환하는 함수를 호출하고, 이미지 문자열을 각 구성 요소가 [0, 1] 내에 있는 픽셀 텐서로 변환하고, 이미지 크기를 충족하도록 조정합니다. 모델의 예상 너비와 높이, 픽셀 값은 모델에 필요한 간격 [-1, 1]로 변환됩니다. 원래 모델 추론 방법을 호출하고 변환된 입력을 기반으로 결과를 추론합니다.

추론 방법의 각 매개변수에 값을 할당합니다. 체크포인트에서 매개변수 값을 복원합니다. 학습 매개변수가 포함된 모델 훈련 체크포인트 파일을 주기적으로 저장합니다. 마지막으로 저장된 훈련 체크포인트 파일에는 마지막으로 업데이트된 모델 매개변수가 포함되어 있습니다. 사전 학습 체크포인트 파일을 다운로드하려면 다음으로 이동하세요. Docker 컨테이너에서 cd ​​/tmp, cur -0 , tar -xzf inception-v3-2016-03-01.tar.gz.

tensorflow_serving.session_bundle.exporter.Exporter 클래스는 모델을 내보냅니다. saver 인스턴스를 전달하여 인스턴스를 생성하고, importer.classification_signature를 사용하여 모델 서명을 생성합니다. input_tensor 및 출력 텐서를 지정합니다. classes_tensor에는 출력 클래스 이름 목록이 포함되어 있으며 모델은 각 범주 점수(또는 확률) socres_tensor를 할당합니다. 여러 범주가 있는 모델의 경우 구성에서는 tf.nntop_k만 선택 범주에 반환되고 모델 할당 점수는 내림차순으로 상위 K개 범주로 정렬되도록 지정합니다. importer.Exporter.init 메소드 서명을 호출하면 내보내기 메소드는 모델을 내보내고 출력 경로, 모델 버전 번호 및 세션 객체를 받습니다. 내보내기 클래스는 종속성이 있는 코드를 자동으로 생성하고 Doker 컨테이너는 bazel을 사용하여 내보내기를 실행합니다. 코드는 bazel 작업공간 importer.py에 저장됩니다.

import time
import sys

import tensorflow as tf
from tensorflow_serving.session_bundle importexporter
from inception import inception_model

NUM_CLASSES_TO_RETURN = 10

def Convert_external_inputs (external_x):
이미지 = tf.image.convert_image_dtype(tf.image .decode_jpeg(external_x, 채널=3), tf.float32)
이미지 = tf.image.resize_bilinear(tf.expand_dims(이미지, 0), [299, 299])
이미지 = tf.mul(tf.sub(이미지 , 0.5). er (tf.string)
x = Convert_external_inputs ( external_x)

y = 추론(x)

saver = tf.train.Saver()

with tf.Session() as sess:
        ckpt = tf.train.get_checkpoint_state(sys.argv[1])
        ckpt 및 ckpt.model_checkpoint_path:
            저장 r.복원( sess, sys.argv[1] + "/" + ckpt.model_checkpoint_path)
        else:
            print("체크포인트 파일을 찾을 수 없음")
            SystemExit

scores, class_ids = tf.nn.top_k(y, NUM_CLASSES _TO_RETURN)

classes = tf.contrib.lookup.index_to_string(tf.to_int64(class_ids),
            mapping=tf.constant([str(i) for i in range(1001)]))

model_exporter = importer.Exporter(saver) #      model_exporter.export(sys.argv[1] + " /export", tf.constant(time.time()), sess)

一个构建规则BUILD文件。在容器命令运行导器,cd /mnt/home/serving_example, hazel run:export /tmp/inception-v3 ,依据/tmp/inception-v3提到的检查点文件在/tmp/inception-v3/{currenttimestamp}/创建导器.入cc_proto_library规则정义,为proto文件定义构建规则。 일반적인 过命令bazel run :server 9999 /tmp/inception-v3/export/{timestamp},容器运行推断服务器。

py_binary(

        name = "export",

        srcs = [

            "내보내기. py",

        ],
        deps = [
            "@tf_serving//tensorflow_serving/session_bundle:exporter",
            "@org_tensorflow//tensorflow:tensorflow_py",
           "@inception_model//inception",
        ],
    )

load("@protobuf//:protobuf.bzl", "cc_proto_library")

cc_proto_library(

        name="classification_service_proto",

        srcs=["classification_service.proto"],

        cc_libs = ["@pro tobuf//:프로토부프 "],

        protoc="@protobuf//:protoc",
        default_runtime="@protobuf//:protobuf",
        use_grpc_plugin=1
    )

cc_binary(
        이름 = "서버 ",
        srcs = [

            " server.cc",

            ],
        deps = [
            ":classification_service_proto",
            "@tf_serving//tensorflow_serving/servables/tensorflow:session_bundle_factory",
           "@grpc//:grpc++",
            ],
    )

TensorFlow는 gRPC协议(基于HTTP/2二进协议)을 사용합니다. .프로토콜 버퍼정정에서는 gRPC IDL(接口정정义语言)과 두 가지 제어제약을 사용합니다. 。接收JPEG编码待分类图image字符串输入,返回分数排列推断类别列表。 정义在classification_service.proto文件。可用可一接口.proto编译器转换proto文件为客户端和服务器类bazel 빌드:classification_service_proto可行构建,통로bazel-genfiles/classification_service.grpc.pb.h检查结果。推断逻辑,ClassificationService::Service接口必须实现。检查bazel-genfiles/classification_service.p b.h查看요청, 응답消息정义.proto정정义变成每种类型C++接口。

syntax = "proto3";

message ClassificationRequest {

       // bytes input = 1;

       float 꽃잎 폭 = 1;

       flo 꽃잎 높이 = 2;

       float sepalWidth = 3 ;
       float sepalHeight = 4;
    };

message ClassificationResponse {
       반복 ClassificationClass 클래스 = 1;
    };

메시지 분류 클래스 {
          문자열 이름 = 1;
                부동 점수 = 2; 내보낸 모델을 로드하고, 추론 메서드를 호출하고, ClassificationService::Service를 구현합니다. 모델을 내보내고, SessionBundle 개체를 생성하고, 완전히 로드된 데이터 흐름 그래프 TF 세션 개체를 포함하고, 내보내기 도구 분류 서명 메타데이터를 정의합니다. SessionBundleFactory 클래스는 SessionBundle 객체를 생성하고, pathToExportFiles에 의해 지정된 경로에 내보내기 모델을 로드하도록 구성하고, 생성된 SessionBundle 인스턴스에 대한 고유 포인터를 반환합니다. ClassificationServiceImpl을 정의하고 SessionBundle 인스턴스 매개변수를 수신합니다.

분류 서명을 로드하고, GetClassificationSignature 함수는 모델 내보내기 메타데이터 ClassificationSignature를 로드하고, 서명은 수신된 이미지의 실제 이름에 대한 입력 텐서 논리 이름을 지정하고, 데이터 흐름 그래프는 텐서 논리 이름 매핑 추론 결과를 출력합니다. protobuf 입력을 추론 입력 텐서로 변환하고 요청 매개변수는 JPEG로 인코딩된 이미지 문자열을 추론 텐서에 복사합니다. 추론을 실행하기 위해 sessionbundle은 TF 세션 객체를 가져와 한 번 실행한 후 입력 및 출력 텐서 추론을 전달합니다. 추론된 출력 텐서는 protobuf 출력을 변환하고 출력 텐서 결과는 ClassificationResponse 메시지에 복사되며 응답 출력 매개 변수 형식은 모양에 지정됩니다. gRPC 서버를 설정하고, SessionBundle 객체를 구성하고, ClassificationServiceImpl 인스턴스 샘플 코드를 생성합니다.


#include
#include

#include

#include

#include "classification_service.grpc.pb.h"


# include "tensorflow_serving/servables/tensorflow/session_bundle_factory.h"

using 네임스페이스 std;

using 네임스페이스 tensorflow::serving;

using 네임스페이스 grpc;

unique_ptr createSessionBundle(const string& pathToExportFiles) {

SessionBundleConfig 세션 _bundle_config = 세션번들구성( );

Unique_ptrbundle_factory;

SessionBundleFactory::Create(session_bundle_config, &bundle_factory);

unique_ptr Bundle_factory->CreateSessionBundle(pathToExportFiles, &sessionBundle);

return sessionBundle;
}

클래스 ClassificationServiceImpl final : public ClassificationService::Service {


private:

Unique_ptr sessionBundle;


public:

ClassificationServiceImpl(unique_ptr sessionBundle) :

sessionBundle(move(sessionBundle)) {};

Status classify( 서버컨텍스트* context, const ClassificationRequest* 요청,

                                  ClassificationResponse* 응답) 재정의 {                                                                           Bundle->meta_graph_def, &signature);

if (!signatureStatus.ok ()) {

              return Status(StatusCode::INTERNAL, SignatureStatus.error_message())
        }

tensorflow::Tensor input(tensorflow::DT_STRING, tensorflow::TensorShape());

        .scalar ()() = request->input();

Vector         }

for (int i = 0; i < outputs[0].NumElements(); ++i) {
ClassificationClass *classificationClass = response->add_classes();
             classificationClass->set_name(outputs[0].flat()(i));
             classificationClass->set_score(outputs[1].flat()(i));
          }

return Status::OK;

}
    };


    int main(int argc, char** argv) {

if (argc < 3) {
cerr << "Usage: server /path/to/export/files" << endl;
          return 1;
        }

const string serverAddress(string("0.0.0.0:") + argv[1]);
       const string pathToExportFiles(argv[2]);

unique_ptr sessionBundle = createSessionBundle(pathToExportFiles);

ClassificationServiceImpl classificationServiceImpl(move(sessionBundle));

ServerBuilder builder;
        builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
        builder.RegisterService(&classificationServiceImpl);

unique_ptr server = builder.BuildAndStart();
        cout << "Server listening on " << serverAddress << endl;

server->Wait();

return 0;
    }

通过服务器端组件从webapp访问推断服务。运行Python protocol buffer编译器,生成ClassificationService Python protocol buffer客户端:pip install grpcio cython grpcio-tools, python -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. classification_service.proto。生成包含调用服务stub classification_service_pb2.py 。服务器接到POST请求,解析发送表单,创建ClassificationRequest对象 。分类服务器设置一个channel,请求提交,分类响应渲染HTML,送回用户。容器外部命令python client.py,运行服务器。浏览器导航http://localhost:8080 访问UI。

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler

import cgi
    import classification_service_pb2
    from grpc.beta import implementations

class ClientApp(BaseHTTPRequestHandler):
        def do_GET(self):
            self.respond_form()

def respond_form(self, response=""):

form = """
           
           

Image classification service


           

           
Image:

           

           

            %s
           
            """

response = 양식 % 응답

self.send_ response(200)
            self.send_header("콘텐츠 유형" , "text/html")
            self.send_header("Content-length", len(response))
            self.end_headers()
            self.wfile.write(response)

def do_POST(self):

양식 = cgi.FieldStorage(
                fp=self.rfile,
                headers=self.headers,
               environ={
                    'REQUEST_METHOD' : 'POST',
                    'CONTENT_TYPE': self.headers['Content-Type'],
                })

request = classification_service_pb2.ClassificationRequest()
            request.input = form['file'].file.read()

channel =implementations.insecure_channel("127.0.0.1", 9999)
            스텁 = classification_service_pb2.beta _create_ClassificationService_stub(채널 )
            response = stub.classify(request, 10) # 10초 시간 초과

self.respond_form("

Response: %s
" % response)


    if __name__ == '__main__':
        호스트_포트 = ('0.0.0.0', 8080)
        인쇄 "%s:%s에서 검색" % 호스트_포트
        HTTPServer(host_port, ClientApp).serve_forever()

产product准备,分类服务器应용产품。编译服务器文件复算到容器永久位置,清理所有临时构建文件。容器中,mkdir /opt/classification_server, cd /mnt/home/serving_example, cp -R bazel-bin/. /opt/classification_server, bazel clean .容器외부,状态提交NewDocker镜image,创建记录虚拟文件系统变化快Illumina, 容器外, docker ps, Dock 커밋 <컨테이너 ID>。图image推送到自己偏好docker服务云,服务。

参考资料:
《면向机器智能的TensorFlow实践》

欢迎付费咨询(150元每小时),我的微信:qingxingfengzi

위 내용은 제품 환경 모델 배포, Docker 이미지, Bazel 작업 공간, 내보내기 모델, 서버, 클라이언트의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.