Tensoflow model gives wrong output after conversion - tensorflow

My goal is to develop an app that does image classification. Keras model seems to work good but after i try to convert to Tensorflow Lite, output is completely wrong.
These are the layers of the model
model = Sequential([
layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
This is how i save and then convert the model.
model.save('/content/drive/My Drive/my_model.h5')
TF_LITE_MODEL_NAME = "tf_lite_model.tflite"
tf_lite_converter = tf.lite.TFLiteConverter.from_keras_model(model)
tflite_model = tf_lite_converter.convert()
tflite_model_name = TF_LITE_MODEL_NAME
open(tflite_model_name, "wb").write(tflite_model)
Output is like this:
[[ 1.4364377 -0.02920453 -0.149581 -0.7537567 ]]
Why this problem occur?
Edit (Code that gives random input to the model)
# Load TFLite model and allocate tensors.
interpreter = tf.lite.Interpreter(model_path="/content/tf_lite_model.tflite")
interpreter.allocate_tensors()
# Get input and output tensors.
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
# Test model on random input data.
input_shape = input_details[0]['shape']
input_data = np.array(np.random.random_sample(input_shape), dtype=np.float32)
interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()
# The function `get_tensor()` returns a copy of the tensor data.
# Use `tensor()` in order to get a pointer to the tensor.
output_data = interpreter.get_tensor(output_details[0]['index'])
print(output_data)

Related

how can i build tensorflow model in specific shape?

BATCH_SIZE = 32 # ADVISED NOT TO CHANGE THIS
N_PAST = 10 # DO NOT CHANGE THIS
N_FUTURE = 10 # DO NOT CHANGE THIS
SHIFT = 1
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=32, kernel_size=5,
strides=1, padding="causal",
activation="relu",
input_shape=[None, 1]),
tf.keras.layers.LSTM(64, return_sequences=True),
tf.keras.layers.LSTM(64, return_sequences=True),
tf.keras.layers.Dense(30, activation="relu"),
tf.keras.layers.Dense(10, activation="relu"),
tf.keras.layers.Dense(N_FEATURES)
])
I build a time-siries forcasting model but i can't understand how to handle this.
which layer should i use to make this available?
Model input shape must be (BATCH_SIZE, N_PAST = 10, N_FEATURES = 1)
Model output shape must be (BATCH_SIZE, N_FUTURE = 10, N_FEATURES = 1)
the batch_size is not specified in the model.
model = tf.keras.models.Sequential([
tf.keras.layers.Conv1D(filters=32, kernel_size=5,
strides=1, padding="causal",
activation="relu",
input_shape=[N_PAST,1]),
tf.keras.layers.LSTM(64, return_sequences=True),
tf.keras.layers.Dense(30, activation="relu"),
tf.keras.layers.Dense(10, activation="relu"),
tf.keras.layers.Dense(N_FUTURE)
])
You don't need to specify batch_size in input layer. Just change input shape as follows:
input_shape=[N_PAST,1]

How do I change the decoder feature type in Tensorflow Datasets?

I am trying to do some augmentations to tensorflow image datasets such as cifar and others from here:
https://www.tensorflow.org/datasets/catalog/
Now I have a mapping function that actually another user from SO helped me with that works with my own dataset:
def map_data(inputs):
image = inputs['image']
image = tf.numpy_function(func=aug_fn, inp=[image], Tout=tf.float32)
image = image / 255.0
labels = inputs['label']
labels = tf.one_hot(labels, num_classes)
return {'image_input': image, 'label': labels}, labels
now when iterating over the dataset I get this error:
ValueError: Missing data for input "image_input". You passed a data dictionary with keys ['image', 'label']. Expected the following keys: ['image_input', 'label']
which makes sense because the decoder returns uint8 type.
But I couldn't find any info or examples in the docs on how to change that.
Can I somehow just access the decoder Object's attributes?
I tried like in the API https://www.tensorflow.org/datasets/api_docs/python/tfds/decode/Decoder?hl=cs
but it doesn't work.
thank you very much in advance!
If it is augmentation you want to use, you should use these layers in the top of your model
data_augmentation = tf.keras.Sequential([
tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal'),
tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
tf.keras.layers.experimental.preprocessing.RandomZoom(0.1),
])
For the scaling, you use this line
rescale = tf.keras.layers.experimental.preprocessing.Rescaling(1. / 255)
This should work smoothly in your model. Here an example of a model with augmentation and rescaling
model = Sequential([
layers.experimental.preprocessing.Rescaling(1. / 255, input_shape=(256, 256, 3)),
layers.experimental.preprocessing.RandomFlip('horizontal'),
layers.experimental.preprocessing.RandomRotation(0.2),
layers.experimental.preprocessing.RandomZoom(0.1),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])

How to transfer weights from baseline model to federated model?

def create_keras_model():
model = Sequential([
Conv2D(16, 3, padding='same', activation='relu'),
MaxPooling2D(),
Conv2D(32, 3, padding='same', activation='relu'),
MaxPooling2D(),
Conv2D(64, 3, padding='same', activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(512, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.001)),
Dropout(0.5),
Dense(1, activation='sigmoid')
])
model.load_weights('/content/drive/My Drive/localmodel/weights')
return model
Tried something like this in Colab, but I get errno 21, is a directory.
Then I tried another method as shown below,
tff_model = create_keras_model() #now this function doesnt load weights, just returns a Sequential model
tff.learning.assign_weights_to_keras_model(tff_model, model_with_weights)
Just like assign_weights_to_keras_model() transfers weights from tff_model to keras model, I want to transfer weights from keras model to tff_model. How can this be done?
here model_with_weights must be a TFF value representing the weights of a model for example:
def model_fn():
keras_model = create_keras_model()
return tff.learning.from_keras_model(keras_model)
fed_avg = tff.learning.build_federated_averaging_process(model_fn, ...)
state = fed_avg.initialize()
state = fed_avg.next(state, ...)
...
tff.learning.assign_weights_to_keras_model(keras_model, state.model)
I just got to know how this can be done.
The idea is to use:
tff.learning.state_with_new_model_weights(state, trainable_weights_numpy, non_trainable_weights_numpy)
Documentation here
where trainable weights are taken from baseline model and converted to numpy format.
trainable_weights = []
for weights in baseline_model.trainable_weights:
trainable_weights.append(weights.numpy())
This is particularly useful when the server has part of the data and the client has similar data. May be this can be used for transfer learning.

model.fit_generator.() returns error.Invalid Argument

Below is the code i am using for training some gestures. the directory for training data is as follows
'E:\build\set_1\training\palm\seq_01','E:\build\set_1\training\palm\seq_02' and so on.
The error i am follwong is on the last lines. I have tried both of the two lines as provided but they are giving error as Invalid Argument error. I am running this code on jupyter notebook.
import tensorflow as tf
from tensorflow import keras
from keras_preprocessing.image import ImageDataGenerator
path = 'E:\build\set_1\training'
training_datagen = ImageDataGenerator(rescale = 1./255)
TRAINING_DIR = 'E:/build/set_1/training/'
train_generator = training_datagen.flow_from_directory(
TRAINING_DIR,
target_size = (150,150),
class_mode= 'categorical',
batch_size=64
)
VALIDATION_DIR = "E:/build/set_1/test/"
validation_datagen = ImageDataGenerator(rescale = 1./255)
validation_generator = training_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(150,150),
class_mode='categorical',
batch_size=64
)
model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 150x150 with 3 bytes color
# This is the first convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# The second convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The third convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fourth convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.5),
# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])
model.summary()
model.compile(loss='categorical_crossentropy',optimizer = 'rmsprop',
metrics= ['accuracy'])
history = model.fit_generator(train_generator,steps_per_epoch = train_generator.samples//train_generator.batch_size,epochs = 30,validation_data = validation_generator,validation_steps=validation_generator.samples//validation_generator.batch_size)
history = model.fit(train_generator, epochs=25, validation_data = validation_generator, verbose = 1)

How can I pass logits to sigmoid_cross_entropy_with_logits before I fit and predict model?

Since I need to train a model with multiple labels, I need to use loss function tf.nn.sigmoid_cross_entropy_with_logits. This function has two parameters: logits and loss.
Is parameter logitsis the value of predicted y? How can I pass this value before I compile model? I cannot predict y before I compile and fit model, right?
This is my code:
import tensorflow as tf
from tensorflow import keras
model = keras.Sequential([keras.layers.Dense(50, activation='tanh', input_shape=[100]),
keras.layers.Dense(30, activation='relu'),
keras.layers.Dense(50, activation='tanh'),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(8)])
model.compile(optimizer='rmsprop',
loss=tf.nn.sigmoid_cross_entropy_with_logits(logits=y_pred), labels=y), # <---How to figure out y_pred here?
metrics=['accuracy'])
model.fit(x, y, epochs=10, batch_size=32)
y_pred = model.predict(x) # <--- Now I got y_pred after compile, fit and predict
I'm using tensorflow v2.1.0
These arguments (labels and logits) are passed to the loss function within Keras' implementation. To make your code work do like this:
import tensorflow as tf
from tensorflow import keras
def loss_fn(y_true, y_pred):
return tf.nn.sigmoid_cross_entropy_with_logits(labels=y_true, logits=y_pred)
model = keras.Sequential([keras.layers.Dense(50, activation='tanh', input_shape=[100]),
keras.layers.Dense(30, activation='relu'),
keras.layers.Dense(50, activation='tanh'),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(8)])
model.compile(optimizer='rmsprop',
loss=loss_fn,
metrics=['accuracy'])
x = np.random.normal(0, 1, (64, 100))
y = np.random.randint(0, 2, (64, 8)).astype('float32')
model.fit(x, y, epochs=10, batch_size=32)
y_pred = model.predict(x)
The suggested way, though, is to use Keras' loss implementation instead. In your case it would be:
model = keras.Sequential([keras.layers.Dense(50, activation='tanh', input_shape=[100]),
keras.layers.Dense(30, activation='relu'),
keras.layers.Dense(50, activation='tanh'),
keras.layers.Dense(100, activation='relu'),
keras.layers.Dense(8)])
model.compile(optimizer='rmsprop',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=['accuracy'])
x = np.random.normal(0, 1, (64, 100))
y = np.random.randint(0, 2, (64, 8)).astype('float32')
model.fit(x, y, epochs=10, batch_size=32)
y_pred = model.predict(x)