[TF serving] 딥러닝 모델 Tf serving에 올리기
이전까지 학습시킨 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
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)