Prediction failed: contents must be scalar - tensorflow

I have successfully trained, exported and uploaded my 'retrained_graph.pb' to ML Engine. My export script is as follows:
import tensorflow as tf
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
from tensorflow.python.saved_model import builder as saved_model_builder
input_graph = 'retrained_graph.pb'
saved_model_dir = 'my_model'
with tf.Graph().as_default() as graph:
# Read in the export graph
with tf.gfile.FastGFile(input_graph, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
# Define SavedModel Signature (inputs and outputs)
in_image = graph.get_tensor_by_name('DecodeJpeg/contents:0')
inputs = {'image_bytes': tf.saved_model.utils.build_tensor_info(in_image)}
out_classes = graph.get_tensor_by_name('final_result:0')
outputs = {'prediction_bytes': tf.saved_model.utils.build_tensor_info(out_classes)}
signature = tf.saved_model.signature_def_utils.build_signature_def(
inputs=inputs,
outputs=outputs,
method_name='tensorflow/serving/predict'
)
with tf.Session(graph=graph) as sess:
# Save out the SavedModel.
b = saved_model_builder.SavedModelBuilder(saved_model_dir)
b.add_meta_graph_and_variables(sess,
[tf.saved_model.tag_constants.SERVING],
signature_def_map={'serving_default': signature})
b.save()
I build my prediction Json using the following:
# Copy the image to local disk.
gsutil cp gs://cloud-ml-data/img/flower_photos/tulips/4520577328_a94c11e806_n.jpg flower.jpg
# Create request message in json format.
python -c 'import base64, sys, json; img = base64.b64encode(open(sys.argv[1], "rb").read()); print json.dumps({"image_bytes": {"b64": img}}) ' flower.jpg &> request.json
# Call prediction service API to get classifications
gcloud ml-engine predict --model ${MODEL_NAME} --json-instances request.json
However this fails with the response:
{
"error": "Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details=\"contents must be scalar, got shape [1]\n\t [[Node: Deco
deJpeg = DecodeJpeg[_output_shapes=[[?,?,3]], acceptable_fraction=1, channels=3, dct_method=\"\", fancy_upscaling=true, ratio=1, try_recover_truncated=false, _device=\"/job:l
ocalhost/replica:0/task:0/device:CPU:0\"](_arg_DecodeJpeg/contents_0_0)]]\")"
}
Any help appreciated, I'm so close I can taste it :D

Why do you have this line:
in_image = graph.get_tensor_by_name('DecodeJpeg/contents:0')?
inputs = {'image_bytes': tf.saved_model.utils.build_tensor_info(in_image)}
The shape here is scalar. Can you make sure you create input with shape [None]
https://github.com/GoogleCloudPlatform/cloudml-samples/blob/master/flowers/trainer/model.py#L364

The server will decode and batch all the inputs. So the input to your graph is essentially [base64_decode("xxx")] where you actually want to feed base64_decode("xxx") since the op takes a string type tensor. Server-side assumes the shape of input as [None, ] i.e. the first dimension can be anything for batching. In your case, [None]. You might want to create a tensor of that shape and then feed that into the op.

Related

How to run inference using Tensorflow 2.2 pb file?

I followed the website: https://leimao.github.io/blog/Save-Load-Inference-From-TF2-Frozen-Graph/
However, I still do not know how to run inference with frozen_func(see my code below).
Please advise how to run inference using pb file in TensorFlow 2.2. Thanks.
import tensorflow as tf
def wrap_frozen_graph(graph_def, inputs, outputs, print_graph=False):
def _imports_graph_def():
tf.compat.v1.import_graph_def(graph_def, name="")
wrapped_import = tf.compat.v1.wrap_function(_imports_graph_def, [])
import_graph = wrapped_import.graph
print("-" * 50)
print("Frozen model layers: ")
layers = [op.name for op in import_graph.get_operations()]
if print_graph == True:
for layer in layers:
print(layer)
print("-" * 50)
return wrapped_import.prune(
tf.nest.map_structure(import_graph.as_graph_element, inputs),
tf.nest.map_structure(import_graph.as_graph_element, outputs))
# Load frozen graph using TensorFlow 1.x functions
with tf.io.gfile.GFile("/content/drive/My Drive/Model_file/froze_graph.pb", "rb") as f:
graph_def = tf.compat.v1.GraphDef()
loaded = graph_def.ParseFromString(f.read())
# Wrap frozen graph to ConcreteFunctions
frozen_func = wrap_frozen_graph(graph_def=graph_def,
inputs=["wav_data:0"],
outputs=["labels_softmax:0"],
print_graph=True)
You can use tf.graph_util.import_graph_def inside a tf.function to do that. For example, suppose you make a test GraphDef file my_func.pb like this:
import tensorflow as tf
# Test function to make into a GraphDef file
#tf.function
def my_func(x):
return tf.square(x, name='y')
# Get graph
g = my_func.get_concrete_function(tf.TensorSpec(None, tf.float32)).graph
# Write to file
tf.io.write_graph(g, '.', 'my_func.pb', as_text=False)
You can then load it and use it like this:
import tensorflow as tf
from tensorflow.core.framework.graph_pb2 import GraphDef
# Load GraphDef
with open('my_func.pb', 'rb') as f:
gd = GraphDef()
gd.ParseFromString(f.read())
#tf.function
def my_func2(x):
# Ensure the input is a tensor of the right type
x = tf.convert_to_tensor(x, tf.float32)
# Import the graph giving x as input and getting the output y
y = tf.graph_util.import_graph_def(
gd, input_map={'x:0': x}, return_elements=['y:0'])[0]
return y
tf.print(my_func2(2))
# 4

How to load model back from cpkt, .meta, .index and .pb files for Mobilenet v3?

I have downloaded checkpoints along with model for Mobilenet v3. After extraction of rar file, I get two folders and two other files. Directory looks like following
Main Folder
ema (folder)
checkpoint
model-x.data-00000-of-00001
model-x.index
model-x.meta
pristine (folder)
model.ckpt-y.data-00000-of-00001
model.ckpt-y.index
model.ckpt-y.meta
.pb
.tflite
I have tried many codes among which few are below.
import tensorflow as tf
from tensorflow.python.platform import gfile
model_path = "./weights/v3-large-minimalistic_224_1.0_uint8/model.ckpt-3868848"
detection_graph = tf.Graph()
with tf.Session(graph=detection_graph) as sess:
# Load the graph with the trained states
loader = tf.train.import_meta_graph(model_path+'.meta')
loader.restore(sess, model_path)
The above code results in following error
Node {{node batch_processing/distort_image/switch_case/indexed_case}} of type Case has '_lower_using_switch_merge' attr set but it does not support lowering.
I tried following code:
import tensorflow as tf
import sys
sys.path.insert(0, 'models/research/slim')
from nets.mobilenet import mobilenet_v3
tf.reset_default_graph()
file_input = tf.placeholder(tf.string, ())
image = tf.image.decode_jpeg(tf.read_file('test.jpg'))
images = tf.expand_dims(image, 0)
images = tf.cast(images, tf.float32) / 128. - 1
images.set_shape((None, None, None, 3))
images = tf.image.resize_images(images, (224, 224))
model = mobilenet_v3.wrapped_partial(mobilenet_v3.mobilenet,
new_defaults={'scope': 'MobilenetEdgeTPU'},
conv_defs=mobilenet_v3.V3_LARGE_MINIMALISTIC,
depth_multiplier=1.0)
with tf.contrib.slim.arg_scope(mobilenet_v3.training_scope(is_training=False)):
logits, endpoints = model(images)
ema = tf.train.ExponentialMovingAverage(0.999)
vars = ema.variables_to_restore()
print(vars)
with tf.Session() as sess:
tf.train.Saver(vars).restore(sess, './weights/v3-large-minimalistic_224_1.0_uint8/saved_model.pb')
tf.train.Saver().save(sess, './weights/v3-large-minimalistic_224_1.0_uint8/pristine/model.ckpt')
The above code generates following error:
Unable to open table file ./weights/v3-large-minimalistic_224_1.0_uint8/saved_model.pb: Data loss: not an sstable (bad magic number): perhaps your file is in a different file format and you need to use a different restore operator?
[[node save/RestoreV2 (defined at <ipython-input-11-1531bbfd84bb>:29) ]]
How can I load Mobilenet v3 model along with the checkpoints and use it for my data?
try this
with tf.contrib.slim.arg_scope(mobilenet_v3.training_scope(is_training=False)):
logits, endpoints = mobilenet_v3.large_minimalistic(images)
instead of
model = mobilenet_v3.wrapped_partial(mobilenet_v3.mobilenet,
new_defaults={'scope': 'MobilenetEdgeTPU'},
conv_defs=mobilenet_v3.V3_LARGE_MINIMALISTIC,
depth_multiplier=1.0)
with tf.contrib.slim.arg_scope(mobilenet_v3.training_scope(is_training=False)):
logits, endpoints = model(images)

Get predictions from deployed TF for poet model in google cloud

I deployed my retrained TF for poet model in google cloud. currently, I am trying to get predictions from that. But it gives the following error.
"error": "Prediction failed: Error during model execution: AbortionError(code=StatusCode.INVALID_ARGUMENT, details=\"contents must be scalar, got shape [1]\n\t [[{{node DecodeJpeg}}]]\")"
Following code, I used to get serving model
import tensorflow as tf
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
from tensorflow.python.saved_model import builder as saved_model_builder
input_graph = 'retrained_graph.pb'
saved_model_dir = 'my_model'
with tf.Graph().as_default() as graph:
# Read in the export graph
with tf.gfile.FastGFile(input_graph, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
# Define SavedModel Signature (inputs and outputs)
in_image = graph.get_tensor_by_name('DecodeJpeg/contents:0')
inputs = {'image_bytes': tf.saved_model.utils.build_tensor_info(in_image)}
out_classes = graph.get_tensor_by_name('final_result:0')
outputs = {'prediction': tf.saved_model.utils.build_tensor_info(out_classes)}
signature = tf.saved_model.signature_def_utils.build_signature_def(
inputs=inputs,
outputs=outputs,
method_name='tensorflow/serving/predict'
)
with tf.Session(graph=graph) as sess:
# Save out the SavedModel.
b = saved_model_builder.SavedModelBuilder(saved_model_dir)
b.add_meta_graph_and_variables(sess,[tf.saved_model.tag_constants.SERVING],signature_def_map={'serving_default': signature})
b.save()
request.json generating code
python -c 'import base64, sys, json; img = base64.b64encode(open(sys.argv[1], "rb").read()); print json.dumps({"image_bytes": {"b64": img}})' test.jpg &> request.json
You can try:
{"instances": [{"image_bytes": {"b64": encoded_string}, "key": "0"}]}

Keras model to Tensorflow to input b64 encoded data instead of numpy ml-engine predict

I am trying to convert a keras model to use it for predictions on google cloud's ml-engine. I have a pre-trained classifier that takes in a numpy array as input. The normal working data I send to model.predict is named input_data.
I convert it to base 64 and dump it to a json file using the following few lines:
data = {}
data['image_bytes'] = [{'b64':base64.b64encode(input_data.tostring())}]
with open('weights/keras/example.json', 'w') as outfile:
json.dump(data, outfile)
Now, I try to create the TF model from my existing model:
from keras.models import model_from_json
import tensorflow as tf
from keras import backend as K
from tensorflow.python.saved_model import builder as saved_model_builder
from tensorflow.python.saved_model import utils
from tensorflow.python.saved_model import tag_constants, signature_constants
from tensorflow.python.saved_model.signature_def_utils_impl import build_signature_def, predict_signature_def
init = tf.global_variables_initializer()
with tf.Session() as sess:
K.set_session(sess)
sess.run(init)
print("Keras model & weights loading...")
K.set_learning_phase(0)
with open(json_file_path, 'r') as file_handle:
model = model_from_json(file_handle.read())
model.load_weights(weight_file_path)
builder = saved_model_builder.SavedModelBuilder(export_path)
raw_byte_strings = tf.placeholder(dtype=tf.string, shape=[None], name='source')
decode = lambda raw_byte_str: tf.decode_raw(raw_byte_str, tf.float32)
input_images = tf.map_fn(decode, raw_byte_strings)
print(input_images)
signature = predict_signature_def(inputs={'image_bytes': input_images},
outputs={'output': model.output})
builder.add_meta_graph_and_variables(
sess=sess,
tags=[tag_constants.SERVING],
signature_def_map={
signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signature
}
)
builder.save()
When I try to test this locally I get the following error:
ERROR:root:Exception during running the graph: You must feed a value for placeholder tensor 'input_1' with dtype float and shape [?,473,473,3]
[[Node: input_1 = Placeholder[dtype=DT_FLOAT, shape=[?,473,473,3], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]
Help?

Convert a graph proto (pb/pbtxt) to a SavedModel for use in TensorFlow Serving or Cloud ML Engine

I've been following the TensorFlow for Poets 2 codelab on a model I've trained, and have created a frozen, quantized graph with embedded weights. It's captured in a single file - say my_quant_graph.pb.
Since I can use that graph for inference with the TensorFlow Android inference library just fine, I thought I could do the same with Cloud ML Engine, but it seems it only works on a SavedModel model.
How can I simply convert a frozen/quantized graph in a single pb file to use on ML engine?
It turns out that a SavedModel provides some extra info around a saved graph. Assuming a frozen graph doesn't need assets, then it needs only a serving signature specified.
Here's the python code I ran to convert my graph to a format that Cloud ML engine accepted. Note I only have a single pair of input/output tensors.
import tensorflow as tf
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
export_dir = './saved'
graph_pb = 'my_quant_graph.pb'
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
with tf.gfile.GFile(graph_pb, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sigs = {}
with tf.Session(graph=tf.Graph()) as sess:
# name="" is important to ensure we don't get spurious prefixing
tf.import_graph_def(graph_def, name="")
g = tf.get_default_graph()
inp = g.get_tensor_by_name("real_A_and_B_images:0")
out = g.get_tensor_by_name("generator/Tanh:0")
sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
tf.saved_model.signature_def_utils.predict_signature_def(
{"in": inp}, {"out": out})
builder.add_meta_graph_and_variables(sess,
[tag_constants.SERVING],
signature_def_map=sigs)
builder.save()
There is sample with multiple outputs nodes:
# Convert PtotoBuf model to saved_model, format for TF Serving
# https://cloud.google.com/ai-platform/prediction/docs/exporting-savedmodel-for-prediction
import shutil
import tensorflow.compat.v1 as tf
from tensorflow.python.saved_model import signature_constants
from tensorflow.python.saved_model import tag_constants
export_dir = './1' # TF Serving supports run different versions of same model. So we put current model to '1' folder.
graph_pb = 'frozen_inference_graph.pb'
# Clear out folder
shutil.rmtree(export_dir, ignore_errors=True)
builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
with tf.io.gfile.GFile(graph_pb, "rb") as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
sigs = {}
with tf.Session(graph=tf.Graph()) as sess:
# Prepare input and outputs of model
tf.import_graph_def(graph_def, name="")
g = tf.get_default_graph()
image_tensor = g.get_tensor_by_name("image_tensor:0")
num_detections = g.get_tensor_by_name("num_detections:0")
detection_scores = g.get_tensor_by_name("detection_scores:0")
detection_boxes = g.get_tensor_by_name("detection_boxes:0")
detection_classes = g.get_tensor_by_name("detection_classes:0")
sigs[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY] = \
tf.saved_model.signature_def_utils.predict_signature_def(
{"input_image": image_tensor},
{ "num_detections": num_detections,
"detection_scores": detection_scores,
"detection_boxes": detection_boxes,
"detection_classes": detection_classes})
builder.add_meta_graph_and_variables(sess,
[tag_constants.SERVING],
signature_def_map=sigs)
builder.save()