How to use MaxPooling1D with Conv1D - python

I use Conv1D like this
X_train_t = X_train.reshape(X_train.shape[0], 1,12)
X_test_t = X_test.reshape(X_test.shape[0], 1,12)
print(X_train_t.shape)
print(X_train_t)
K.clear_session()
model = Sequential()
model.add(Conv1D(12,1, activation='relu', input_shape=(1,12)))
#model.add(MaxPooling1D(pool_size = (6)))
model.add(LSTM(3))
model.add(Dense(1))
I add maxpooling to improve performance like this under line model.add(Conv1D..
model.add(MaxPooling1D(pool_size = (6)))
but it show error like this
ValueError: Negative dimension size caused by subtracting 6 from 1 for 'max_pooling1d_1/MaxPool' (op: 'MaxPool') with input shapes: [?,1,1,12].
It work if I set pool_size = (1) but it increase more loss value. If I want to change pool_size to another value not 1. How to edit model ?

MaxPooling1D needs a 3d Tensor for its inputs with shape: (batch_size, steps, features). Based on your code, X_train_t and X_test_t have 1 step (*.shape[0], 1, 12). When Pooling moves its window 6 steps (pool_size=(6)) it can't. As a result it throws such an exception.
Suggestion: Try to change your input shape
Minimal example: Here is the one possible solution with Conv1D:
model = Sequential()
model.add(Embedding(input_dim=1000, output_dim=128, input_shape=(12,))
model.add(Convolution1D(filters=2, kernel_size=100, padding='same', activation=tf.nn.relu))
model.add(MaxPooling1D(pool_size=6))
model.add(GlobalAveragePooling1D())
model.add(Dense(2))

I added a Dense layer and Reshape Layer to overcome this issue.
model = Sequential()
model.add(Conv1D(12,1, activation='relu', input_shape=(1,12)))
model.add(Dense(32*3))
model.add(Reshape((3,32)))
model.add(MaxPooling1D(pool_size = (3)))
model.add(LSTM(32))
model.add(Dense(1))

Related

CNN-LSTM with TimeDistributed Layers behaving weirdly when trying to use tf.keras.utils.plot_model

I have a CNN-LSTM that looks as follows;
SEQUENCE_LENGTH = 32
BATCH_SIZE = 32
EPOCHS = 30
n_filters = 64
n_kernel = 1
n_subsequences = 4
n_steps = 8
def DNN_Model(X_train):
model = Sequential()
model.add(TimeDistributed(
Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu', input_shape=(n_subsequences, n_steps, X_train.shape[3]))))
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(100, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mse', optimizer='adam')
return model
I'm using this CNN-LSTM for a multivariate time series forecasting problem. the CNN-LSTM input data comes in the 4D format: [samples, subsequences, timesteps, features]. For some reason, I need TimeDistributed Layers; or I get errors like ValueError: Input 0 of layer conv1d is incompatible with the layer: expected ndim=3, found ndim=4. Full shape received: [None, 4, 8, 35]. I think this has to do with the fact that Conv1D is officially not meant for time series, so to preserve time-series data shape we need to use a wrapper layer like TimeDistributed. I don't really mind using TimeDistributed layers - They're wrappers and if they make my model work I am happy. However, when I try to visualize my model with
file = 'CNN_LSTM_Visualization.png'
tf.keras.utils.plot_model(model, to_file=file, show_layer_names=False, show_shapes=False)
The resulting visualization only shows the Sequential():
I suspect this has to do with the TimeDistributed layers and the model not being built yet. I cannot call model.summary() either - it throws ValueError: This model has not yet been built. Build the model first by calling build()or callingfit()with some data, or specify aninput_shape argument in the first layer(s) for automatic build Which is strange because I have specified the input_shape, albeit in the Conv1D layer and not in the TimeDistributed wrapper.
I would like a working model together with a working tf.keras.utils.plot_model function. Any explanation as to why I need TimeDistributed and why it makes the plot_model function behave weirdly would be greatly awesome.
An alternative to using an Input layer is to simply pass the input_shape to the TimeDistributed wrapper, and not the Conv1D layer:
def DNN_Model(X_train):
model = Sequential()
model.add(TimeDistributed(
Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu'), input_shape=(n_subsequences, n_steps, X_train.shape[3])))
model.add(TimeDistributed(Conv1D(filters=n_filters, kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(100, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='mse', optimizer='adam')
return model
Add your input layer at the beginning. Try this
def DNN_Model(X_train):
model = Sequential()
model.add(InputLayer(input_shape=(n_subsequences, n_steps, X_train)))
model.add(TimeDistributed(
Conv1D(filters=n_filters, kernel_size=n_kernel,
activation='relu')))
model.add(TimeDistributed(Conv1D(filters=n_filters,
kernel_size=n_kernel, activation='relu')))
model.add(TimeDistributed(MaxPooling1D(pool_size=2)))
....
Now, you can plot and get a summary properly.
DNN_Model(3).summary() # OK
tf.keras.utils.plot_model(DNN_Model(3)) # OK

How to fix: ValueError: Input 0 is incompatible with layer lstm_2: expected ndim=3, found ndim=2

I have a question concerning time series data. My training dataset has the dimension (3183, 1, 6)
My model:
model = Sequential()
model.add(LSTM(100, input_shape = (training_input_data.shape[1], training_input_data.shape[2])))
model.add(Dropout(0.2))
model.add(LSTM(100, input_shape = (training_input_data.shape[1], training_input_data.shape[2])))
model.add(Dense(1))
model.compile(optimizer = 'adam', loss='mse')
I get the following error at the second LSTM layer:
ValueError: Input 0 is incompatible with layer lstm_2: expected
ndim=3, found ndim=2 But there is no ndim parameter.
The problem is that the first LSTM layer is returning something with shape (batch_size, 100). If you want to iterate with a 2nd LSTM layer, you should probably add the option return_sequences=True in the first LSTM layer (which would then return an object of shape (batch_size, training_input_data.shape[1], 100).
Note that passing input_shape = (..) in the 2nd LSTM is not mandatory, as the input shape of this layer is autoamtically computed based on the output shape of the first one.
You need to set parameter return_sequences=True to stack LSTM layers.
model = Sequential()
model.add(LSTM(
100,
input_shape = (training_input_data.shape[1], training_input_data.shape[2]),
return_sequences=True
))
model.add(Dropout(0.2))
model.add(LSTM(100, input_shape = (training_input_data.shape[1], training_input_data.shape[2])))
model.add(Dense(1))
model.compile(optimizer = 'adam', loss='mse')
See also How to stack multiple lstm in keras?

Keras fully connected followed by convolution

I'm not super amazing with keras yet, so please be gentle.
My input data is a matrix of size 60000 x 784.
I'm trying to add convolutional layers after my fully connected layers, something like this:
model = Sequential()
model.add(Dense(784, input_dim=train_amplitudes.shape[1], activation='relu'))
model.add(Dense(784, activation='relu'))
model.add(Dense(784, activation='relu'))
model.add(Conv2D(100, kernel_size=5, activation='relu', input_shape=(28, 28))
mode.add(Conv2D(20, kernel_size = 3, activation = 'relu'))
model.add(Dense(train_targets.shape[1], activation='linear'))
Notice that 28 * 28 = 784.
I get the error "Input 0 is incompatible with layer conv2d_1: expected ndim=4, found ndim=2" at the first convolution layer.
Why and how can I fix this?
What is the purpose of this specific network structure? Assuming that your original data was 28x28, you should leave the input with 28x28 and then apply conv2d. After that you can flatten the last output of the convolutional blocks to continue with the fully connected layers.
In Keras, input shape argument is a 4D tensor with shape: (batch, channels, rows, cols) if data_format is "channels_first" or 4D tensor with shape: (batch, rows, cols, channels) if data_format is "channels_last". You're just passing rows and columns (what you think) but it also requires batch and channels. More information can be found here.
I think I've managed to fix it. This is the code that "works"
model = Sequential()
model.add(Dense(784, input_dim=train_amplitudes.shape[1], activation='relu'))
model.add(Dense(784, activation='relu'))
model.add(Dense(784, activation='relu'))
mode.add(Reshape((28, 28, 1))
model.add(Conv2D(100, kernel_size=5, activation='relu')
mode.add(Conv2D(20, kernel_size = 3, activation = 'relu'))
model.add(Flatten())
model.add(Dense(train_targets.shape[1], activation='linear'))
it works in the sense that no error is produced. Whether it makes sense or produces a good output, that's another matter, but this is good enough for me.

How to get one output for several timestep in Keras LSTM?

I want to classifying a timeframe of data. So for example every 5 input, there's one output. But my code refuse to accept my output.
model = Sequential()
model.add(GRU(32, input_shape=(TimeStep.TIME_STEP + 1, 10), return_sequences=True, activation='relu'))
model.add(GRU(64, activation='relu', return_sequences=True))
model.add(Dense(2, activation='hard_sigmoid'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=[categorical_accuracy])
history = model.fit(TimeStep.fodder, TimeStep.target, epochs=50)
The error:
ValueError: Error when checking target: expected dense_1 to have shape (5, 2) but got array with shape (31057, 2)
It does have 31057 data point that each data point consist of 5 sequential data.
The return_sequences param in the GRU layer instructs the model to return the state at each time step rather than the final activation.
If you set that flag to False in the second GRU, your model will return the shape that you expect.
Tip: use model.summary() to display the output shapes of your layers.
For a model with a categorical loss you want the output layer activation to be a softmax not a sigmoid.

ValueError: Input 0 is incompatible with layer lstm_14: expected ndim=3, found ndim=2

I am building a cnn_rnn network for image classification. I am getting an error while running the following python code in my jupyter notebook.
# model
model1 = Sequential()
# first convolutional layer
model1.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape(160, 120, 3)))
# second convolutional layer
model1.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
#Adding a pooling Layer
model1.add(MaxPooling2D(pool_size=(3, 3)))
#Adding dropouts
model1.add(Dropout(0.25))
# flatten and put a fully connected layer
model1.add(Flatten())
model1.add(Dense(32, activation='relu')) # fully connected
#Adding RNN N/W
model1.add(LSTM(32, return_sequences=True))
model1.add(TimeDistributed(Dense(5, activation='softmax')))
I also tried adding input_shape=(160, 120, 3) as a parameter to the LSTM function but to no avail. Please Help!
P.S: I also tried using GRU instead of LSTM but got the same error.
Update: Please note the model.summary() results
enter image description here
Your error is due to your use of Flatten and Dense BEFORE the LSTM layer.
LSTM layers require the input to be in the shape of (Batchsize x Length x Feature depth0) (or some variant), whereas your flatten changes the Conv2D output from (B x H x W x F) to (B x W * F * H) if that makes sense. If you want to use this architecture, I'd recommend using a Reshape layer to flatten the dimension you want, and using a Conv1D of kernel size 1 (same as a fully-connected layer) before the LSTM layer.
Or, if you want to use this exact code, add this before your LSTM layer and it should work:
model1.add(Reshape(target_shape=(1,54*40,32))
It's 54 and 40 due a pool_size of (3,3).

Categories