Keras shape error when given input from the front end - python-3.x

I am trying to build a chatbot using keras and bag of words model. But when i am trying to input the answer from the front end , this is the error that i get :-
ValueError: Input 0 of layer sequential is incompatible with the layer: expected axis -1 of input shape to have value 69 but received input with shape [None, 1]
Here is my code :-
model = tensorflow.keras.Sequential([
tensorflow.keras.layers.Dense(8,input_shape=(len(training[0]), )),
tensorflow.keras.layers.Dense(8),
tensorflow.keras.layers.Dense(len(output[0]), activation = "softmax")
])
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics="accuracy")
model.summary()
try:
tensorflow.keras.models.load_model('heya')
print('Existing model loaded.')
except:
model.fit(training, output, epochs=1000, batch_size=8)
model.save('heya')
Any help would be appreciated

You have to define correctly the input and output shapes of your model
import tensorflow
import numpy as np
training = np.random.uniform(0,1, (24, 69))
output = np.random.randint(0,2, (24, 13))
model = tensorflow.keras.Sequential([
tensorflow.keras.layers.Dense(8,input_shape=(training.shape[1], )),
tensorflow.keras.layers.Dense(8),
tensorflow.keras.layers.Dense(output.shape[1], activation = "softmax")
])
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics="accuracy")
model.fit(training, output, epochs=10, batch_size=8)
the input dimension is the number of features (69 in your case), while the output dim is equivalent to the number of classes (13 in your case)

Related

Dimension error in feeding Keras with Tensorflow dataset

I have a TFRecords file consisting of 60 examples of six Landsat band values for some pixels plus a label for each pixel, and I want to train a Keras classifier with it. But I get a dimension mismatch when I try to load network with the data.
TFRecords file is generated with below structure:
# TFRecords file contains below features per each example
bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7','landcover']
columns = [tf.FixedLenFeature(shape=[1], dtype=tf.float32) for k in bands]
featuresDict = dict(zip(bands, columns))
And my code for defining generator function and Keras model is as follows:
def tfdata_generator_training(fileName, batchSize=None):
dataset = tf.data.TFRecordDataset(fileName, compression_type='GZIP')
def parse_tfrecord(example):
features = tf.parse_single_example(example, featuresDict)
# Extract landcover and remove it from dictionary
labels = features.pop('landcover')
labels = tf.one_hot(tf.cast(labels, tf.uint8), 3)
# Return list of dictionary values (to be convertable to numpy array for Keras) and pixel label in one-hot format
return list(features.values()), labels
# Map the parsing function over the dataset
dataset = dataset.map(parse_tfrecord)
dataset = dataset.batch(batchSize)
return dataset
training_data = tfdata_generator_training(fileName=<my_file_path>, batchSize=1)
def keras_model():
from tensorflow.keras.layers import Dense, Input
inputs = Input(shape=(6,1))
x = Dense(5, activation='relu')(inputs)
x = Dense(7, activation='relu')(x)
outputs = Dense(3, activation='softmax')(x)
return tf.keras.Model(inputs, outputs)
model = keras_model()
model.compile('adam', 'categorical_crossentropy', metrics=['acc'])
model.fit(training_data.make_one_shot_iterator(), steps_per_epoch=60, epochs=8)
But I get below error when running the code:
ValueError: Error when checking target: expected dense_2 to have shape (6, 3) but got array with shape (1, 3)
What is the problem with my code? I also tried to get the dimensions of the input layer and the Tensorflow printout was as follows:
(<tf.Tensor 'IteratorGetNext:0' shape=(?, 6, 1) dtype=float32>, <tf.Tensor 'IteratorGetNext:1' shape=(?, 1, 3) dtype=float32>)

LSTM input_shape incompatible

I'm trying to build a sequential model using Keras with an LSTM layer as the first layer. train_x has a shape of (21000, 2) and I'm using a batch size of 10
When I try
model = Sequential()
model.add(LSTM(128, activation='relu', input_shape=(
train_x.shape[1:]), return_sequences=True))
I get an error saying
Input 0 is incompatible with layer lstm_1: expected ndim=3, found ndim=2
Then I tried to change input_shape and set it to input_shape=(train_x.shape) and I got another error saying
Error when checking input: expected lstm_1_input to have 3 dimensions, but got array with shape (21000, 2)
What am I doing wrong?
Keras LSTM layer expects the input to be 3 dims as (batch_size, seq_length, input_dims), but you have assigned it wrong. Try this
input_dims = train_x.shape[1]
seq_length = #decide an integer
model = Sequential()
model.add(LSTM(128, activation='relu', input_shape=(seq_length, input_dims), return_sequences=True))
Also you need to reshape your data to three dims, where new dims will represent the sequence, as
I used toy dataset to show an example, here data and labels are of shape ((150, 4), (150,)) initially, using the following script:
seq_length = 10
dataX = []
dataY = []
for i in range(0, 150 - seq_length, 1):
dataX.append(data[i:i+seq_length])
dataY.append(labels[i+seq_length-1])
import numpy as np
dataX = np.reshape(dataX, (-1, seq_length, 4))
dataY = np.reshape(dataY, (-1, 1))
# dataX.shape, dataY.shape
Output: ((140, 10, 4), (140, 1))
Now you can safely feed it to model.
Note: I prepared dataset for many-to-one model, but you can use it appropriately.

Keras LSTM, expected 3 but got array with shape []

I am trying to find out label associated with word from annotated text. I am using a bidirectional LSTM. I have X_train which is having shape (1676, 39) and Y_train with the same shape (1676, 39).
input = Input(shape=(sequence_length,))
model = Embedding(input_dim=n_words, output_dim=20,
input_length=sequence_length, mask_zero=True)(input)
model = Bidirectional(LSTM(units=50, return_sequences=True,
recurrent_dropout=0.1))(model)
out_model = TimeDistributed(Dense(50, activation="softmax"))(model)
model = Model(input, out_model)
model.compile(optimizer="rmsprop", loss= "categorical_crossentropy", metrics=["accuracy"])
model.fit(X_train, Y_train, batch_size=32, epochs= 10,
validation_split=0.1)
While executing this, I am getting error:
ValueError: Error when checking target: expected time_distributed_5 to have 3 dimensions, but got array with shape (1676, 39).
I am not able to find out how to feed proper dimension which is needed by the Keras LSTM model.
In the LSTM you set return_sequences=True, as a result, the outputs of the layer is a Tensor with shape of [batch_size * 39 * 50]. Then you pass this Tensor to TimeDistributed layer. TimeDistributed apply Dense layer on the each time stamp. The outputs of the layer, again is [batch_size * 39 * 50]. As you see, you pass 3 dimension Tensor for prediction, while your ground truth is 2 dimension (1676, 39).
How to fix the issue?
1) Remove return_sequences=True from LSTM args.
2) Remove TimeDistributed layer and apply Dense layer directly.
inps = keras.layers.Input(shape=(39,))
embedding = keras.layers.Embedding(vocab_size, 16)(inps)
rnn = keras.layers.LSTM(50)(embedding)
dense = keras.layers.Dense(50, activation="softmax")(rnn)
prediction = keras.layers.Dense(39, activation='softmax')(dense)

Python Keras LSTM input output shape issue

I am running keras over tensorflow, trying to implement a multi-dimensional LSTM network to predict a linear continuous target variable , a single value for each example(return_sequences = False).
My sequence length is 10 and number of features (dim) is 11.
This is what I run:
import pprint, pickle
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.layers import LSTM
# Input sequence
wholeSequence = [[0,0,0,0,0,0,0,0,0,2,1],
[0,0,0,0,0,0,0,0,2,1,0],
[0,0,0,0,0,0,0,2,1,0,0],
[0,0,0,0,0,0,2,1,0,0,0],
[0,0,0,0,0,2,1,0,0,0,0],
[0,0,0,0,2,1,0,0,0,0,0],
[0,0,0,2,1,0,0,0,0,0,0],
[0,0,2,1,0,0,0,0,0,0,0],
[0,2,1,0,0,0,0,0,0,0,0],
[2,1,0,0,0,0,0,0,0,0,0]]
# Preprocess Data:
wholeSequence = np.array(wholeSequence, dtype=float) # Convert to NP array.
data = wholeSequence
target = np.array([20])
# Reshape training data for Keras LSTM model
data = data.reshape(1, 10, 11)
target = target.reshape(1, 1, 1)
# Build Model
model = Sequential()
model.add(LSTM(11, input_shape=(10, 11), unroll=True, return_sequences=False))
model.add(Dense(11))
model.add(Activation('linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(data, target, nb_epoch=1, batch_size=1, verbose=2)
and get the error ValueError: Error when checking target: expected activation_1 to have 2 dimensions, but got array with shape (1, 1, 1)
Not sure what should the activation layer should get (shape wise)
Any help appreciated
thanks
If you just want to have a single linear output neuron, you can simply use a dense layer with one hidden unit and supply the activation there. Your output then can be a single vector without the reshape- I adjusted your given example code to make it work:
wholeSequence = np.array(wholeSequence, dtype=float) # Convert to NP array.
data = wholeSequence
target = np.array([20])
# Reshape training data for Keras LSTM model
data = data.reshape(1, 10, 11)
# Build Model
model = Sequential()
model.add(LSTM(11, input_shape=(10, 11), unroll=True, return_sequences=False))
model.add(Dense(1, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(data, target, nb_epoch=1, batch_size=1, verbose=2)

How to change input shape in Sequential model in Keras

I have a sequential model that I built in Keras.
I try to figure out how to change the shape of the input. In the following example
model = Sequential()
model.add(Dense(32, input_shape=(500,)))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
let's say that I want to build a new model with different input shape, conceptual this should looks like this:
model1 = model
model1.layers[0] = Dense(32, input_shape=(250,))
is there a way to modify the model input shape?
Somewhat related, so hopefully someone will find this useful: If you have an existing model where the input is a placeholder that looks like (None, None, None, 3) for example, you can load the model, replace the first layer with a concretely shaped input. Transformation of this kind is very useful when for example you want to use your model in iOS CoreML (In my case the input of the model was a MLMultiArray instead of CVPixelBuffer, and the model compilation failed)
from keras.models import load_model
from keras import backend as K
from keras.engine import InputLayer
import coremltools
model = load_model('your_model.h5')
# Create a new input layer to replace the (None,None,None,3) input layer :
input_layer = InputLayer(input_shape=(272, 480, 3), name="input_1")
# Save and convert :
model.layers[0] = input_layer
model.save("reshaped_model.h5")
coreml_model = coremltools.converters.keras.convert('reshaped_model.h5')
coreml_model.save('MyPredictor.mlmodel')
Think about what changing the input shape in that situation would mean.
Your first model
model.add(Dense(32, input_shape=(500,)))
Has a dense layer that really is a 500x32 matrix.
If you changed your input to 250 elements, your layers's matrix and input dimension would mismatch.
If, however, what you were trying to achieve was to reuse your last layer's trained parameters from your first 500 element input model, you could get those weights by get_weights. Then you could rebuild a new model and set values at the new model with set_weights.
model1 = Sequential()
model1.add(Dense(32, input_shape=(250,)))
model1.add(Dense(10, activation='softmax'))
model1.layers[1].set_weights(model1.layers[1].get_weights())
Keep in mind that model1 first layer (aka model1.layers[0]) would still be untrained
Here is another solution without defining each layer of the model from scratch. The key for me was to use "_layers" instead of "layers". The latter only seems to return a copy.
import keras
import numpy as np
def get_model():
old_input_shape = (20, 20, 3)
model = keras.models.Sequential()
model.add(keras.layers.Conv2D(9, (3, 3), padding="same", input_shape=old_input_shape))
model.add(keras.layers.MaxPooling2D((2, 2)))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(1, activation="sigmoid"))
model.compile(loss='binary_crossentropy', optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['acc'], )
model.summary()
return model
def change_model(model, new_input_shape=(None, 40, 40, 3)):
# replace input shape of first layer
model._layers[1].batch_input_shape = new_input_shape
# feel free to modify additional parameters of other layers, for example...
model._layers[2].pool_size = (8, 8)
model._layers[2].strides = (8, 8)
# rebuild model architecture by exporting and importing via json
new_model = keras.models.model_from_json(model.to_json())
new_model.summary()
# copy weights from old model to new one
for layer in new_model.layers:
try:
layer.set_weights(model.get_layer(name=layer.name).get_weights())
except:
print("Could not transfer weights for layer {}".format(layer.name))
# test new model on a random input image
X = np.random.rand(10, 40, 40, 3)
y_pred = new_model.predict(X)
print(y_pred)
return new_model
if __name__ == '__main__':
model = get_model()
new_model = change_model(model)

Resources