impossible to change the model to detect - object-detection-api

I use the tensorflow lite detector for android. I want to change the model to recognise dog for example, i put my dog.tflite file and his label in assets and change in the code the files to choose (the dog.tflite and his label), change the "TF_OD_API_INPUT_SIZE=300" to "TF_OD_API_INPUT_SIZE=224" and "TF_OD_API_IS_QUANTIZED = true;" to "TF_OD_API_IS_QUANTIZED = false;" in the DetectorActivity.java. But i have the error : "Cannot copy between a TensorFlowLite tensor with shape [1, 25] and a Java object with shape [1, 10, 4].".
How to fix this problem ?
Thanks

Is your TF Lite model an "Image Classification" model, or an "Object Detection" model?
TensorFlowLite tensor with shape [1, 25]
From the model output's shape, I believe that it is an image classification model. You should use this sample code instead of the object_detection sample.

Related

Incompatible shapes error while training my UNET model in Tensorflow

I have written an UNET model in Tensorflow, to run on some CT scan images, which have been already preprocessed and turned into .npz files.The model runs successfully, but I get an error,Shapes (2, 512, 512, 2, 17) and (2, 512, 512, 2) are incompatible. My model has 17 features(Tuberculosis, Ground glass etc), and Features are the same as labels I assume(correctly?). I am attaching the colab link of the model, with shapes outputted wherever necessary. The error is after the last block of code, and the model runs perfectly until I execute the last block. Where exactly is my model failing? And how do I match the shapes for the model to train successfully?Here is the colab link.
P.S:I am really sorry to use a colab link, but the code relevent is too big to source here.

Tensorflow: tf.trainable_variables() does not show my mode weights

I am trying to extract my model weights to be able to run my first pre-trained model. However, I am unable to extract my weights since executing tf.trainable_variables() give me the following output:
[<tf.Variable 'VGGNet/B1C1/kernel:0' shape=(3, 1, 3, 32) dtype=float32_ref>, <tf.Variable 'VGGNet/B1C1/bias:0' shape=(32,) dtype=float32_ref>, <tf.Variable 'VGGNet/B1C2/kernel:0' shape=(1, 3, 32, 32)....
It shows the shape, but not the numpy array that I am expecting. What am I missing?
You should not be extracting weights for using your pre-trained model; instead use the model.save_weights() and model.load_weights() utility methods provided by the API. Here's a link to the document you can use to learn more about it Save and load models.
Coming to your question - why you are not seeing the weights: it is because tf.trainable_variables() is supposed to give you variables and not their values (aka weights).

Keras Same Feature Extraction from Different Images

I'm using Keras' pre-trained model for feature extraction in two images, however they gave the same outcome (array_equal = True). I've tried other model like VGG16 and Resnet50 but the results are the same. Am I writing the code wrong or is it the limitation of pre-trained model? Is there anything I can do to extract different features? Thanks!
import cv2
from keras.applications.inception_v3 import InceptionV3
from keras.applications.inception_v3 import preprocess_input
model = InceptionV3(weights='imagenet', include_top=False)
def get_img_vector(path):
im = cv2.imread(path)
im = cv2.resize(im,(224,224))
img = preprocess_input(np.expand_dims(im.copy(), axis=0))
resnet_feature = model.predict(img)
return np.array(resnet_feature)
arr1 = get_img_vector('image1.png')
arr2 = get_img_vector('image2.png')
np.array_equal(arr1,arr2)
Below are my two images:
I think that the file format png create the image loading problem. Currently cv2.imread a png file and cv2.imshow it result in a black screen, which make two images identical. Saving the file from png to jpg and trying it again.
If you run the code, you should see some warning like this,
WARNING: TensorFlow:Model was constructed with shape (None, 299, 299, 3)
for input Tensor("input_3:0", shape=(None, 299, 299, 3), dtype=float32),
but it was called on an input with incompatible shape (None, 224, 224, 3).
Change your code to
im = cv2.resize(im,(299,299))
Now about the similar features, pre-trained imagenet can classify 1000 classes and the given picture. If you decode then you'll see that both of them will give you the same output. And you'll see even for the top 5 predictions, confidence is very low, and most similar is to the image of a nematode.
[[('n01930112', 'nematode', 0.11086103), ('n03729826', 'matchstick', 0.08173305), ('n03196217', 'digital_clock', 0.034744), ('n03590841', "jack-o'-lantern", 0.017616412), ('n04286575', 'spotlight', 0.016781498)]]
However, if you want to train a model that can differentiate these two images then you can use the pre-trained models for transfer learning with your own dataset.

TensorFlow 1.2.1 and InceptionV3 to classify an image

I'm trying to create an example using the Keras built in the latest version of TensorFlow from Google. This example should be able to classify a classic image of an elephant. The code looks like this:
# Import a few libraries for use later
from PIL import Image as IMG
from tensorflow.contrib.keras.python.keras.preprocessing import image
from tensorflow.contrib.keras.python.keras.applications.inception_v3 import InceptionV3
from tensorflow.contrib.keras.python.keras.applications.inception_v3 import preprocess_input, decode_predictions
# Get a copy of the Inception model
print('Loading Inception V3...\n')
model = InceptionV3(weights='imagenet', include_top=True)
print ('Inception V3 loaded\n')
# Read the elephant JPG
elephant_img = IMG.open('elephant.jpg')
# Convert the elephant to an array
elephant = image.img_to_array(elephant_img)
elephant = preprocess_input(elephant)
elephant_preds = model.predict(elephant)
print ('Predictions: ', decode_predictions(elephant_preds))
Unfortunately I'm getting an error when trying to evaluate the model with model.predict:
ValueError: Error when checking : expected input_1 to have 4 dimensions, but got array with shape (299, 299, 3)
This code is taken from and based on the excellent example coremltools-keras-inception and will be expanded more when it is figured out.
The reason why this error occured is that model always expects the batch of examples - not a single example. This diverge from a common understanding of models as mathematical functions of their inputs. The reasons why model expects batches are:
Models are computationaly designed to work faster on batches in order to speed up training.
There are algorithms which takes into account the batch nature of input (e.g. Batch Normalization or GAN training tricks).
So four dimensions comes from a first dimension which is a sample / batch dimension and then - the next 3 dimensions are image dims.
Actually I found the answer. Even though the documentation states that if the top layer is included the shape of the input vector is still set to take a batch of images. Thus we need to add this before the code line for the prediction:
elephant = numpy.expand_dims(elephant, axis=0)
Then the tensor is in the right shape and everything works correctly. I am still uncertain why the documentation states that the input vector should be (3x299x299) or (299x299x3) when it clearly wants 4 dimensions.
Be careful!

Name of input and output tensors when loading Keras model to TensorFlow

I'm trying to use Keras' model in "pure" TensorFlow (I want to use it in Android app). I've successfully exported Keras model to protobuf and imported it to Tensorflow. However running tensorflow model requires providing input and output tensors' names and I don't know how to find them. My model looks like this:
seq = Sequential()
seq.add(Convolution2D(32, 3, 3, input_shape=(3, 15, 15), name="Conv1"))
....
seq.add(Activation('softmax', name="Act4"))
seq.compile()
When I'm printing tensors in TensorFlow I can find:
Tensor("Conv1_W/initial_value:0", shape=(32, 3, 3, 3), dtype=float32)
Tensor("Conv1_W:0", dtype=float32_ref)
Tensor("Conv1_W/Assign:0", shape=(32, 3, 3, 3), dtype=float32_ref)
Tensor("Conv1_W/read:0", dtype=float32)
Tensor("Act4_sample_weights:0", dtype=float32)
Tensor("Act4_target:0", dtype=float32)
Hovewer, there are no tensors that have shape (3,15,15).
I've seen here that I can add "my_input_tensor" as input, hovewer I don't know which type is it - I've tried TensorFlow's and Keras' placeholders and they gave me this error:
/XXXXXXXXX/lib/python2.7/site-packages/keras/engine/topology.pyc in __init__(self, input, output, name)
1599 # check that x is an input tensor
1600 layer, node_index, tensor_index = x._keras_history
-> 1601 if len(layer.inbound_nodes) > 1 or (layer.inbound_nodes and layer.inbound_nodes[0].inbound_layers):
1602 cls_name = self.__class__.__name__
1603 warnings.warn(cls_name + ' inputs must come from '
AttributeError: 'NoneType' object has no attribute 'inbound_nodes'
As of TensorFlow 2.0 (unfortunately they seem to change this often) you can export the model to the SavedModel format -in python- using
model.save('MODEL-FOLDER')
and then inspect the model using the saved_model_cli tool (found inside python folder <yourenv>/bin/saved_model_cli -in anaconda at least)
saved_model_cli show --dir /path/to/model/MODEL-FOLDER/ --tag_set serve --signature_def serving_default
the output will be something like
The given SavedModel SignatureDef contains the following input(s):
inputs['graph_input'] tensor_info:
dtype: DT_DOUBLE
shape: (-1, 28, 28)
name: serving_default_graph_input:0
The given SavedModel SignatureDef contains the following output(s):
outputs['graph_output'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 10)
name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict
By inspecting the output, you can see the name of the input and output tensors in this case to be, respectively: serving_default_graph_input and StatefulPartitionedCall
This is how you find the tensor names.
The right way to do this, though, is to define a graph path and its output and input tensors on the model using SignatureDefs. So you's load those SignaturesDefs instead of having to deal with the tensor name's directly.
This is a nice reference that explains this better than the official docs, imo:
https://sthalles.github.io/serving_tensorflow_models/
Call a model.summary() in Keras to see all the layers.
An input tensor will often be called input_1, input_2, etc. See in the summary the correct name.
When you use input_shape=(3,15,15) in Keras, you're actually using tensors that have shape (None, 3, 15, 15). Where None will be replaced by the batch size in training or prediction.
Often, for these unknonw dimensions, you use -1, such as in (-1, 3, 15, 15). But I cannot assure you that it will work like this. It works perfectly for reshaping tensors, but for creating I've never tested.
To get the input and output tensors of your Keras models, do the following:
input_tensor = seq.inputs[0]
output_tensor = seq.outputs[0]
print("Inputs: "+str(input_tensor))
print("Outputs: "+str(output_tensor))
The above assumes that there is only 1 input tensor and 1 output tensor. If you have more, then you would have to use the appropriate index to get those tensors.
Note that there is a difference between layer output shapes and tensor output shapes. The two are usually the same, but not always.
You can try calling summary() on the loaded model object as suggested in one of the answers. But if you couldn't find the input and output names in the model summary, try calling input_names and output_names on the model object as below :
from tensorflow.keras.models import load_model
model = load_model("./model/00001")
print(model.input_names)
print(model.output_names)
Tried out on TensorFlow version : 2.3.1

Resources