Keras input dim error - keras

while Iam experimenting with keras and Gym of Openai and I keep getting this error
ValueError: Error when checking input: expected reshape_1_input to have shape (None, 979, 1) but got array with shape (979, 1, 1)
I gather my Data as follow:
def getData():
rewardc = 0
rewardo = 0
labels = np.array([])
data = np.array([])
for i in range(11):
print("run",i)
for _ in range (10000):
print("---------------------------------------------------------------------------")
print("action", _)
#env.render()
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
if done:
env.reset()
break
rewardc = rewardo - reward
rewardo = reward
observationo = observation
rewardco = rewardc
ohobservation = np.array(observationo)
ohobservation = np.append(ohobservation, rewardo)
ohobservation = np.append(ohobservation, rewardco)
#print ("whole observation",ohobservation)
#print("data", data)
labelsb = np.array([action])
if labels.size == 0:
labels = labelsb
else:
labels = np.vstack((labels,action))
if data.size == 0:
data = ohobservation
else:
data = np.vstack((data, ohobservation))
return labels, data
My x array will look like that:
[ [2] [0] [2] [3] [0] [0] .. [2] [3]]
My Y:
Y [[ 1.15792274e-02 9.40991027e-01 5.85608387e-01 ..., 0.00000000e+00
-5.27112172e-01 5.27112172e-01]
[ 1.74466133e-02 9.40591342e-01 5.95346880e-01 ..., 0.00000000e+00
-1.88372436e+00 1.35661219e+00]
[ 2.32508659e-02 9.39789397e-01 5.87415648e-01 ..., 0.00000000e+00
-4.41631844e-02 -1.83956118e+00]
Network Code:
model = Sequential()
model.add(Dense(units= 64, input_dim= 100))
model.add(Activation('relu'))
model.add(Dense(units=10))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
model.fit(X,Y, epochs=5)
But I cannot feed it in Keras at any Chance.
It would be awesome if somebody could help me solve it thank you!

Inputs
If your data is 979 examples, each example containing one element, make sure that its first dimension is 979
print(X.shape) #confirm that the shape is (979,1) or (979,)
If the shape is different from that, you will have to reshape the array, because the Dense layer expects shapes in those forms.
X = X.reshape((979,))
Now, make sure that your Dense layer is compatible with that shape:
#using input_dim:
Dense(units=64, input_dim=1) #each example has only one element
#or, using input_shape:
Dense(units=64, input_shape=(1,)) #input_shape must always be a tuple. Again, the number of examples shouldn't be a part of this shape
This will solve the problems you have with the inputs. All the error messages you get like this one are about the compatibility between your input data and the input shape you gave to the first layer:
Error when checking input: expected reshape_1_input to have shape (None, 979, 1)
but got array with shape (979, 1, 1)
The first shape in the message is the input_shape you passed to the layer. The second is the shape of your actual data.
Outputs
The same compatibility is necessary for Y, but now with the last layer.
If you put units=10 in the last layer, it means your labels must be of shape (979,10).
If your labels don't have that shape, adjust the number of cells to match it.

Related

Numpy and tensorflow RNN shape representation mismatch

I'm building my first RNN in tensorflow. After understanding all the concepts regarding the 3D input shape, I came across with this issue.
In my numpy version (1.15.4), the shape representation of 3D arrays is the following: (panel, row, column). I will make each dimension different so that it is clearer:
In [1]: import numpy as np
In [2]: arr = np.arange(30).reshape((2,3,5))
In [3]: arr
Out[3]:
array([[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]],
[[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24],
[25, 26, 27, 28, 29]]])
In [4]: arr.shape
Out[4]: (2, 3, 5)
In [5]: np.__version__
Out[5]: '1.15.4'
Here my understanding is: I have two timesteps with each timestep having 3 observations with 5 features in each observation.
However, in tensorflow "theory" (which I believe it is strongly based in numpy) RNN cells expect tensors (i.e. just n-dimensional matrices) of shape [batch_size, timesteps, features], which could be translated to: (row, panel, column) in the numpy "jargon".
As can be seen, the representation doesn't match, leading to errors when feeding numpy data into a placeholder, which in most of the examples and theory is defined like:
x = tf.placeholder(tf.float32, shape=[None, N_TIMESTEPS_X, N_FEATURES], name='XPlaceholder')
np.reshape() doesn't solve the issue because it just rearranges the dimensions, but messes up with the data.
I'm using for the first time the Dataset API, but I encounter the problems once into the session, not in the Dataset API ops.
I'm using the static_rnn method, and everything works well until I have to feed the data into the placeholder, which obviously results in a shape error.
I have tried to change the placeholder shape to shape=[N_TIMESTEPS_X, None, N_FEATURES]. HOWEVER, I'm using the dataset API, and I get errors when making the initializer if I change the Xplaceholder to the shape=[N_TIMESTEPS_X, None, N_FEATURES].
So, to summarize:
First problem: Shape errors with different shape representations.
Second problem: Dataset error when equating the shape representations (I think that either static_rnn or dynamic_rnn would function if this is resolved).
My question is:
¿Is there anything I'm missing in regard to this different representation logic which makes the practice confusing?
¿Could the solution be attained to switching to dynamic_rnn? (although the problems about the shape I encounter are related to the dataset API initializer being fed with shape [N_TIMESTEPS_X, None, N_FEATURES], not with the RNN cell itself.
Thank you very much for your time.
Full code:
'''The idea is to create xt, yt, xval and yval. My numpy arrays to
be fed are of the following shapes:
The 3D xt array has a shape of: (11, 69579, 74)
The 3D xval array has a shape of: (11, 7732, 74)
The yt array has a shape of: (69579, 3)
The yval array has a shape of: (7732, 3)
'''
N_TIMESTEPS_X = xt.shape[0] ## The stack number
BATCH_SIZE = 256
#N_OBSERVATIONS = xt.shape[1]
N_FEATURES = xt.shape[2]
N_OUTPUTS = yt.shape[1]
N_NEURONS_LSTM = 128 ## Number of units in the LSTMCell
N_NEURONS_DENSE = 64 ## Number of units in the Dense layer
N_EPOCHS = 600
LEARNING_RATE = 0.1
### Define the placeholders anda gather the data.
train_data = (xt, yt)
validation_data = (xval, yval)
## We define the placeholders as a trick so that we do not break into memory problems, associated with feeding the data directly.
'''As an alternative, you can define the Dataset in terms of tf.placeholder() tensors, and feed the NumPy arrays when you initialize an Iterator over the dataset.'''
batch_size = tf.placeholder(tf.int64)
x = tf.placeholder(tf.float32, shape=[None, N_TIMESTEPS_X, N_FEATURES], name='XPlaceholder')
y = tf.placeholder(tf.float32, shape=[None, N_OUTPUTS], name='YPlaceholder')
# Creating the two different dataset objects.
train_dataset = tf.data.Dataset.from_tensor_slices((x,y)).batch(BATCH_SIZE).repeat()
val_dataset = tf.data.Dataset.from_tensor_slices((x,y)).batch(BATCH_SIZE)
# Creating the Iterator type that permits to switch between datasets.
itr = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes)
train_init_op = itr.make_initializer(train_dataset)
validation_init_op = itr.make_initializer(val_dataset)
next_features, next_labels = itr.get_next()
### Create the graph
cellType = tf.nn.rnn_cell.LSTMCell(num_units=N_NEURONS_LSTM, name='LSTMCell')
inputs = tf.unstack(next_features, N_TIMESTEPS_X, axis=0)
'''inputs: A length T list of inputs, each a Tensor of shape [batch_size, input_size]'''
RNNOutputs, _ = tf.nn.static_rnn(cell=cellType, inputs=inputs, dtype=tf.float32)
predictionsLayer = tf.layers.dense(inputs=tf.layers.batch_normalization(RNNOutputs[-1]), units=N_NEURONS_DENSE, activation=None, name='Dense_Layer')
### Define the cost function, that will be optimized by the optimizer.
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=predictionsLayer, labels=next_labels, name='Softmax_plus_Cross_Entropy'))
optimizer_type = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE, name='AdamOptimizer')
optimizer = optimizer_type.minimize(cost)
### Model evaluation
correctPrediction = tf.equal(tf.argmax(predictionsLayer,1), tf.argmax(y,1))
accuracy = tf.reduce_mean(tf.cast(correctPrediction,tf.float32))
#confusionMatrix = tf.confusion_matrix(next_labels, predictionsLayer, num_classes=3, name='ConfMatrix')
N_BATCHES = train_data[0].shape[0] // BATCH_SIZE
## Saving variables so that we can restore them afterwards.
saver = tf.train.Saver()
save_dir = '/home/zmlaptop/Desktop/tfModels/{}_{}'.format(cellType.__class__.__name__, datetime.now().strftime("%Y%m%d%H%M%S"))
os.mkdir(save_dir)
varDict = {'nTimeSteps':N_TIMESTEPS_X, 'BatchSize': BATCH_SIZE, 'nFeatures':N_FEATURES,
'nNeuronsLSTM':N_NEURONS_LSTM, 'nNeuronsDense':N_NEURONS_DENSE, 'nEpochs':N_EPOCHS,
'learningRate':LEARNING_RATE, 'optimizerType': optimizer_type.__class__.__name__}
varDicSavingTxt = save_dir + '/varDict.txt'
modelFilesDir = save_dir + '/modelFiles'
os.mkdir(modelFilesDir)
logDir = save_dir + '/TBoardLogs'
os.mkdir(logDir)
acc_summary = tf.summary.scalar('Accuracy', accuracy)
loss_summary = tf.summary.scalar('Cost_CrossEntropy', cost)
summary_merged = tf.summary.merge_all()
with open(varDicSavingTxt, 'w') as outfile:
outfile.write(repr(varDict))
with tf.Session() as sess:
tf.set_random_seed(2)
sess.run(tf.global_variables_initializer())
train_writer = tf.summary.FileWriter(logDir + '/train', sess.graph)
validation_writer = tf.summary.FileWriter(logDir + '/validation')
# initialise iterator with train data
sess.run(train_init_op, feed_dict = {x : train_data[0], y: train_data[1], batch_size: BATCH_SIZE})
print('¡Training starts!')
for epoch in range(N_EPOCHS):
batchAccList = []
tot_loss = 0
for batch in range(N_BATCHES):
optimizer_output, loss_value, summary = sess.run([optimizer, cost, summary_merged])
accBatch = sess.run(accuracy)
tot_loss += loss_value
batchAccList.append(accBatch)
if batch % 10 == 0:
train_writer.add_summary(summary, batch)
epochAcc = tf.reduce_mean(batchAccList)
if epoch%10 == 0:
print("Epoch: {}, Loss: {:.4f}, Accuracy: {}".format(epoch, tot_loss / N_BATCHES, epochAcc))
#confM = sess.run(confusionMatrix)
#confDic = {'confMatrix': confM}
#confTxt = save_dir + '/confMDict.txt'
#with open(confTxt, 'w') as outfile:
# outfile.write(repr(confDic))
#print(confM)
# initialise iterator with validation data
sess.run(validation_init_op, feed_dict = {x : validation_data[0], y: validation_data[1], batch_size:len(validation_data[0])})
print('Validation Loss: {:4f}, Validation Accuracy: {}'.format(sess.run(cost), sess.run(accuracy)))
summary_val = sess.run(summary_merged)
validation_writer.add_summary(summary_val)
saver.save(sess, modelFilesDir)
Is there anything I'm missing in regard to this different
representation logic which makes the practice confusing?
In fact, you made a mistake about the input shapes of static_rnn and dynamic_rnn. The input shape of static_rnn is [timesteps,batch_size, features](link),which is a list of 2D tensors of shape [batch_size, features]. But The input shape of dynamic_rnn is either [timesteps,batch_size, features] or [batch_size,timesteps, features] depending on time_major is True or False(link).
Could the solution be attained to switching to dynamic_rnn?
The key is not that you use static_rnn or dynamic_rnn, but that your data shape matches the required shape. The general format of placeholder is like your code is [None, N_TIMESTEPS_X, N_FEATURES]. It's also convenient for you to use dataset API.
You can use transpose()(link) instead of reshape().transpose() will permute the dimensions of an array and won't messes up with the data.
So your code needs to be modified.
# permute the dimensions
xt = xt.transpose([1,0,2])
xval = xval.transpose([1,0,2])
# adjust shape,axis=1 represents timesteps
inputs = tf.unstack(next_features, axis=1)
Other errors should have nothing to do with rnn shape.

CTCBeamSearchDecoder thinks sequence_length of shape (2,) is not a vector

Trying to run a beam search in a Keras model, I get confusing (and conflicting?) error messages. My model has inputs such as
inputs = Input(name='spectrograms',
shape=(None, hparams["n_spectrogram"]))
input_length = Input(name='len_spectrograms',
shape=[1], dtype='int64')
and the CTC loss function requires the [1] shapes in input and label length. As far as I understand, the output should be obtained with something like
# Stick connectionist temporal classification on the end of the core model
paths = K.function(
[inputs, input_length],
K.ctc_decode(output, input_length, greedy=False, top_paths=4)[0])
but as-is, that leads to a complain about the shape of input_length
ValueError: Shape must be rank 1 but is rank 2 for 'CTCBeamSearchDecoder' (op: 'CTCBeamSearchDecoder') with input shapes: [?,?,44], [?,1].
but if I chop off that dimension
K.ctc_decode(output, input_length[..., 0], greedy=False, top_paths=4)[0])
the model definition runs, but when I run y = paths([x, numpy.array([[30], [30]])]) with a x.shape == (2, 30, 513) I suddenly get
tensorflow.python.framework.errors_impl.InvalidArgumentError: sequence_length is not a vector
[[{{node CTCBeamSearchDecoder}} = CTCBeamSearchDecoder[beam_width=100, merge_repeated=true, top_paths=4, _device="/job:localhost/replica:0/task:0/device:CPU:0"](Log, ToInt32)]]
What am I doing wrong?

Keras "Shapes must be of equal rank" error when trying to slice tensor with another tensor

Building off some of the other questions I've asked, I'm trying to define a custom loss function that allows me to slice the contents of an input tensor using the contents of another tensor:
def innerLoss(z):
y_pred = z[0]
patch_x = z[1][0]
patch_y = z[1][1]
patch_true = y_pred[patch_y:patch_y+10, patch_x:patch_x+10, 0]
return 0
originalInputs = Input(shape=(128, 128, 1))
featureInputs = Input(shape=(2,), dtype="int64")
originalOutputs = Input(shape=(128, 128, 1))
loss = Lambda(innerLoss)([originalOutputs, featureInputs])
outerModel = Model(inputs=[originalInputs, featureInputs], outputs=loss)
I'm getting the following error:
ValueError: Shapes must be equal rank, but are 1 and 0
From merging shape 1 with other shapes. for 'lambda_3/strided_slice_2/stack_1' (op: 'Pack') with input shapes: [2], [2], [].
Here, featureInputs will consist of a pair of coordinates telling us where to begin slicing the image in originalInputs.

Resnet with Custom Data

I am trying to modify Resnet50 with my custom data as follows:
X = [[1.85, 0.460,... -0.606] ... [0.229, 0.543,... 1.342]]
y = [2, 4, 0, ... 4, 2, 2]
X is a feature vector of length 2000 for 784 images. y is an array of size 784 containing the binary representation of labels.
Here is the code:
def __classifyRenet(self, X, y):
image_input = Input(shape=(2000,1))
num_classes = 5
model = ResNet50(weights='imagenet',include_top=False)
model.summary()
last_layer = model.output
# add a global spatial average pooling layer
x = GlobalAveragePooling2D()(last_layer)
# add fully-connected & dropout layers
x = Dense(512, activation='relu',name='fc-1')(x)
x = Dropout(0.5)(x)
x = Dense(256, activation='relu',name='fc-2')(x)
x = Dropout(0.5)(x)
# a softmax layer for 5 classes
out = Dense(num_classes, activation='softmax',name='output_layer')(x)
# this is the model we will train
custom_resnet_model2 = Model(inputs=model.input, outputs=out)
custom_resnet_model2.summary()
for layer in custom_resnet_model2.layers[:-6]:
layer.trainable = False
custom_resnet_model2.layers[-1].trainable
custom_resnet_model2.compile(loss='categorical_crossentropy',
optimizer='adam',metrics=['accuracy'])
clf = custom_resnet_model2.fit(X, y,
batch_size=32, epochs=32, verbose=1,
validation_data=(X, y))
return clf
I am calling to function as:
clf = self.__classifyRenet(X_train, y_train)
It is giving an error:
ValueError: Error when checking input: expected input_24 to have 4 dimensions, but got array with shape (785, 2000)
Please help. Thank you!
1. First, understand the error.
Your input does not match the input of ResNet, for ResNet, the input should be (n_sample, 224, 224, 3) but you are having (785, 2000). From your question, you have 784 images with array of size 2000, which doesn't really align with the original ResNet50 input shape of (224 x 224) no matter how you reshape it. That means you cannot use the ResNet50 directly with your data. The only thing you did in your code is to take the last layer of ResNet50 and added you output layer to align with your output class size.
2. Then, what you can do.
If you insist to use the ResNet architecture, you will need to change the input layer rather than output layer. Also, you will need to reshape your image data to utilize the convolution layers. That means, you cannot have it in a (2000,) array, but need to be something like (height, width, channel), just like what ResNet and other architectures are doing. Of course you will also need to change the output layer as well just like you did so that you are predicting for your classes. Try something like:
model = ResNet50(input_tensor=image_input_shape, include_top=True,weights='imagenet')
This way, you can specify customized input image shape. You can check the github code for more information (https://github.com/keras-team/keras/blob/master/keras/applications/resnet50.py). Here's part of the docstring:
input_shape: optional shape tuple, only to be specified
if `include_top` is False (otherwise the input shape
has to be `(224, 224, 3)` (with `channels_last` data format)
or `(3, 224, 224)` (with `channels_first` data format).
It should have exactly 3 inputs channels,
and width and height should be no smaller than 197.
E.g. `(200, 200, 3)` would be one valid value.

1D Convolutional network with keras, error on input size

I'm trying to build a convolutional neural network for my dataset. My training dataset has 1209 examples of 800 features each.
Here's what part of the code looks like :
model = Sequential()
model.add(Conv1D(64, 3, activation='linear', input_shape=(1209, 800)))
model.add(GlobalMaxPooling1D())
model.add(Dense(1, activation='linear'))
model.compile(loss=loss_type, optimizer=optimizer_type, metrics=[metrics_type])
model.fit(X, Y, validation_data=(X2,Y2),epochs = nb_epochs,
batch_size = batch_size,shuffle=True)
When I compile this code, I get the following error :
Error when checking input: expected conv1d_25_input to have 3 dimensions,
but got array with shape (1209, 800)
So I add a dimension, here's what I do :
X = np.expand_dims(X, axis=0)
X2 = np.expand_dims(X2, axis=0)
And then I get this error :
ValueError: Input arrays should have the same number of samples as target arrays.
Found 1 input samples and 1209 target samples.
My training data has now a shape like this (1, 1209, 800), should it be something else ?
Thanks a lot for reading this.
Instead of expanding the dimensions on X at axis 0, you should expand on axis 2. Thus, rather than X = np.expand_dims(X, axis=0), you need X = np.expand_dims(X, axis=2).
Afterwards, the shape of X should be (1209, 800, 1), and you should then specify input_shape=(800, 1) in your first layer.

Resources