`decode_predictions` expects a batch of predictions (i.e. a 2D array of shape (samples, 1000)). Found array with shape: (1, 5) - tensorflow

A retrained the inception_v3 model for my own test data. (Backstory: im just trying to understand how the whole process works before im trying it on my 130 class "problem")
Now i got the .h5.
I tryed to import it and predict some image. But i only get the following error messages.
ValueError: `decode_predictions` expects a batch of predictions (i.e. a 2D array of shape (samples, 1000)). Found array with shape: (1, 5)
May some can tell me what im doing horrible wrong?
my thoughts:
I read something that i need a vector of 1000 probabilitys (for 1000 classes) but i dont have them.
How do i create such vector and set all 1000-my_num_of_classes(in my case 5) to like 0?
I guess i have to preshape a 2d array of a size of 1000. But it dont get it what "samples" or in my case the "1" represent.
Or do i have to write some matching for my array of [1.0592173e-07 8.3998479e-09 9.9305904e-01 4.8276172e-05 6.8924953e-03] (in my case). Where i interprete that the 3 (id 2) class(which got trained) have the highest probability?
So maybe like a file where i have all the trained classes in order like trained? to match the highest with the correspoding row (label)?
Would be awesome :)
That would be my code for predicition
# Testing Inceptionv3
#from keras.applications.imagenet_utils import decode_predictions
import numpy as np
from keras.applications.inception_v3 import decode_predictions
import matplotlib.pyplot as plt
import os
from keras.models import load_model
from PIL import Image
my_model = load_model('my_model.h5')
#images = transform_img_fn([os.path.join('data','rose.jpg')])
img = Image.open('./data/rose.jpg')
img = img.resize((150,150))
img = np.array(img)
img = img / 255.0
img = img.reshape(1,150,150,3)
#base_model = inc_net.InceptionV3(weights='imagenet', include_top=False)
preds = my_model.predict(img)
for x in decode_predictions(preds)[0]:
print(x)

The decode_predictions utility converts the class predictions of a pretrained ImageNet model into the corresponding human-readable ImageNet classes.
Using "decode_predictions" only makes sense if your model outputs the ImageNet classes (1000-dimensional). Your model (my_model) appears to return predictions over 5 classes. It's not an ImageNet model.

Related

How to dilate y_true inside a custom metric in keras/tensorflow?

I am trying to code a custom metric for U-net model implemented using keras/tensorflow. In the metric, I need to use the opencv function, 'cv2.dilate' on the ground truth. When I tried to use it, it gave the error as y_true is a tensor and cv2.dilate expects a numpy array.
Any idea on how to implement this?
I tried to convert tensor to numpy array but it is not working.
I searched for the tensorflow implementation of cv2.dilate but couldnt find one.
One possibility, if you are using a simple rectangular kernel in your dilation, is to use tf.nn.max_pool2d as a replacement.
import numpy as np
import tensorflow as tf
import cv2
image = np.random.random((28,28))
kernel_size = 3
# OpenCV dilation works with grayscale image, with H,W dimensions
dilated_cv = cv2.dilate(image, np.ones((kernel_size, kernel_size), np.uint8))
# TensorFlow maxpooling works with batch and channels: B,H,W,C dimenssions
image_w_batch_and_channels = image[None,...,None]
dilated_tf = tf.nn.max_pool2d(image_w_batch_and_channels, kernel_size, 1, "SAME")
# checking that the results are equal
np.allclose(dilated_cv, dilated_tf[0,...,0])
However, given that you mention that you are applying dilation on the ground truth, this dilation does not need to be differentiable. In that case, you can wrap your dilation in a tf.numpy_function
from functools import partial
# be sure to put the correct output type, tf.float64 is working in that specific case because numpy defaults to float64, but it might be different in your case
dilated_tf_npfunc = tf.numpy_function(
partial(cv2.dilate, kernel=np.ones((kernel_size, kernel_size), np.uint8)), [image]
)

Evaluation with pre-trained model results in Type error

I have a trained inceptionV3 model that I want to test on a new data set. However, i am getting TypeError concerning shape of image data. InceptionV3 model is a trained on 1500 image classification dataset.
from tensorflow import keras
import cv2
from tensorflow.keras.preprocessing import image
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import numpy as np
import tensorflow as tf
from tensorflow.keras.models import load_model
# dimensions of our images ----- are these then grayscale (black and white)?
img_width, img_height = 139, 139
# load the model we saved
model = load_model('/home/DEV/model_inception.h5', compile=False)
# Get test image ready
test_image = cv2.imread('/home/images/0b53daf814304dd0d74efb2fa052ef23_0.png')
test_image = np.array(test_image)
test_image = cv2.resize(test_image,(img_width,img_height))
test_image = test_image.reshape(1,img_width, img_height,3)
result = model.predict(test_image)
plt.imshow(result, cmap="gray")
plt.show()
The Type error that i am getting is
TypeError: Invalid shape (1, 3, 3, 2048) for image data
How can I correct my evaluation model and and test it
Here is the sample of model summary
model.summary
what you want is for your input image to have shape(1,139,139,3)if this is what the image size was for the training images you used to train your model.
Next question is was your model trained on RGB or BGR images? cv2 reads in images as BGR. If your model was trained on RGB images then you need to convert the image from BGR to RGB with
image_rgb=cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
Next question were the images your model was trained on have the pixel values scaled? Usually they are scale with
scaled_image=image/255
If the training images were scaled you need to scale the input image. Finally to get the image into the right shape use
image=np.expand_dims(image, axis=0)
this adds the extra dimension needed by model.predict

Tensorflow: Classifying images in batches

I have followed this TensorFlow tutorial to classify images using transfer learning approach. Using almost 16,000 manually classified images (with about 40/60 split of 1/0) added on top of the pre-trained MobileNet V2 model, my model achieved 96% accuracy on the hold out test set. I then saved the resulting model.
Next, I would like to use this trained model to classify new images. To do so, I have adapted one of the portions of the tutorial's code (in the end where it says #Retrieve a batch of images from the test set) in the way described below. The code works, however, it only processes one batch of 32 images and that's it (there are hundreds of images in the source folder). What am I missing here? Please advise.
# Import libraries
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import preprocessing
from tensorflow.keras.preprocessing import image_dataset_from_directory
import matplotlib.pyplot as plt
import numpy as np
import os
# Load saved model
model = tf.keras.models.load_model('/model')
# Re-compile model
base_learning_rate = 0.0001
model.compile(optimizer=tf.keras.optimizers.Adam(lr=base_learning_rate),
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
# Define paths
PATH = 'Data/'
new_dir = os.path.join(PATH, 'New_images') # New_images must contain at least one class (sub-folder)
IMG_SIZE = (640, 640)
BATCH_SIZE = 32
new_dataset = image_dataset_from_directory(new_dir, shuffle=True, batch_size=BATCH_SIZE, image_size=IMG_SIZE)
# Retrieve a batch of images from the test set
image_batch, label_batch = new_dataset.as_numpy_iterator().next()
predictions = model.predict_on_batch(image_batch).flatten()
# Apply a sigmoid since our model returns logits
predictions = tf.nn.sigmoid(predictions)
predictions = tf.where(predictions < 0.5, 0, 1)
print('Predictions:\n', predictions.numpy())
len(new_dataset) # equals 25, i.e., there are 25 batches
Replace this code:
# Retrieve a batch of images from the test set
image_batch, label_batch = new_dataset.as_numpy_iterator().next()
predictions = model.predict_on_batch(image_batch).flatten()
with this one:
predictions = model.predict(new_dataset,batch_size=BATCH_SIZE).flatten()
tf.data.Dataset objects can be directly passed to the method predict(). Reference

How to resize elements in a ragged tensor in TensorFlow

I would like to resize every element in a ragged tensor. For example, if I have a ragged tensor of various sized images, how can I resize each one so that the dimensions are the same?
For example,
digits = tf.ragged.constant([np.zeros((1,60,60,1)), np.zeros((1,46,75,1))])
resize_lambda = lambda x: tf.image.resize(x, (60,60))
res = tf.ragged.map_flat_values(resize_lambda, digits)
I wish res to be a tensor of shape (2,60,60,1). How can I achieve this?
To clarify, this would be useful if within a custom layer we wanted to slice or crop sections from a single image to batch for inference in the next layer. In my case, I am attempting to combine two models (a model to segment an image into multiple cropped images of varying size and a classifier to predict each sub-image). I am also using tf 2.0
You should be able to do the following.
import tensorflow as tf
import numpy as np
digits = tf.ragged.constant([np.zeros((1,60,60,1)), np.zeros((1,46,75,1))])
res = tf.concat(
[tf.image.resize(digits[i].to_tensor(), (60,60)) for i in tf.range(digits.nrows())],
axis=0)

How to give multiple input at each time step of a sequential data to a recurrent neural network using tensorflow?

Suppose i am having a data set with: number of observations = 1000, each observation is a sequence of fixed length = 10(lets say), and each point in the sequence having 2 features(numerical). how we can input such data to an rnn in tensorflow ?
Any small suggestions also accepted. Thanks
According to your description, Your dataset is 1000x10x2
which looks something like this:
import numpy as np
data=np.random.randint(0,10,[1000,10,2])
Now as you said your sequence is fixed size so you don't need padding , now you have to just decide batch_size and then iterations
suppose batch size is 5:
batch_size=5
iterations=int(len(train_dataset)//batch_size)
Now feed your input to tensorflow lstm cell , your model would be something like this:
Here is example without batch size,
import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
data=np.random.randint(0,10,[1000,10,2])
input_x=tf.placeholder(tf.float32,[1000,10,2])
with tf.variable_scope('encoder') as scope:
cell=rnn.LSTMCell(150)
model=tf.nn.dynamic_rnn(cell,inputs=input_x,dtype=tf.float32)
output_,(fs,fc)=model
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
output = sess.run(model, feed_dict={input_x: data})
print(output)
if you want to use batch then you have to either reshape data for LSTM or you have to use embedding, because LSTM takes rank 3