TensorFlow Serving Object Detection

Viewed 76

I'm having trouble serving a tensorflow object detection model. I trained a model from the tensorflow model repo, and have set up a tensorflow-serving instance. But when I make a request, there's an issue with dimensionality. I'm using the the tolist() method to convert the numpy array of the image into something that the json encoder can use. The tolist() function appears to maintain the structure of the numpy array by having the list recursive inside each other, so I'm not sure where tf-serving is getting a tensor with shape [339450,3]. Do I have to specify the shape of the image when I make the request?

The error:

Data: {"signature_name": "serving_default", "instances": ... 58, 63], [35, 59, 63], [37, 58, 63], [43, 67, 71]]]}
{'error': 'Specified a list with shape [?,?,3] from a tensor with shape [339450,3]\n\t [[{{function_node __inference_call_func_9686}}{{node map/TensorArrayUnstack/TensorListFromTensor}}]]'}

The code to make the request:

import requests
import json
from PIL import Image
import numpy

# Load image
img = Image.open("Hilarious-Car-License-Plates-1.jpg")
img_np = numpy.array(img.getdata())
img_np.resize(tuple([1] + list(img_np.shape)))
data = json.dumps({"signature_name": "serving_default", "instances": img_np.tolist()})
print('Data: {} ... {}'.format(data[:50], data[len(data)-52:]))

headers = {"content-type": "application/json"}
json_response = requests.post('http://localhost:8501/v1/models/plate_detect:predict', data=data, headers=headers)
response = json.loads(json_response.text)

print(response)

Model metadata:

{
"model_spec":{
 "name": "plate_detect",
 "signature_name": "",
 "version": "1"
}
,
"metadata": {"signature_def": {
 "signature_def": {
  "serving_default": {
   "inputs": {
    "input_tensor": {
     "dtype": "DT_UINT8",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "-1",
        "name": ""
       },
       {
        "size": "-1",
        "name": ""
       },
       {
        "size": "3",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "serving_default_input_tensor:0"
    }
   },
   "outputs": {
    "detection_boxes": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "100",
        "name": ""
       },
       {
        "size": "4",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:1"
    },
    "raw_detection_boxes": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "1917",
        "name": ""
       },
       {
        "size": "4",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:6"
    },
    "detection_scores": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "100",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:4"
    },
    "raw_detection_scores": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "1917",
        "name": ""
       },
       {
        "size": "2",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:7"
    },
    "detection_anchor_indices": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "100",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:0"
    },
    "detection_multiclass_scores": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "100",
        "name": ""
       },
       {
        "size": "2",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:3"
    },
    "detection_classes": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       },
       {
        "size": "100",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:2"
    },
    "num_detections": {
     "dtype": "DT_FLOAT",
     "tensor_shape": {
      "dim": [
       {
        "size": "1",
        "name": ""
       }
      ],
      "unknown_rank": false
     },
     "name": "StatefulPartitionedCall:5"
    }
   },
   "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": ""
  }
 }
}
}
}
1 Answers

I managed to fix this by switching to https://tfhub.dev/tensorflow/ssd_mobilenet_v2/2

I saved my model like this:

MODULE_HANDLE = 'https://tfhub.dev/tensorflow/ssd_mobilenet_v2/2'
ts = int(time.time())
detector = hub.load(MODULE_HANDLE)
file_path = "./models/object_detector/{}/".format(str(ts))
tf.saved_model.save(detector, file_path)
Related