Tutorial

[TF serving] 딥러닝 모델 Tf serving에 올리기

new_challenge 2019. 5. 8. 22:56
반응형

이전까지 학습시킨 2개의 모델을 tf serving에 올려 실제 서비스에 적용할 수 있게 하는 한다.

현재 진행하는 프로젝트에서 실제 사용 된 코드.

 

 

 

1. 필요한 라이브러리 설치

$ apt-get update
$ apt-get install tensorflow-model-server
$ apt-get upgrade tensorflow-model-server

- 일단 tf serving을 사용하기 위해 tensorflow-model-server를 설치

 

 

2. 모델 저장하기

1> 필요한 라이브러리 로딩

import argparse
import json

import numpy as np
import requests
import keras
import tensorflow as tf

import sys
import os
import cv2
import matplotlib.pyplot as plt

- 필요한 라이브러리 로딩

 

 

2> path 설정

sys.path.append(os.path.dirname("../../ssd_detectors/"))

- 사용 할 코드들이 있는 곳으로 path를 설정해준다

 

 

3> 첫 번째 모델 생성 ( seglink : text detection )

# 모델 가져오기

from sl_model import SL512

# SegLink
model = SL512(input_shape=(512, 512, 3), softmax=True)
weights_path= "../../ssd_detectors/checkpoints/sl512_ksignboard_ex18/weights.240.h5"

- 모델을 생성하고 사용할 가중치가 있는 경로를 변수에 담는다.

 

 

# 모델 저장하기

export_path = 'seglink_ksignboard/1'

with tf.keras.backend.get_session() as sess:
    model.load_weights(weights_path)
    tf.saved_model.simple_save( sess, 
                                export_path, 
                                inputs={t.name: t for t in model.inputs}, 
                                outputs={t.name: t for t in model.outputs}
                                )

- 모델이 저장 될 경로를 지정한다.

- tf.keras.backend.get_seesion()으로 세션을 얻은 상태에서 모델에 가중치를 올린다.

- tf.saved_model.simple_save( 세션, 모델이 저장 될 경로, 인풋, 아웃풋 ) 을 사용해 모델을 저장한다.

- 위의 코드를 실행하면 지정 된 경로에 모델이 저장이 된다.

- 새롭게 모델을 저장하려면 export_path에서 /1을 /2로만 변경해주면 된다. 버전을 나타낸다.

 

 

# 확인하기

[t.name for t in  model.inputs]
[t.name for t in  model.outputs]

- 위의 코드를 실행시키면 모델의 input과 output의 이름을 알 수 있다.

- 추후에 모델에 입력 값을 넣을 때 꼭 여기에서 출력 된 이름과 동일한 파라미터로 보내주어야한다.

 

 

 

4> 두 번째 모델 생성 ( CRNN: text regcognition )

# 모델 가져오기

from crnn_model_focal_ctc_loss import CRNN
from util.crnn_utils import dict838

input_width = 256
input_height = 32
input_shape = (input_width, input_height, 1)
model, model_pred = CRNN(input_shape, len(dict838),prediction_only=False, gru=False)
weight_path = "../../ssd_detectors/checkpoints/201905061732_crnn_ksignboard_v18_best_3/weights.053.h5"

- CRNN 모델은 keras API 함수를 사용하여 모델을 만들었고, Training 모델과 predict모델이 다르다.pl

 

 

# 모델 저장하기

export_path = '../crnn/1'

with tf.keras.backend.get_session() as sess:
    model_pred.load_weights(weight_path,by_name=True)
    tf.saved_model.simple_save(sess, export_path, inputs={t.name: t for t in model_pred.inputs}, outputs={t.name: t for t in model_pred.outputs})

- Tf serving에 올릴 모델은 predict모델이기때문에, 가중치를 model_pred에 로딩한다.

- 그리고 tf.saved_model.simple_save를 사용해서 모델을 저장한다.

 

 

# 확인하기

[t.name for t in  model.inputs]
[t.name for t in  model_pred.inputs]

- 위의 코드를 실행시키면 input과 output의 이름을 알 수 있다.

 

 

 

3. TF SERVING 서버 실행시키기

# 모델을 하나만 올릴 경우

tensorflow_model_server \
--model_base_path = 절대경로입력(모델이 있는 곳) \
--rest_api_port=9002 --model_name=모델이름

- 여기서의 model_name은 서빙서버의 이름이다.

 

 

# 모델을 여러개 올릴 경우

tensorflow_model_server \
--rest_api_port=9002 \
--model_config_file=/home/Documents/django/tfserver/models.conf

- REST API : 9002 포트에서 사용가능하다. 

- Tf serving 서버를 실행시키기 위해서는 위와 같은 커맨드를 실행시켜야한다.

- .sh 파일로 만들어놓으면 사용하기 편리하다.

- 위 코드에서 사용하는 model.conf에 대한 설정파일도 있어야한다.

 

 

model.conf
model_config_list {
  config {
    name: 'seglink'
    base_path: '/home/Documents/django/tfserver/seglink_ksignboard/'
    model_platform: 'tensorflow'
  }
  config {
    name: 'crnn'
    base_path: '/home/Documents/django/tfserver/crnn/'
    model_platform: 'tensorflow'
  }
}

 

 

# 아래 링크를 참고하면 어떻게 모델 서버를 구축하는지에 대해 자세히 확인 할 수 있다.

https://www.tensorflow.org/tfx/serving/serving_config

 

How to Configure a Model Server  |  TFX  |  TensorFlow

Create a file containing an ASCII ModelServerConfig protocol buffer, and pass its path to the server using the --model_config_file flag. (Some useful references: what an ASCII protocol buffer looks like; how to pass flags in Docker.) You can also reload th

www.tensorflow.org

 

 

4> 서버에 올린 모델 테스트

1> SegLink Model Test

# 서버로 보낼 이미지 가져오기

image_path = "/home/ina/Documents/ssd_detectors/data/KSIGNBOARD/21102_11.jpg"
input_image = cv2.imread(image_path)
seg_img = cv2.resize(input_image, (512,512), cv2.INTER_AREA)

- seglink에 넣을 이미지를 읽고, 모델에 넣기 위해 512 * 512로 리사이즈 한다.

 

 

# 리사이즈된 이미지 확인

input_t = input_seglink.astype('int32')
plt.imshow(input_t)

 

 

 

# 인스턴스에 이미지 담기

payload = {
    "instances": [{'input_1:0': seg_img.tolist()}]
}

- 위에서 확인한 input 이름과 동일하게 넣어준다.

- 이미지를 넣어줄 때는 tolist()로 변환 후 넣어준다.

 

 

# request 보내기

r = requests.post('http://localhost:9002/v1/models/seglink:predict', json=payload)

- localhost에 위에서 지정한 포트 9002번에 모델이 있는 v1/models/모델이름:predict 으로 request를 보낸다.

- 이때 predict할 이미지를 json에 담아서 보낸다.

 

 

# 결과 받아오기

pred = json.loads(r.content.decode('utf-8'))
res = np.array(pred['predictions'])

- 결과는 r.content안에 담겨져있다. 이것을 'utf-8'로 디코드해서 json으로 읽는다.

- 결과의 ['predictions']를 가져온다. 이 안에 우리가 디코드 해야할 결과 값이 담겨져온다.

  (위에서 봤던 output의 이름)

- res.shape는 (5461, 31)이다.

 

 

2> CRNN Model Test

# 서버로 보낼 이미지 가져오기

input_crnn = input_crnn #256.32

- seglink를 거쳐서 나온 이미지를 CRNN에 넣을 수 있게 인코딩한다.

 

 

# 인스턴스에 이미지 담기

payload_crnn = {
            "instances": [{'image_input:0' : input_crnn.tolist()}]
        }

- 위에서 확인한 input 이름과 동일하게 넣어준다.

- 이미지를 넣어줄 때는 tolist()로 변환 후 넣어준다.

 

 

# request 보내기

r = requests.post('http://localhost:9002/v1/models/crnn:predict', json=payload)

- localhost에 위에서 지정한 포트 9002번에 모델이 있는 v1/models/모델이름:predict 으로 request를 보낸다.

- 이때 predict할 이미지를 json에 담아서 보낸다.

 

 

# 결과 받아오기

pred = json.loads(r.content.decode('utf-8'))
res = np.array(pred['predictions'])

- 결과는 r.content안에 담겨져있다. 이것을 'utf-8'로 디코드해서 json으로 읽는다.

- 결과의 ['predictions']를 가져온다. 이 안에 우리가 디코드 해야할 결과 값이 담겨져온다.

  (위에서 봤던 output의 이름)

- res.shape는 (1, 62, 836)

 

반응형