1D Convolutional Neural Network Input Shape `ValueError` - python

I am generating a 1D Convolution and have some trouble with the input shape of my data. I had a look at some posts and it seems the error was that the data has to be 3D but my data is already 3D.
# shape
# x_train shape: (1228, 1452, 20)
# y_train shape: (1228, 1452, 8)
# x_val shape: (223, 680, 20)
# x_val shape: (223, 680, 8)
###
n_outputs = 8
n_timesteps = 1452
n_features = 20
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(x_train.shape[1:]))) # ie 1452, 20
model.add(Conv1D(filters=64, kernel_size=3, activation='relu'))
model.add(Dropout(0.5))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(n_outputs, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=9,
batch_size=64,
shuffle=True)
But I keep on getting this error message:
ValueError: A target array with shape (1228, 1452, 8) was passed for an output of shape (None, 8) while using as loss `categorical_crossentropy`. This loss expects targets to have the same shape as the output.
What I gather from this is that target shape which is 3 dimensional is not the same as the 2 dimensional output and so it can't work out the loss, but I just need to find a way to reshape so that they are equal.
EDIT
model.summary() is shown below
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d (Conv1D) (None, 1450, 64) 3904
_________________________________________________________________
conv1d_1 (Conv1D) (None, 1448, 64) 12352
_________________________________________________________________
dropout (Dropout) (None, 1448, 64) 0
_________________________________________________________________
max_pooling1d (MaxPooling1D) (None, 724, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 46336) 0
_________________________________________________________________
dense (Dense) (None, 100) 4633700
_________________________________________________________________
dense_1 (Dense) (None, 8) 808
=================================================================
Total params: 4,650,764
Traceback (most recent call last):
Trainable params: 4,650,764
Non-trainable params: 0

The issue in my case was that the target vector was 3D whilst the output vector was 2D and so there is an obvious mismatch. To fix the issue change the shape of the y_train to (batch, 8) or use return_sequences=True to return the same shape from the previous LSTM layer.

Related

Tensorflow: Prediction of float value from image always returns 0

I have a model as follows:
from tensorflow import keras
from tensorflow.keras.layers import Dense, Conv2D, Flatten, MaxPooling2D
model = keras.Sequential([
Conv2D(16, (3, 3), padding='same', activation='relu', input_shape=(480, 640, 3), data_format="channels_last"),
MaxPooling2D(),
Conv2D(32, (3, 3), padding='same', activation='relu'),
MaxPooling2D(),
Conv2D(64, (3, 3), padding='same', activation='relu'),
MaxPooling2D(),
Flatten(),
Dense(480, activation='relu'),
Dense(1, activation="relu")
])
model.compile(optimizer='adam',
loss=keras.losses.MeanSquaredError(),
metrics=['accuracy'])
epochs = 3
model.fit(
x=train_images,
y=train_values,
epochs=epochs
)
The variable train_images is an array of PNG images (640x480 pixels) and train_values is an array of floats (e.g: [1.11842, -17.894, 2.03, ...].
My goal is to predict the float value (at least, to find some approximate value), so I suppose that MSE should be the loss function in this case.
However, after training the model, I only get zeros not only with model.predict(test_images) but also with model.predict(train_images).
Note: I have to recall that my batch contains only 37 images, and my test sample contains 14. I know that the size is ridiculous, but this script is just a concept for something bigger.
If it helps, here is the result of model.summary():
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 480, 640, 16) 448
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 240, 320, 16) 0
_________________________________________________________________
conv2d_1 (Conv2D) (None, 240, 320, 32) 4640
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 120, 160, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 120, 160, 64) 18496
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 60, 80, 64) 0
_________________________________________________________________
flatten (Flatten) (None, 307200) 0
_________________________________________________________________
dense (Dense) (None, 480) 147456480
_________________________________________________________________
dense_1 (Dense) (None, 1) 481
=================================================================
Total params: 147,480,545
Trainable params: 147,480,545
Non-trainable params: 0
To start with change your activation function, relu limits values so anything below 0 = 0, thats not desire-able
Secondly normalize your y values, as it stands your values could be anywhere from -inf to +inf, range normalize them and store the normalization parameters. At run time you could always reverse this and get actual values
Also pump up the epochs, with that small a train set i suggest try overfitting the network, if a network overfits it will most likely train well
For now try these suggestions out, i think normalization is quite important
ALSO :: I suggest make the network much deeper, you need to extract the shapes and textures in the image and your network might not be deep enough (or as a matter of fact even be dense enough) to do that. I suggest use keras to load a pre trained model like VGG16, strip the head off add regression layers and transfer learn it onto your dataset. That could be better

Keras Conv2D CNN - Error when checking target - expected smaller output

I am stacking 6 layers of 2D satellite imagery (x data) and attempting to run a CNN over them to classify the landcover (using 8 land cover classes taken from a reformatted USDA Crop Data Layer - y data).
The x data is shaped (2004, 2753, 6) and the y is shaped (2004, 2753, 8) originally and I have used data_x.reshape(-1,2004,2752,6) (same for y) to add an extra dimension as the model.
The 8 categories in the y data-set represent 8 possible land-cover categories in numerical format in 8 bands (i.e. 1st band is corn and represented by 1's for positive and 0 for not corn).
However, when i try to run the model the expected shape does not match what is being passed through to it. I am unsure if I am using the correct model structure or data structure - one idea would be to take the 8 bands of the y dataset
Based on some serious googling i have been learning how to get the data into the correct format with the right number of dimensions etc but feel I am falling at the last hurdle with regards to dimensions (and most likely correct preparation of the x & y data sets).
Below is the CNN model
input_shape=([2004, 2753, 6])
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),strides=(1, 1),activation='relu',input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2,2), strides=(2, 2), padding="same"))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2), padding="same"))
model.add(Dropout(0.25))
#model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(8, activation='softmax'))
#model.add(Flatten())
model.summary()
Model Summary - expecting 500, 687, 8 out at the end
Layer (type) Output Shape Param #
=================================================================
conv2d_54 (Conv2D) (None, 2002, 2751, 32) 1760
_________________________________________________________________
max_pooling2d_52 (MaxPooling (None, 1001, 1376, 32) 0
_________________________________________________________________
conv2d_55 (Conv2D) (None, 999, 1374, 32) 9248
_________________________________________________________________
max_pooling2d_53 (MaxPooling (None, 500, 687, 32) 0
_________________________________________________________________
dropout_57 (Dropout) (None, 500, 687, 32) 0
_________________________________________________________________
dense_59 (Dense) (None, 500, 687, 128) 4224
_________________________________________________________________
dropout_58 (Dropout) (None, 500, 687, 128) 0
_________________________________________________________________
dense_60 (Dense) (None, 500, 687, 8) 1032
=================================================================
Total params: 16,264
Trainable params: 16,264
Non-trainable params: 0
_________________________________________________________________
compile
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
fit - and where i get the error message
history = model.fit(x_train3d, y_train3d,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_split=0.2, validation_data=None)
shape of x_train3D = (1, 2004, 2753, 6)
shape of y_train3D = (1, 2004, 2753, 8)
error message
ValueError: Error when checking target: expected dense_58 to have shape (500, 687, 8) but got array with shape (2004, 2753, 8)
Again, I suspect this is down to needing to get the data in the right format both for the input and output but also likely something wrong in the specification of the model. Would appreciate some guidance as i'm new to Keras.
Can you please explain what are you trying to classifiy and what is your expected y_train3D (is it an image or some value for classificaton e.g. 1/2/3.. or x/y/z..etc)
Just for an update on this - I have managed to clear the error (and now onto a memory error but that's another question).
Solved the issue in 2 ways.
1. Added upsampling to the end of the model to get the data back into the original size - new code in below
model = Sequential()
model.add(Conv2D(32, (3, 3), padding="same", activation="relu",input_shape=input_shape))
model.add(MaxPooling2D(pool_size=(2, 2),strides=(2, 2)))
model.add(Conv2D(64, (3, 3), padding="same", activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (3, 3), padding="same", activation="relu"))
#Upsampling
model.add(UpSampling2D(size=(2,2),interpolation='nearest'))
model.add(UpSampling2D(size=(2,2),interpolation='nearest'))
model.add(Dense(8, activation='relu'))
model.summary()
Give me the below summary
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 2004, 2752, 32) 1760
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 1002, 1376, 32) 0
_________________________________________________________________
conv2d_2 (Conv2D) (None, 1002, 1376, 64) 18496
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 501, 688, 64) 0
_________________________________________________________________
conv2d_3 (Conv2D) (None, 501, 688, 128) 73856
_________________________________________________________________
up_sampling2d_1 (UpSampling2 (None, 1002, 1376, 128) 0
_________________________________________________________________
up_sampling2d_2 (UpSampling2 (None, 2004, 2752, 128) 0
_________________________________________________________________
dense_1 (Dense) (None, 2004, 2752, 8) 1032
=================================================================
Total params: 95,144
Trainable params: 95,144
Non-trainable params: 0
Part 2 - was ensuring the x and y data arrays were dividable by 4, otherwise this meant as I was losing some of the data through the model through rounding. The below is specific to my code and not robust but worked
if x_train3d.shape[2] % 2:
x_train3d_adj = x_train3d_adj[:,:,:-1,:]
y_train3d_adj = y_train3d_adj[:,:,:-1,:]
Not a complete solution yet but does get me closer to the end goal

Shapes error in Convolutional Neural Network

I'm trying to train a neural network with the following structure:
model = Sequential()
model.add(Conv1D(filters = 300, kernel_size = 5, activation='relu', input_shape=(4000, 1)))
model.add(Conv1D(filters = 300, kernel_size = 5, activation='relu'))
model.add(MaxPooling1D(3))
model.add(Conv1D(filters = 320, kernel_size = 5, activation='relu'))
model.add(MaxPooling1D(3))
model.add(Dropout(0.5))
model.add(Dense(num_labels, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
return model
And I'm getting this error:
expected dense_1 to have shape (442, 3) but got array with shape (3, 1)
My input is a set of phrases (12501 total) that have been tokenized for the 4000 most relevant words, and there's 3 possible classification. Therefore my input is train_x.shape = (12501, 4000). I reshaped this to (12501, 4000, 1) for the Conv1D layer. Now, my train_y.shape = (12501,3), and I reshaped that into (12501,3, 1).
I'm using the fit function as follows:
model.fit(train_x, train_y, batch_size=32, epochs=10, verbose=1, validation_split=0.2, shuffle=True)
What am I doing wrong?
There's no need to convert label shape for classification. And you can look at your network structure.
print(model.summary())
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d_1 (Conv1D) (None, 3996, 300) 1800
_________________________________________________________________
conv1d_2 (Conv1D) (None, 3992, 300) 450300
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 1330, 300) 0
_________________________________________________________________
conv1d_3 (Conv1D) (None, 1326, 320) 480320
_________________________________________________________________
max_pooling1d_2 (MaxPooling1 (None, 442, 320) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 442, 320) 0
_________________________________________________________________
dense_1 (Dense) (None, 442, 3) 963
=================================================================
Total params: 933,383
Trainable params: 933,383
Non-trainable params: 0
_________________________________________________________________
The last output of the model is (None, 442, 3), but the shape of your label is (None, 3, 1). You should eventually ending in either a global pooling layer GlobalMaxPooling1D() or a Flatten layer Flatten(), turning the 3D outputs into 2D outputs, for classification or regression.

Keras 2D input to 2D output

First, I have read this and this questions with similar names to mine and still do not have an answer.
I want to build a feedforward network for sequence prediction. (I realize that RNNs are more suitable for this task, but I have my reasons). The sequences are of length 128 and each element is a vector with 2 entries, so each batch should be of shape (batch_size, 128, 2) and the target is the next step in the sequence, so the target tensor should be of shape (batch_size, 1, 2).
The network architecture is something like this:
model = Sequential()
model.add(Dense(50, batch_input_shape=(None, 128, 2), kernel_initializer="he_normal" ,activation="relu"))
model.add(Dense(20, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(5, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(2))
But trying to train I get the following error:
ValueError: Error when checking target: expected dense_4 to have shape (128, 2) but got array with shape (1, 2)
I've tried variations like:
model.add(Dense(50, input_shape=(128, 2), kernel_initializer="he_normal" ,activation="relu"))
but get the same error.
If you take a look at the model.summary() output you will see that what the issue is:
Layer (type) Output Shape Param #
=================================================================
dense_13 (Dense) (None, 128, 50) 150
_________________________________________________________________
dense_14 (Dense) (None, 128, 20) 1020
_________________________________________________________________
dense_15 (Dense) (None, 128, 5) 105
_________________________________________________________________
dense_16 (Dense) (None, 128, 2) 12
=================================================================
Total params: 1,287
Trainable params: 1,287
Non-trainable params: 0
_________________________________________________________________
As you can see, the output of the model is (None, 128,2) and not (None, 1, 2) (or (None, 2)) as you expected. So, you may or may not know that Dense layer is applied on the last axis of its input array and as a result, as you see above, the time axis and dimension is preserved until the end.
How to resolve this? You mentioned you don't want to use a RNN layer, therefore you have two options: you need to either use Flatten layer somewhere in the model or you can also use some Conv1D + Pooling1D layers or even a GlobalPooling layer. For example (these are just for demonstration, you may do it differently):
using Flatten layer
model = models.Sequential()
model.add(Dense(50, batch_input_shape=(None, 128, 2), kernel_initializer="he_normal" ,activation="relu"))
model.add(Dense(20, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(5, kernel_initializer="he_normal", activation="relu"))
model.add(Flatten())
model.add(Dense(2))
model.summary()
Model summary:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_17 (Dense) (None, 128, 50) 150
_________________________________________________________________
dense_18 (Dense) (None, 128, 20) 1020
_________________________________________________________________
dense_19 (Dense) (None, 128, 5) 105
_________________________________________________________________
flatten_1 (Flatten) (None, 640) 0
_________________________________________________________________
dense_20 (Dense) (None, 2) 1282
=================================================================
Total params: 2,557
Trainable params: 2,557
Non-trainable params: 0
_________________________________________________________________
using GlobalAveragePooling1D layer
model = models.Sequential()
model.add(Dense(50, batch_input_shape=(None, 128, 2), kernel_initializer="he_normal" ,activation="relu"))
model.add(Dense(20, kernel_initializer="he_normal", activation="relu"))
model.add(GlobalAveragePooling1D())
model.add(Dense(5, kernel_initializer="he_normal", activation="relu"))
model.add(Dense(2))
model.summary()
​Model summary:
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_21 (Dense) (None, 128, 50) 150
_________________________________________________________________
dense_22 (Dense) (None, 128, 20) 1020
_________________________________________________________________
global_average_pooling1d_2 ( (None, 20) 0
_________________________________________________________________
dense_23 (Dense) (None, 5) 105
_________________________________________________________________
dense_24 (Dense) (None, 2) 12
=================================================================
Total params: 1,287
Trainable params: 1,287
Non-trainable params: 0
_________________________________________________________________
Note that in both cases above you need to reshape the labels (i.e. targets) array to (n_samples, 2) (or you may want to use a Reshape layer at the end).

LSTM and CNN: ValueError: Error when checking target: expected time_distributed_1 to have 3 dimensions, but got array with shape (400, 256)

I want to apply CNN and LSTM on my data, I just choose a small set of data; My training data's size is (400,50)and my testing data is (200,50).
With only CNN model, it works without any errors, I just have many errors when adding the LSTM model:
model = Sequential()
model.add(Conv1D(filters=8,
kernel_size=16,
padding='valid',
activation='relu',
strides=1, input_shape=(50,1)))
model.add(MaxPooling1D(pool_size=2,strides=None, padding='valid', input_shape=(50,1))) # strides=None means strides=pool_size
model.add(Conv1D(filters=8,
kernel_size=8,
padding='valid',
activation='relu',
strides=1))
model.add(MaxPooling1D(pool_size=2,strides=None, padding='valid',input_shape=(50,1)))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2)) # 100 num of LSTM units
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(TimeDistributed(Dense(256, activation='softmax')))
# # # 4. Compile model
print('########################### Compilation of the model ######################################')
model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
print(model.summary())
print('###########################Fitting the model ######################################')
# # # # # 5. Fit model on training data
x_train = x_train.reshape((400,50,1))
print(x_train.shape) # (400,50,1)
x_test = x_test.reshape((200,50,1))
print(x_test.shape) # (200,50,1)
model.fit(x_train, y_train, batch_size=100, epochs=100,verbose=0)
print(model.summary())
# # # # # 6. Evaluate model on test data
score = model.evaluate(x_test, y_test, verbose=0)
print (score)
This is the error:
Traceback (most recent call last):
File "CNN_LSTM_Based_Attack.py", line 156, in <module>
model.fit(x_train, y_train, batch_size=100, epochs=100,verbose=0)
File "/home/doc/.local/lib/python2.7/site-packages/keras/models.py", line 853, in fit
initial_epoch=initial_epoch)
File "/home/doc/.local/lib/python2.7/site-packages/keras/engine/training.py", line 1424, in fit
batch_size=batch_size)
File "/home/doc/.local/lib/python2.7/site-packages/keras/engine/training.py", line 1304, in _standardize_user_data
exception_prefix='target')
File "/home/doc/.local/lib/python2.7/site-packages/keras/engine/training.py", line 127, in _standardize_input_data
str(array.shape))
ValueError: Error when checking target: expected time_distributed_1 to have 3 dimensions, but got array with shape (400, 256)
You can find here the whole summary for this model:(I am new with LSTM it is the first time that I use it).
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv1d_1 (Conv1D) (None, 35, 8) 136
_________________________________________________________________
max_pooling1d_1 (MaxPooling1 (None, 17, 8) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 17, 8) 0
_________________________________________________________________
conv1d_2 (Conv1D) (None, 10, 8) 520
_________________________________________________________________
max_pooling1d_2 (MaxPooling1 (None, 5, 8) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 5, 8) 0
_________________________________________________________________
lstm_1 (LSTM) (None, 5, 32) 5248
_________________________________________________________________
lstm_2 (LSTM) (None, 5, 32) 8320
_________________________________________________________________
lstm_3 (LSTM) (None, 5, 32) 8320
_________________________________________________________________
lstm_4 (LSTM) (None, 5, 32) 8320
_________________________________________________________________
lstm_5 (LSTM) (None, 5, 32) 8320
_________________________________________________________________
time_distributed_1 (TimeDist (None, 5, 256) 8448
=================================================================
Total params: 47,632
Trainable params: 47,632
Non-trainable params: 0
_________________________________________________________________
When I replace this lines of code:
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2)) # 100 num of LSTM units
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(LSTM(32, return_sequences=True,
activation='tanh', recurrent_activation='hard_sigmoid',
dropout=0.2,recurrent_dropout=0.2))
model.add(TimeDistributed(Dense(256, activation='softmax')))
With only this line:
model.add(LSTM(26, activation='tanh'))
Than it works very well.
I would be grateful if you could help me please.
So LSTM layers expect input in shape (Samples, Time steps, Features). When stacking LSTM you should return_sequences = True. This will give an output of shape (Samples, Time steps, units), thus allowing the stack to fit together - You should set return_sequences = False on the last LSTM-layer if you only want to predict one step ahead (i.e. the next value in the sequence/time series) - if you don't it will predict the same number of time steps as is in the input. You can of cause also predict a different number (e.g. given 50 past observations predict the next 10, but it is a little tricky in Keras).
In your case the Conv/MaxPool-layers output 5 "time steps" and you have return_sequences = True on the last LSTM-layer - so your "y" must have shape (Samples, 5, 256) - otherwise turn return_sequences = False on the last layer and don't use TimeDistributed, as you only predict one time step ahead.

Categories