Deploying tensorflow serving client script

2/21/2019

I am new to tensorflow and I am learning how to deploy production models. I have already deployed my Tensorflow Object detection model on GCP cloud storage and it is available on Google Kubernetes engine and has an endpoint. Now, I want to deploy the client script which uses gRPC (instead of REST for faster response time). How do I deploy the client script so that it is available as an API request to the outside world and such that it can take an encoded image array and make request to the serving model and then return it's response to the user? I would like it to have fast response times and maybe handle multiple requests at once. The client script is :

import os

import argparse
from argparse import RawTextHelpFormatter

from grpc.beta import implementations
import numpy as np
from PIL import Image
import tensorflow as tf

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

from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as vis_util
from object_detection.core.standard_fields import \
    DetectionResultFields as dt_fields

tf.logging.set_verbosity(tf.logging.INFO)

def load_image_into_numpy_array(input_image):
    image = Image.open(input_image)
    (im_width, im_height) = image.size
    image_arr = np.array(image.getdata()).reshape(
        (im_height, im_width, 3)).astype(np.uint8)
    image.close()
    return image_arr

def load_input_tensor(input_image):
    image_np = load_image_into_numpy_array(input_image)
    image_np_expanded = np.expand_dims(image_np, axis=0).astype(np.uint8)
    tensor = tf.contrib.util.make_tensor_proto(image_np_expanded)
    return tensor

def main(args):
    host, port = args.server.split(':')
    channel = implementations.insecure_channel(host, int(port))._channel
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    request = predict_pb2.PredictRequest()
    request.model_spec.name = args.model_name

    input_tensor = load_input_tensor(args.input_image)
    request.inputs['inputs'].CopyFrom(input_tensor)

    result = stub.Predict(request, 60.0)
    image_np = load_image_into_numpy_array(args.input_image)

    output_dict = {}
    output_dict[dt_fields.detection_classes] = np.squeeze(
        result.outputs[dt_fields.detection_classes].float_val).astype(np.uint8)
    output_dict[dt_fields.detection_boxes] = np.reshape(
        result.outputs[dt_fields.detection_boxes].float_val, (-1, 4))
    output_dict[dt_fields.detection_scores] = np.squeeze(
        result.outputs[dt_fields.detection_scores].float_val)

    category_index = label_map_util.create_category_index_from_labelmap(args.label_map,
                                                                        use_display_name=True)

    vis_util.visualize_boxes_and_labels_on_image_array(image_np,
      output_dict[dt_fields.detection_boxes],
      output_dict[dt_fields.detection_classes],
      output_dict[dt_fields.detection_scores],
      category_index,
      instance_masks=None,
      use_normalized_coordinates=True,
      line_thickness=8)
    output_img = Image.fromarray(image_np.astype(np.uint8))
    base_filename = os.path.splitext(os.path.basename(args.input_image))[0]
    output_image_path = os.path.join(args.output_directory, base_filename + "_output.jpg")
    tf.logging.info('Saving labeled image: %s' % output_image_path)
    output_img.save(output_image_path)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Object detection grpc client.",
                                     formatter_class=RawTextHelpFormatter)
    parser.add_argument('--server',
                        type=str,
                        required=True,
                        help='PredictionService host:port')
    parser.add_argument('--model_name',
                        type=str,
                        required=True,
                        help='Name of the model')
    parser.add_argument('--input_image',
                        type=str,
                        required=True,
                        help='Path to input image')
    parser.add_argument('--output_directory',
                        type=str,
                        required=True,
                        help='Path to output directory')
    parser.add_argument('--label_map',
                        type=str,
                        required=True,
                        help='Path to label map file')

    args = parser.parse_args()
    main(args) 

I am thinking of building a microservice with docker in it containing tensorflow, tensorflow serving api and the client script.

Update 1: I tried using the grpc client and ran into issues. Since I used kubeflow, the url for requests is of the form http://HOST:8000/model/:predict. But the client script dosen't seem to accept this url format. It accepts only HOST:PORT NUMBER format and I am getting an error

Traceback (most recent call last):
  File "object_detection_grpc_client.py", line 104, in <module>
    main(args)
  File "object_detection_grpc_client.py", line 41, in main
    stub = prediction_service_pb2_grpc.PredictionServiceStub('http://A.B.C.D:8000/model/my-model:predict')
  File "/usr/local/lib/python3.5/dist-packages/tensorflow_serving/apis/prediction_service_pb2_grpc.py", line 40, in __init__
    self.Classify = channel.unary_unary(
AttributeError: 'str' object has no attribute 'unary_unary'

When I use only A.B.C.D:8000 as the server parameter value, I get the error:

Traceback (most recent call last):
  File "object_detection_grpc_client.py", line 104, in <module>
    main(args)
  File "object_detection_grpc_client.py", line 48, in main
    result = stub.Predict(request, 60.0)
  File "/usr/local/lib/python3.5/dist-packages/grpc/_channel.py", line 550, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/usr/local/lib/python3.5/dist-packages/grpc/_channel.py", line 467, in _end_unary_response_blocking
    raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with:
    status = StatusCode.UNAVAILABLE
    details = "Socket closed"
    debug_error_string = "{"created":"@1550755989.677583779","description":"Error received from peer","file":"src/core/lib/surface/call.cc","file_line":1036,"grpc_message":"Socket closed","grpc_status":14}"
>

I have directly used predict protobufs available in this repository. How do I modify my code to resolve the issues?

-- zinngg
docker
google-cloud-platform
kubernetes
tensorflow
tensorflow-serving

1 Answer

3/4/2019

If you are using grpc client, your host format should be HOST:PORT. And http://HOST:PORT/model is rest_api format. Make sure your port is right. Could you show the way you start tf-serving?

-- zzachimonde
Source: StackOverflow