[인공지능] gRPC 메타데이터 input, ouput 정보 가져오기

참조

 

목적

  • Tensorflow Serving 에서 gRPC를 이용하여 Python 코드에서 검증하는 작업 코드를 작성하였습니다.
  • 하지만, 문제가 되는 부분이 모델별로 input, ouput 데이터가 다르기 때문에 해당 부분을 유연하게 가져오는 방법이 필요 했습니다.
  • 조사 결과, Model의 Metadata 안에 Key, Value 값으로 Input, Ouput 값들이 저장되어 있는 것을 확인하였습니다.
  • 실제로 Tensroflow Serving 의 gRPC 코드에 metadata를 가져와 Input, Ouput 값들을 파싱하는 부분 로직 추가 하였습니다.

 

gRPCHelper.py

  • gRPCHelper 클래스를 하나 생성하여 해당 클래스 안에는 gRPC 관련 메서드들을 작성하였습니다.
  • 여기서 새롭게 추가된 메서드는 get_model_metadata 메서드 이고, 해당 메서드를 통해 metadata 값을 가져올 수 있습니다.
import numpy as np
import tensorflow as tf
import grpc

from tensorflow_serving.apis import prediction_service_pb2_grpc
from tensorflow_serving.apis import get_model_metadata_pb2
from tensorflow_serving.apis import predict_pb2

class gRPCHelper(object):

    @staticmethod    
    def get_mnist_dataset():
        mnist = tf.keras.datasets.mnist

        (x_train, y_train), (x_test, y_test) = mnist.load_data()
        x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
        x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
        x_train = x_train.astype('float32')
        x_test = x_test.astype('float32')
        x_train, x_test = x_train / 255.0, x_test / 255.0

        return (x_test, y_test)

    @staticmethod
    def get_stub(host, port):
        channel = grpc.insecure_channel(f'{host}:{port}')
        stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)

        return stub

    @staticmethod
    def get_model_metadata(stub, model):
        get_model_metadata_request  = get_model_metadata_pb2.GetModelMetadataRequest()
        get_model_metadata_request .model_spec.name = model
        get_model_metadata_request .metadata_field.append('signature_def')
        resp = stub.GetModelMetadata(get_model_metadata_request, 5.0)  # 5 secs timeout

        signature_def = resp.metadata['signature_def']
        signature_map = get_model_metadata_pb2.SignatureDefMap()
        signature_map.ParseFromString(signature_def.value)

        serving_default = signature_map.ListFields()[0][1]['serving_default']
        serving_inputs = serving_default.inputs
        serving_outputs = serving_default.outputs

        return (serving_inputs, serving_outputs)

    @staticmethod
    def get_predict(stub, model, test_images, input):
        # Send request
        # See prediction_service.proto for gRPC request/response details.
        request = predict_pb2.PredictRequest()
        request.model_spec.name = model
        request.model_spec.signature_name = 'serving_default'

        request.inputs[input].CopyFrom(
            tf.make_tensor_proto(test_images))

        result = stub.Predict(request, 10.0)  # 10 secs timeout

        return result

    @staticmethod
    def get_input_output(datas):
        for key in datas.keys():
            key = key
        return key

    @staticmethod
    def list_chunk(list, num):
        return [list[idx:idx+num] for idx in range(0, len(list), num)]

    @staticmethod
    def test_images_append(test_images, x_test, y_test):
        for idx in range(0, 2):
            test_images = np.append(test_images, x_test[0:10000], axis=0)
            y_test = np.append(y_test, y_test[0:10000], axis=0)

        return (test_images, y_test)

    @staticmethod
    def predict_print(response, y_test):
        for idx, list in enumerate(response):
            prediction = np.argmax(list)
            if(y_test[idx] != prediction):
                print('실제 값 : {} / 예측 값 : {}'.format(y_test[idx], prediction))
            else:
                print('실제 값 : {} / 예측 값 : {}'.format(y_test[idx], prediction))

 

tensorflow_serving_gRPC.py

  • 다음 파이썬 파일에서는 실제 gRPCHelper 클래스를 사용하여 gRPC 통신으로 mnist 모델 Inference 하는 내용의 코드 입니다.
import numpy as np

from unit_test.tf_serving.gRPC.gRPCHelper import gRPCHelper

# mnist 데이터 셋 가져오기
(x_test, y_test) = gRPCHelper.get_mnist_dataset()
test_images = np.empty((0, 15))
test_images = x_test[0:15]

# gRPC 최대 전송 테스트
# 최대 전송 용량 확인 할 때 주석 풀어서 사용
#test_images, y_test = test_images_append(test_images=test_images, y_test=y_test)

host = 'localhost'
port = 8500
model = 'mnist-model'

# gRPC channel, stup 생성
stub = gRPCHelper.get_stub(host=host, port=port)

# 메타데이터 정보 가져오기
(serving_inputs, serving_outputs) = gRPCHelper.get_model_metadata(stub=stub, model=model)

input = gRPCHelper.get_input_output(serving_inputs)
output = gRPCHelper.get_input_output(serving_outputs)

# predict 값 가져오기
result = gRPCHelper.get_predict(stub=stub, model=model, test_images=test_images, input=input)
response = np.array(result.outputs[output].float_val)

response = gRPCHelper.list_chunk(response.tolist(), 10)

# 결과값 출력
gRPCHelper.predict_print(response=response, y_test=y_test)

 

실행 결과

  • 실행 결과, Inference 가 정상적으로 진행되는 것을 확인할 수 있습니다.
실제 값 : 7 / 예측 값 : 7
실제 값 : 2 / 예측 값 : 2
실제 값 : 1 / 예측 값 : 1
실제 값 : 0 / 예측 값 : 0
실제 값 : 4 / 예측 값 : 4
실제 값 : 1 / 예측 값 : 1
실제 값 : 4 / 예측 값 : 4
실제 값 : 9 / 예측 값 : 9
실제 값 : 5 / 예측 값 : 6
실제 값 : 9 / 예측 값 : 9
실제 값 : 0 / 예측 값 : 0
실제 값 : 6 / 예측 값 : 6
실제 값 : 9 / 예측 값 : 9
실제 값 : 0 / 예측 값 : 0
실제 값 : 1 / 예측 값 : 1
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY