gRPC-tutorial

  • 딥러닝 모델을 gRPC 프로토콜을 이용해 end-to-end 서비스로 구현하는 예제

텐서플로, mnist 데이터셋을 이용한 숫자 손글씨 인식 서비스

모델 학습

# 모델 구현 및 SavedModel 저장 
python ./model/sample_mnist.py

텐서플로 서빙 gRPC 서버 구축(local)

  • tensorflow/serving 도커 이미지를 이용
docker run --rm -p 8500:8500 --name tensorflow-mnist --mount type=bind,source=$(pwd)/protobuf/model/mnist,target=/models/mnist -e MODEL_NAME=mnist -t tensorflow/serving

텐서플로 서빙 서버 호출 예시

# server/zebra1_server.py
request = predict_pb2.PredictRequest()
request.model_spec.name = 'mnist'

dim = [tensor_shape_pb2.TensorShapeProto.Dim(size=28 * 28)]
shape = tensor_shape_pb2.TensorShapeProto(dim=dim)
img_tensor_content = np.array(tensor).tostring()  # tensor is a tf.Tensor from image
tensor_proto = tensor_pb2.TensorProto(
    dtype=types_pb2.DT_FLOAT, tensor_shape=shape, tensor_content=img_tensor_content,
)
request.inputs['flatten_input'].CopyFrom(tensor_proto)

with grpc.insecure_channel('localhost:8500') as channel:
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    response = stub.Predict(request)

텐서플로 서빙 REST API 서버 구축(local)

  • tensorflow/serving 도커 이미지를 이용
docker run --rm -p 8501:8501 --name tensorflow-mnist --mount type=bind,source=$(pwd)/protobuf/model/mnist,target=/models/mnist -e MODEL_NAME=mnist -t tensorflow/serving

텐서플로 서빙 서버 호출 예시

메타데이터
응답 예시
{
    "model_spec": {
        "name": "mnist",
        "signature_name": "",
        "version": "0"
    },
    "metadata": {
        "signature_def": {
            "signature_def": {
                "serving_default": {
                    "inputs": {
                        "flatten_input": {
                            "dtype": "DT_FLOAT",
                            "tensor_shape": {
                                "dim": [
                                    {
                                        "size": "-1",
                                        "name": ""
                                    },
                                    {
                                        "size": "28",
                                        "name": ""
                                    },
                                    {
                                        "size": "28",
                                        "name": ""
                                    }
                                ],
                                "unknown_rank": false
                            },
                            "name": "serving_default_flatten_input:0"
                        }
                    },
                    "outputs": {
                        "dense_1": {
                            "dtype": "DT_FLOAT",
                            "tensor_shape": {
                                "dim": [
                                    {
                                        "size": "-1",
                                        "name": ""
                                    },
                                    {
                                        "size": "10",
                                        "name": ""
                                    }
                                ],
                                "unknown_rank": false
                            },
                            "name": "StatefulPartitionedCall:0"
                        }
                    },
                    "method_name": "tensorflow/serving/predict"
                },
                "__saved_model_init_op": {
                    "inputs": {},
                    "outputs": {
                        "__saved_model_init_op": {
                            "dtype": "DT_INVALID",
                            "tensor_shape": {
                                "dim": [],
                                "unknown_rank": true
                            },
                            "name": "NoOp"
                        }
                    },
                    "method_name": ""
                }
            }
        }
    }
}
추론
body
  • mnist 데이터셋의 이미지 픽셀 정보를 flatten 처리
  • 28 * 28 픽셀의 이미지이기 때문에 길이 784의 array 필요
{
    "inputs": [
        0, 
        0,
        ...
        0
    ]
}
응답 예시
{
    "outputs": [
        [
            -3.95562673,
            -6.8210392,
            -3.59877825,
            8.60473824,
            -24.2328682,
            12.1519499,
            -14.8646755,
            -3.63648438,
            -8.98115826,
            -3.38781738
        ]
    ]
}