Tensor name has no shape information ERROR when predicting with tensorflow serving - tensorflow

I'm using tensorflow serving to serve a savedmodel. I have two signatures: 1st outputting keras model.output and the 2nd outputting post processing of model.output. When I try a predict call of the 2nd signature on tensorflow serving it is giving me an error { "error": "Tensor name: prediction has no shape information " }
this is the code to build the savedmodel
shape1 = 92
shape2 = 92
reg=0.000001
learning_rate=0.001
sess = tf.Session()
K.set_session(sess)
K._LEARNING_PHASE = tf.constant(0)
K.set_learning_phase(0)
#preprocessing
x_input = tf.placeholder(tf.string, name='x_input', shape=[None])
reshaped = tf.reshape(x_input, shape=[])
image = tf.image.decode_jpeg(reshaped, channels=3)
image2 = tf.expand_dims(image,0)
resized = tf.image.resize_images(image2, (92,92))
meaned = tf.math.subtract(resized, tf.constant(116.0))
normalized = tf.math.divide(meaned, tf.constant(66.0))
#keras model
model = tf.keras.Sequential()
model.add(InputLayer(input_tensor=normalized))
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Conv2D(32, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.1))
model.add(Conv2D(64, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.1))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.2))
model.add(Conv2D(128, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.2))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(256, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.3))
model.add(Conv2D(256, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.5))
model.add(Dense(256, activation='relu', kernel_regularizer=l2(reg)))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer=tf.train.RMSPropOptimizer(learning_rate=learning_rate),
metrics=['accuracy'])
#post processing to output label
pred = tf.gather_nd(model.output, (0,0))
label = tf.cond(pred > 0.5, lambda: tf.constant('Dog', shape=[]), lambda: tf.constant('Cat', shape=[]))
model.load_weights(r'./checkpoints/4.ckpt')
export_path = './saved_models/1'
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init_op)
model.load_weights(r'./checkpoints/4.ckpt')
if os.path.isdir(export_path):
print('\nAlready saved a model, cleaning up\n')
print(subprocess.run(['rm', '-r', export_path]))
#first signature(this works)
x_info = tf.saved_model.utils.build_tensor_info(x_input)
y_info = tf.saved_model.utils.build_tensor_info(model.output)
sigmoid_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')
#2nd signature(this doesn't work)
x_info = tf.saved_model.utils.build_tensor_info(x_input)
y_info = tf.saved_model.utils.build_tensor_info(label)
label_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')
builder = tf.saved_model.builder.SavedModelBuilder(export_path)
legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')
builder.add_meta_graph_and_variables(sess=sess,
tags=["serve"],
signature_def_map={'sigmoid': sigmoid_signature, 'label': label_signature})
builder.save()
this is code to call tf serving
imgs = ['./Dog/' + img for img in imgs]
img = open('./Dog/3.jpg', 'rb').read()
img = base64.b64encode(img).decode('utf-8')
data = json.dumps(
{"signature_name": "label",
"instances": [
{'image': {'b64': img}}
]
}
)
json_response = requests.post('http://localhost:8501/v1/models/pet:predict', data=data)
print(json_response.text)
Instead of getting a response of {"predictions": "Dog"}, i am getting an error { "error": "Tensor name: prediction has no shape information " }

I managed to fix this. I used tf.reshape on what i wanted to output and passed that into the signature builder.
#post processing to output label
pred = tf.gather_nd(model.output, (0,0))
label = tf.cond(pred > 0.5, lambda: tf.constant('Dog', shape=[]), lambda: tf.constant('Cat', shape=[]))
label_reshaped = tf.reshape(label, [None])
...
#2nd signature(this doesn't work)
x_info = tf.saved_model.utils.build_tensor_info(x_input)
y_info = tf.saved_model.utils.build_tensor_info(label_reshaped)
label_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')

Reading the tensorflow serving documentation, you'll see that there are two ways to specify input tensors in your request, the row format (using instances like your example), and the column format (using inputs).
Since the row format requires that all inputs and outputs have the same 0th dimension, if you did not export the model with explicit output shape, you cannot use the row format.
Therefore, in your case (without having to re-export the model with explicit reshaping, like the other answer has provided), you can send this payload instead
data = json.dumps(
{
"signature_name": "label",
"inputs": {'image': {'b64': img}}
}
)
On the other hand, keep in mind that if you do want to send multiple b64 encoded images, your best bet would be to use the row format with multiple instances (such as if you want to run batch predict on multiple images).

Related

Training Multi Class Image classification model

I am trying to create a model using Tensorflow and Python, I get the data from a folder on my pc
The Folder Structure
An Example from the data
Almost all data are the same size [237 items,223 items,495 items,387 items,301 items]
That's how I load my data:
lables = {'Basic T-shrit':0, 'Bikini Bottom':1, 'Cargo Pants':2, 'Jeans':3, 'Oversize T-Shirt':4}
#Data
train_datagen = ImageDataGenerator(rescale=1/256)
train_generator = train_datagen.flow_from_directory(
'Dataset', # This is the source directory for training images
target_size=(256, 256), # All images will be resized to 200 x 200
batch_size=batch_size,
# Specify the classes explicitly
classes = lables,
# Since we use categorical_crossentropy loss, we need categorical labels
class_mode='categorical')
That's a model I tried:
#Model
model = Sequential()
model.add(Conv2D(32, (3,3), 1, activation='relu', input_shape=(image_width,image_height,3)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(32,3,3, activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(64,3,3, activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Conv2D(64,3,3, activation='relu'))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(categorys_size, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer="adam",
metrics=['acc'])
Then I start the learning process:
model.fit_generator(train_generator,
steps_per_epoch=epoch_steps,
epochs=Epoch,
validation_data=train_generator)
But it's not working good, The model sees the oversize shirt and normal shirt the same and any kind of pants as jeans
Model Train result
Then I tested this model:
model = tf.keras.models.Sequential([
keras.layers.Conv2D(32, kernel_size=(5, 5), activation=tf.keras.activations.relu, input_shape=IMAGE_SHAPE),
keras.layers.MaxPooling2D(pool_size=(2, 2)),
keras.layers.BatchNormalization(axis = 1),
keras.layers.Dropout(0.22),
keras.layers.Conv2D(32, kernel_size=(5, 5), activation=tf.keras.activations.relu),
keras.layers.AveragePooling2D(pool_size=(2, 2)),
keras.layers.BatchNormalization(axis = 1),
keras.layers.Dropout(0.25),
keras.layers.Conv2D(32, kernel_size=(4, 4), activation=tf.keras.activations.relu),
keras.layers.AveragePooling2D(pool_size=(2, 2)),
keras.layers.BatchNormalization(axis = 1),
keras.layers.Dropout(0.15),
keras.layers.Conv2D(32, kernel_size=(3, 3), activation=tf.keras.activations.relu),
keras.layers.AveragePooling2D(pool_size=(2, 2)),
keras.layers.BatchNormalization(axis = 1),
keras.layers.Dropout(0.15),
keras.layers.Flatten(),
keras.layers.Dense(256, activation=tf.keras.activations.relu,kernel_regularizer=keras.regularizers.l2(0.001)),
#keras.layers.Dropout(0.25),
keras.layers.Dense(64, activation=tf.keras.activations.relu,kernel_regularizer=keras.regularizers.l2(0.001)),
#keras.layers.Dropout(0.1),
keras.layers.Dense(len(lables), activation=tf.keras.activations.softmax)])
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['accuracy'])
Then I start learning:
#Start Learning
checkpoint_path="/chk/cp-{epoch:04d}.ckpt"
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
save_weights_only=True,
verbose=1,
period=10)
model.fit(train,
epochs=Epoch,callbacks = [cp_callback],
validation_data=val,verbose=1)
And that's how I load the data
data = tf.keras.utils.image_dataset_from_directory('Dataset',labels = 'inferred',image_size = (192,192))
data_iterator = data.as_numpy_iterator()
batch = data_iterator.next()
fig, ax = plt.subplots(ncols=4, figsize=(20,20))
for idx, img in enumerate(batch[0][:4]):
ax[idx].imshow(img.astype(int))
ax[idx].title.set_text(batch[1][idx])
#Scale Data
data = data.map(lambda x,y: (x/192, y))
data.as_numpy_iterator().next()
train_size = int(len(data)*.7)
val_size = int(len(data)*.2)
test_size = int(len(data)*.1)
print(train_size)
train = data.take(train_size)
val = data.skip(train_size).take(val_size)
test = data.skip(train_size+val_size).take(test_size)
What I am doing wrong? and is the data I collected good enough for what I am trying to do? Am I missing something ?
Thanks

Operation type in full integer quantization method in TensorFlowLite

I want to apply Post-Training Quantization (Full integer) using TensorFlow model optimization package on a pre-trained model (LeNet5).
https://www.tensorflow.org/model_optimization/guide/quantization/post_training
model = Sequential()
model._name = 'LeNet5'
model.add(tf.keras.layers.InputLayer(input_shape=(28, 28)))
model.add(tf.keras.layers.Reshape(target_shape=(28, 28, 1)))
model.add(
Conv2D(6, kernel_size=(5, 5), strides=(1, 1), activation='tanh', padding='same'))
model.add(AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
model.add(Conv2D(16, kernel_size=(5, 5), strides=(1, 1), activation='tanh', padding='valid'))
model.add(AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'))
model.add(Flatten())
model.add(Dense(120, activation='tanh'))
model.add(Dense(84, activation='tanh'))
model.add(Dense(10, activation='softmax'))
and using this code I have applied Full Integer Post-Training Quantization:
mnist_train, _ = tf.keras.datasets.mnist.load_data()
images = tf.cast(mnist_train[0], tf.float32) / 255.0
mnist_ds = tf.data.Dataset.from_tensor_slices((images)).batch(1)
def representative_data_gen():
for input_value in mnist_ds.take(100):
yield [input_value]
converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]
converter.representative_dataset = representative_data_gen
converter.allow_custom_ops = True
converter.target_spec.supported_types = [tf.int8]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
full_integer_quantization_model = converter.convert()
open("tflite_model.tflite", "wb").write(full_integer_quantization_model)
It works fine in tense of accuracy but when I try to print the data type of each layer (operation, like conv, activation, bias), I see that some of operations are in int32 instead of int8.
I don't know why?
How does TFLite decide to do some ops in int32 and some in int8?
Is it possible to control this feature (is it an option) in TFLite and perform all operations as int8?
Have you taken a look at this https://www.tensorflow.org/lite/performance/quantization_spec
?
Bias values have 32-bits width

Conv2D is incompatible with the layer in a GAN

I am developing a GAN using the Mnist dataset. I have developed the Generator and Discriminator. However, when I combine them together I get this error: Input 0 of layer "conv2d" is incompatible with the layer: expected axis -1 of input shape to have value 1, but received input with shape (None, 57, 57, 1024). Does anyone know why this happens? Do I have to add something else?
The preprocessing:
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.reshape(60000, 28, 28, 1)
x_test = x_test.reshape(10000, 28, 28, 1)
x_train = x_train.astype('float32')/255
x_test = x_test.astype('float32')/255
img_rows, img_cols = 28, 28
channels = 1
img_shape = (img_rows, img_cols, channels)
The Generator:
def generator():
model = Sequential()
model.add(Conv2DTranspose(32, (3,3), strides=(2, 2), activation='relu', use_bias=False,
input_shape=img_shape))
model.add(BatchNormalization(momentum=0.3))
model.add(Conv2DTranspose(64,(3,3),strides=(2,2), activation='relu', padding='same',
use_bias=False))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(LeakyReLU(alpha=0.2))
model.add(Conv2DTranspose(64,(3,3),strides=(2,2), activation='relu', padding='same',
use_bias=False))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(BatchNormalization(momentum=0.3))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(512, activation=LeakyReLU(alpha=0.2)))
model.add(BatchNormalization(momentum=0.7))
model.add(Dense(1024, activation='tanh'))
model.summary()
model.compile(loss=keras.losses.binary_crossentropy, optimizer=Adam(learning_rate=0.02))
return model
generator = generator()
The Discriminator:
def discriminator():
model = Sequential()
model.add(Conv2D(32, (5,5), strides=(2, 2), activation='relu', use_bias=False,
input_shape=img_shape))
model.add(BatchNormalization(momentum=0.3))
model.add(Conv2D(64,(5,5),strides=(2,2), activation='relu', padding='same',
use_bias=False))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(LeakyReLU(alpha=0.2))
model.add(Conv2D(64,(5,5),strides=(2,2), activation='relu', padding='same',
use_bias=False))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.5))
model.add(BatchNormalization(momentum=0.3))
model.add(LeakyReLU(alpha=0.2))
model.add(Dense(512, activation=LeakyReLU(alpha=0.2)))
model.add(BatchNormalization(momentum=0.7))
model.add(Dense(1024, activation='tanh'))
model.summary()
model.compile(loss=keras.losses.binary_crossentropy, optimizer=Adam(learning_rate=0.02))
return model
discriminator = discriminator()
Both models combined (Where I get the error):
def GAN(generator, discriminator):
model = Sequential()
model.add(generator)
discriminator.trainable = False
model.add(discriminator)
model.summary()
model.compile()
return model
gan = GAN(generator, discriminator)
Your generator needs to produce images, thus the output shape of the generator must be the same shape as the images. The activation also must be compatible with the range in the images. I don't think your images go from -1 to +1, so you should not use "tanh". You must choose an activation compatible with the images.
Last generator layer:
Dense(img_shape[-1], ...)
Your discriminator needs to say whether the images are true or false, thus its output must have one value only, 0 or 1.
Last discriminator layer:
Dense(1, activation="sigmoid")

Combination of ResNet and ConvNet

I have prepared a CNN model for image colorization:
"""Encoder - Input grayscale image (L)"""
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(256, 256, 1)))
...
"""Latent space"""
model.add(Conv2D(512, (3,3), activation='relu', padding='same'))
"""Decoder - output (A,B)"""
...
model.add(Conv2D(2, (3, 3), activation='tanh', padding='same'))
Now i want to use ResNet as feature extractor and merge the output to Latent space.
I have already imported ResNet model as:
resnet50_imagnet_model = tf.keras.applications.resnet.ResNet50(weights = "imagenet",
include_top=False,
input_shape = (256, 256, 3),
pooling='max')
Encoder
"""Encoder - Input grayscale image (L)"""
encoder = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', input_shape=(256, 256, 1)))
...
Decoder
decoder = """Decoder - output (A,B)"""
...
Use tf.keras.Sequential() to merge all models
comb_model = tf.keras.Sequential(
[encoder,resnet50_imagnet_model, decoder]
)

how to apply multi input image to Unet for segmentation?

I am a newbie in machine learning.
Actually, I used my unet code for image segmentation using one input image slice (192x912) and one output mask image (192x192)
My Unet code is contained several CNN layer and I usually used one input image (192x912) and one its corresponding mask binary image for training.
Code related with above explanation is as below.
def get_unet():
inputs = Input((img_rows, img_cols, 1))
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
drop1 = Dropout(0.2)(pool1)
conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(drop1)
conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
drop2 = Dropout(0.2)(pool2)
'''''''
return model
model.fit(imgs_train, imgs_mask_train, batch_size=32, epochs=100, verbose=2, shuffle=True, validation_split=0.1, callbacks=[model_checkpoint])
it works well. But, now, I would like to use multi input image when I train my network. So, I add another train data and edit my code like below.
def get_unet():
inputs = Input((img_rows, img_cols, 1))
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
drop1 = Dropout(0.2)(pool1)
conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(drop1)
conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
drop2 = Dropout(0.2)(pool2)
'''''''
return model
model.fit([imgs_train, imgs_other_train], imgs_mask_train, batch_size=32, epochs=100, verbose=2, shuffle=True, validation_split=0.1, callbacks=[model_checkpoint])
but when I run the train code, I got error message as below.
"ValueError: Error when checking model input: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 1 array(s), but instead got the following list of 2 arrays: "
I think my U net needs to be changed for multi input, but I don't know where I have to change.
Please help and give me any comments.
Thanks.
This is actually rather easy. All you need to do would adjust your input size I believe.
inputs = Input((img_rows, img_cols, size)) would have worked. Or you could have used concat like:
inputs = []
for _ in range(num_inputs):
inputs.append(Input((self.input_height, self.input_width, self.input_features)))
x = concatenate(inputs)
x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
You can check something similar I implemented here