keras.model.predict raise ValueError: Error when checking input - tensorflow

I trained a basic Neural Network model on the MNIST dataset. Here's the code to the training: (imports omitted)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data(path='mnist.npz')
x_train, x_test = x_train/255.0, x_test/255.0
#1st Define the model
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape = (28,28)), #input layer
tf.keras.layers.Dense(512, activation=tf.nn.relu), #main computation layer
tf.keras.layers.Dropout(0.2), #Dropout layer to avoid overfitting
tf.keras.layers.Dense(10, activation=tf.nn.softmax) #output layer / Softmax is a classifier AF
])
#2nd Compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
#3rd Fit the model
model.fit(x_train, y_train, epochs=5)
#4th Save the model
model.save('models/mnistCNN.h5')
#5th Evaluate the model
model.evaluate(x_test, y_test)
I wanted to see how this model works with my own inputs, so I wrote a prediction script with help from this post. My prediction code is: (imports omitted)
model = load_model('models/mnistCNN.h5')
for i in range(3):
img = Image.open(str(i+1) + '.png').convert("L")
img = img.resize((28,28))
im2arr = np.array(img)
im2arr = im2arr/255
im2arr = im2arr.reshape(1, 28, 28, 1)
y_pred = model.predict(im2arr)
print('For Image',i+1,'Prediction = ',y_pred)
First, I don't understand the purpose of this line:
im2arr = im2arr.reshape(1, 28, 28, 1)
If some one could shed light on why this line necessary, that would be of great help.
Second, this very line throws the following error:
ValueError: Error when checking input: expected flatten_input to have 3 dimensions, but got array with shape (1, 28, 28, 1)
What am I missing here?

First dimension is used for batch size. It is added by keras.model internally. So this line just adds it to image array.
im2arr = im2arr.reshape(1, 28, 28, 1)
The error you get is because a single example from mnist dataset, that you used for training has shape (28, 28), so as your input layer. To get rid of this error you need to change this line to
im2arr = img.reshape((1, 28, 28))

Related

How can I set 'input_shape' of keras.layers.SimpleRNN, when Data is unvariate?

I am trying to do time-series forecasting using RNN, but an error continuously occurred in 'input_shape' of keras.layers.SimpleRNN,
but I could not solve it, so I would like to ask a question.
First of all, below is the code. and This is Error Message:
ValueError: Input 0 of layer sequential is incompatible with the layer: expected ndim=3, found ndim=2. Full shape received: (None, 1)
# X_train.shape = (58118,)
# y_train.shape = (58118,)
X_train, X_test, y_train, y_test = train_test_split(x,y,test_size=0.2,shuffle=False,random_state=1004)
X_train,X_val,y_train,y_val = train_test_split(X_train,y_train,test_size=0.125,shuffle=False,random_state=1004)
print(X_train.shape)
print(y_train.shape)
with tf.device('/gpu:0'):
model = keras.models.Sequential([
keras.layers.SimpleRNN(20, return_sequences=True, input_shape=[None,1]),
keras.layers.SimpleRNN(20, return_sequences=True),
keras.layers.TimeDistributed(keras.layers.Dense(10))
])
model.compile(loss="mse", optimizer="adam")
history = model.fit(X_train, y_train, epochs=20,validation_data=(X_val, y_val)) #Error
model.save('rnn.h5')
SimpleRNN expects inputs: A 3D tensor, with shape [batch, timesteps, feature]
Sample Code
inputs = np.random.random([32, 10, 8]).astype(np.float32)
simple_rnn = tf.keras.layers.SimpleRNN(4)
output = simple_rnn(inputs)
Output has shape [32, 4].

Flattened input layer shape

The code below was taken from TensorFlow in Practice by deeplearning.ai course in Coursera (computer vision example - week 2).
import tensorflow as tf
mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images = training_images / 255.0
test_images = test_images / 255.0
model = tf.keras.models.Sequential([tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)])
model.compile(optimizer=tf.optimizers.Adam(),
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
print("Executing Training:")
model.fit(training_images, training_labels, epochs=5)
print("Executing inference:")
model.evaluate(test_images, test_labels)
The question: How TensorFlow deduce the shape of the input layer? Which shape is being flattened here? The input shape should be derived from the shape of the input data, Am I missing something here?
Given the model.fit(training_images, training_labels), Tensorflow API automatically passes the training_images to the first layer.
Training_images is a tensor of shape (m, 28, 28, 1).
where,
m - Total number of training images,
28x28 - image size,
1 - channel (Gray scale),
tf.keras.layers.Flatten(), reshapes the(28, 28, 1) 28x28 image into -> (784,).
View this for the Flatten() method source code. https://github.com/tensorflow/tensorflow/blob/v2.2.0/tensorflow/python/keras/layers/core.py#L598-L684

Tensorflow Keras Shape mismatch

While trying to implement a standard MNIST digit recognizer that many tutorials use to introduce you to neural networks, I'm encountering the error
ValueError: Shape mismatch: The shape of labels (received (1,)) should equal the shape of logits except for the last dimension (received (28, 10)).
I would like to use from_tensor_slices to process the data, since I want to apply the code to another problem where the data comes from a CSV file. Anyway, here is the code producing the error in the line model.fit(...)
import tensorflow as tf
train_dataset, test_dataset = tf.keras.datasets.mnist.load_data()
train_images, train_labels = train_dataset
train_images = train_images/255.0
train_dataset_tensor = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
num_of_validation_data = 10000
validation_data = train_dataset_tensor.take(num_of_validation_data)
train_data = train_dataset_tensor.skip(num_of_validation_data)
model = tf.keras.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(100, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.fit(train_data, batch_size=50, epochs=5)
performance = model.evaluate(validation_data)
I don't understand where the shape (28, 10) of the logits comes from, I thought I was flattening the image, essentially making a 1D vector out of the 2D image? How can I prevent the error?
You can use the following code
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
train_ds = tf.data.Dataset.from_tensor_slices(
(x_train, y_train)).shuffle(10000).batch(32)
test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(32)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(100, activation='sigmoid'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=1e-3),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.fit(train_ds)

Keras ImageDataGenerator() expect 3D data and 4-rank tensor at once?

I've been trying to use keras.preprocessing.image.ImageDataGenerator() on the MNIST for extra examples.
I'm using a fully-connected network in Keras on top of Keras. I begin by reshaping the 3D MNIST into 4D tensors before building and compiling a model, then I use data augmentation to help fit the model.
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
model = Sequential(name="mlp")
model.add(ll.InputLayer([28, 28]))
model.add(ll.Flatten())
model.add(ll.Dense(512, kernel_regularizer=regularizers.l2(0.04)))
model.add(ll.Activation('relu'))
model.add(ll.Dense(512, kernel_regularizer=regularizers.l2(0.04)))
model.add(ll.Activation('relu'))
model.add(ll.Dense(256, kernel_regularizer=regularizers.l2(0.04)))
model.add(ll.Activation('relu'))
model.add(ll.Dense(128, kernel_regularizer=regularizers.l2(0.04)))
model.add(ll.Activation('relu'))
model.add(ll.Dense(32, kernel_regularizer=regularizers.l2(0.04)))
model.add(ll.Activation('relu'))
model.add(ll.Dense(10, activation='softmax'))
model.compile("adam", "categorical_crossentropy", metrics=["accuracy"])
gen = ImageDataGenerator(rotation_range=8, width_shift_range=0.08, shear_range=0.3,
height_shift_range=0.08, zoom_range=0.08)
test_gen = ImageDataGenerator()
train_generator = gen.flow(X_train, y_train, batch_size=64)
test_generator = test_gen.flow(X_test, y_test, batch_size=64)
...
model.fit_generator(train_generator, steps_per_epoch=60000//64, epochs=5,
validation_data=test_generator, validation_steps=10000//64)
I get this error:
5 model.fit_generator(train_generator, steps_per_epoch=60000//64, epochs=5,
----> 6 validation_data=test_generator, validation_steps=10000//64)
ValueError: Error when checking input: expected input_6 to have 3 dimensions, but got array with shape (256, 28, 28, 1)
But then when I omit it converting to a 4d tensor, this happens:
52 test_gen = ImageDataGenerator()
---> 53 train_generator = gen.flow(X_train, y_train, batch_size=64)
54 test_generator = test_gen.flow(X_test, y_test, batch_size=64)
ValueError: ('Input data in `NumpyArrayIterator` should have rank 4. You passed an array with shape', (50000, 28, 28))
It seems that the train and test generator objects generate 4D tensors, but the model, itself, wants 3D tensors.
Well, your data is (batch, 28, 28, 1) while your model (the input layer) is expecting (batch, 28, 28).
Solving this is as simple as changing the input shape of the model:
#you don't need to add an input layer, actually, just pass the shape to the first layer:
model = Sequential(name="mlp")
model.add(ll.Flatten(input_shape=(28,28,1)))

input_shape parameter mismatch error in Convolution1D in keras

I want to classify a dataset using Convulation1D in keras.
DataSet Description:
train dataset size = [340,30] ; no of sample = 340 , sample dimension = 30
test dataset size = [230,30] ; no of sample = 230 , sample dimension = 30
label size = 2
Fist I try by the following code using the information from keras site https://keras.io/layers/convolutional/
batch_size=1
nb_epoch = 10
sizeX=340
sizeY=30
model = Sequential()
model.add(Convolution1D(64, 3, border_mode='same', input_shape=(sizeX,sizeY)))
model.add(Convolution1D(32, 3, border_mode='same'))
model.add(Convolution1D(16, 3, border_mode='same'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
print('Train...')
model.fit(X_train_transformed, y_train, batch_size=batch_size, nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test_transformed, y_test, batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
it gives the following error ,
ValueError: Error when checking model input: expected convolution1d_input_1 to have 3 dimensions, but got array with shape (340, 30)
Then I have transformed the Train and Test data into 3 dimension from 2 dimension by using the following code ,
X_train = np.reshape(X_train_transformed, (X_train_transformed.shape[0], X_train_transformed.shape[1], 1))
X_test = np.reshape(X_test_transformed, (X_test_transformed.shape[0], X_test_transformed.shape[1], 1))
Then I run the modified following code ,
batch_size=1
nb_epoch = 10
sizeX=340
sizeY=30
model = Sequential()
model.add(Convolution1D(64, 3, border_mode='same', input_shape=(sizeX,sizeY)))
model.add(Convolution1D(32, 3, border_mode='same'))
model.add(Convolution1D(16, 3, border_mode='same'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
print('Train...')
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
But it shows the error ,
ValueError: Error when checking model input: expected convolution1d_input_1 to have shape (None, 340, 30) but got array with shape (340, 30, 1)
I am unable to find the dimension mismatch error here.
With the release of TF 2.0 and tf.keras, you can fairly easily update your model to work with these new versions. This can be done with the following code:
# import tensorflow 2.0
# keras doesn't need to be imported because it is built into tensorflow
from __future__ import absolute_import, division, print_function, unicode_literals
try:
%tensorflow_version 2.x
except Exception:
pass
import tensorflow as tf
batch_size = 1
nb_epoch = 10
# the model only needs the size of the sample as input, explained further below
size = 30
# reshape as you had before
X_train = np.reshape(X_train_transformed, (X_train_transformed.shape[0],
X_train_transformed.shape[1], 1))
X_test = np.reshape(X_test_transformed, (X_test_transformed.shape[0],
X_test_transformed.shape[1], 1))
# define the sequential model using tf.keras
model = tf.keras.Sequential([
# the 1d convolution layers can be defined as shown with the same
# number of filters and kernel size
# instead of border_mode, the parameter is padding
# the input_shape is (the size of each sample, 1), explained below
tf.keras.layers.Conv1D(64, 3, padding='same', input_shape=(size, 1)),
tf.keras.layers.Conv1D(32, 3, padding='same'),
tf.keras.layers.Conv1D(16, 3, padding='same'),
# Dense and Activation can be combined into one layer
# where the dense layer has 1 neuron and a sigmoid activation
tf.keras.layers.Dense(1, activation='sigmoid')
])
# the model can be compiled, fit, and evaluated in the same way
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
print('Train...')
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
The problem you are having comes from the input shape of your model. According to the keras documentation the input shape of the model has to be (batch, step, channels). This means that the first dimension is the number of instances you have. The second dimension is the size of each sample. The third dimension is the number of channels which in your case would only be one. Overall, your input shape would be (340, 30, 1). When you actually define the input shape in the model, you only need to specify the the second and third dimension which means your input shape would be (size, 1). The model already expects the first dimension, the number of instances you have, as input so you do not need to specify that dimension.
Can you try this?
X_train = np.reshape(X_train_transformed, (1, X_train_transformed.shape[0], X_train_transformed.shape[1]))
X_test = np.reshape(X_test_transformed, (1, X_test_transformed.shape[0], X_test_transformed.shape[1]))