Using LSTM after CNN / Convolutional LSTM in keras - python

I want to predict numerical Y variable using time-series image data.
My dataset has these dimensions:
X: (7000, 3, 128, 128)
Y: (7000, 1)
7000 is the number of samples, each sample is 128 x 128 image and 3 is the number of channels (RGB). The range of the Y variable is 0-1.
Therefore, I want to apply an LSTM model after a CNN. But if I feed the CNN features to LSTM, so many errors occurs. Please help me.
This is my code:
size = 128
model = Sequential()
model.add(Convolution2D(32, (3, 3), input_shape=(3, size, size)))
model.add(Activation('relu'))
model.add(Convolution2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(Convolution2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
#### LSTM #####
model.add(LSTM(50)) ???????????????????????????
model.add(Flatten())
model.add(Dense(32))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='mse', optimizer= 'adam')
return model

Related

How to get shapes of all the layers in a model?

Consider the following model
def create_model():
x_1=tf.Variable(24)
bias_initializer = tf.keras.initializers.HeNormal()
model = Sequential()
model.add(Conv2D(64, (5, 5), input_shape=(28,28,1),activation="relu", name='conv2d_1', use_bias=True,bias_initializer=bias_initializer))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (5, 5), activation="relu",name='conv2d_2', use_bias=True,bias_initializer=bias_initializer))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(120, name='dense_1',activation="relu", use_bias=True,bias_initializer=bias_initializer),)
model.add(Dense(10, name='dense_2', activation="softmax", use_bias=True,bias_initializer=bias_initializer),)
Is there any way I can get the shape/size/dimensions of the all the layer(s) of a model ?
For example in the above model, 'conv2d_1' has shape of (64,1,5,5) while 'conv2d_2' has shape of (32,64,5,5)?
You can use model.summary(). Or you can loop through all layers and print the output shape:
for layer in model.layers:
print(f'{layer.name} {layer.output_shape}')

Tensorflow 2.4.0 RAM continues grow when CNN training

I have built a simple CNN using tensorflow-gpu 2.4.0 for cifar10
# Set constent
num_classes = len(label_names) # The number of classes
input_shape = (32, 32, 3) # The input shape 32 * 32 pixels, 3 RGB brightness for each pixel
# Construct a sequential model
model = Sequential()
# Starting add layers to the model
# First VGG blockes
model.add(Conv2D(16, (3, 3), padding='same', activation='relu', input_shape=input_shape))
model.add(BatchNormalization()) # BatchNormalization after convolutional layer
model.add(Conv2D(16, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization()) # BatchNormalization after convolutional layer
model.add(MaxPooling2D((2, 2))) # MaxPooling2D to keep important features as well as shirnk info size
model.add(Dropout(0.1)) # Drop some portion of nodes to increase generality of model
# Second VGG blockes
model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(32, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.2))
# Third VGG blockes
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(64, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.3))
# Fourth VGG blockes
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(Conv2D(128, (3, 3), padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(MaxPooling2D((2, 2)))
model.add(Dropout(0.4))
# Flat and dense layer
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
# Final softmax layer
model.add(Dense(num_classes, activation='softmax'))
# The optimizer gives the learning rate lr and some other parameters.
opt = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
# Model complie
model.compile(loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy'])
And while I am training this model:
#Train model
epochs = 100
batch_size = 128
# create data generator
datagen = ImageDataGenerator(horizontal_flip=True,
width_shift_range=5,
height_shift_range=5,
rotation_range=20)
history = model.fit(datagen.flow(x_training, y_training, batch_size=batch_size),
epochs=epochs,
validation_data=(x_validate, y_validate),
verbose=1,
shuffle=True)
The RAM of my computer keeps grow until the training process crashes. Adding python garbage collector for at end of each epoch did not work. Disabling eager detection did not work.
I using
tensorflow-gpu 2.4.0
CUDA 11.0
cuDNN 8.0

ValueError: Input 0 of layer conv3d_8 is incompatible with the layer: : expected min_ndim=5, found ndim=4. Full shape received: [None, 4, 150, 150]

I'm trying to train a 3D CNN model in Keras, but i'm getting this error when I execute the cell:
ValueError: Input 0 of layer conv3d_8 is incompatible with the layer: : expected min_ndim=5, found ndim=4. Full shape received: [None, 4, 150, 150]
My input data is a numpy array with image data. Here are the shapes (I know that 53 is too few, but it's just for studying purposes):
Training data shape: (53, 4, 150, 150)
Training labels shape: (53, 1)
Validation data shape: (14, 4, 150, 150)
Validation labels shape: (14, 1)
The model I'm trying to use is:
# Create the model
model = Sequential()
model.add(Conv3D(32, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform', input_shape=(4,150,150)))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Conv3D(64, kernel_size=(3, 3, 3), activation='relu', kernel_initializer='he_uniform'))
model.add(MaxPooling3D(pool_size=(2, 2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(4, activation='softmax'))
# Compile the model
model.compile(loss='categorical_crossentropy',
optimizer=keras.optimizers.Adam(lr=0.001),
metrics=['accuracy'])
model.summary()
# Fit data to model
history = model.fit(treino3d, treino3d_labels,
epochs=40)
Can someone help, please?
Thanks a lot!
It doesn't seem like you need Conv3D layers for this task. Use Conv2D instead, and use only 1 or 2 values in kernel_size and pool_size.
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu',
kernel_initializer='he_uniform',
input_shape=(4,150,150)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu',
kernel_initializer='he_uniform'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(256, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(4, activation='softmax'))
Your channel dimension comes first so you will need to tell Keras. Use this line:
tf.keras.backend.set_image_data_format('channels_first')
Or set this parameter in every Conv2D or MaxPooling2D layer:
data_format='channels_first'
Or permute the dimensions of the input tensor to have shape (54, 150, 150, 4):
np.transpose(x, (0, 2, 3, 1))
Full functioning, corrected example:
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
from tensorflow.keras.layers import *
import numpy as np
from tensorflow.keras.models import Sequential
xtrain = np.random.rand(53, 4, 150, 150)
ytrain = np.random.randint(0, 4, (53, 1))
xtrain = np.transpose(xtrain, (0, 2, 3, 1))
model = Sequential()
model.add(Conv2D(8, kernel_size=(3, 3), activation='relu',
kernel_initializer='he_uniform', input_shape=xtrain.shape[1:]))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Conv2D(8, kernel_size=(3, 3), activation='relu',
kernel_initializer='he_uniform'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization(center=True, scale=True))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(32, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(32, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(4, activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.summary()
history = model.fit(xtrain, ytrain, epochs=1)
32/53 [=================>............] - ETA: 2s - loss: 1.8215 - acc: 0.2812
53/53 [==============================] - 5s 91ms/sample - loss: 1.9651 - acc: 0.2264
The first answer is correct. As I can recall (I didn't work with MRI for a couple of years), each slice is represented by 4 channels and each voxel in channel contains an information about the same physical position. Therefore, it would be correct approach to apply 2D-convolution for the image of 4 channels.
For 2D convolution I would recommend to define your input with input_shape=(150,150,4), or even as input_shape=(None, None, 4) - it is more generic. So you don't need to play with channel_first or channel_last configuration. channel_last is default format, as I remember
If you insist to use Conv3d, your input shape should be: input_shape=(150,150,4,1) or (None, None, None, 1)
and trainset should follow shape like: np.random.rand(53, 150, 150, 4, 1)

ValueError: Error when checking target: expected dense_35 to have 4 dimensions, but got array with shape (1157, 1)

I have train & test image data for which Shapes are given below.
X_test.shape , y_test.shape , X_train.shape , y_train.shape
((277, 128, 128, 3), (277, 1), (1157, 128, 128, 3), (1157, 1))
I am training a model
def baseline_model():
filters = 100
model = Sequential()
model.add(Conv2D(filters, (3, 3), input_shape=(128, 128, 3), padding='same', activation='relu'))
#model.add(Dropout(0.2))
model.add(BatchNormalization())
model.add(Conv2D(filters, (3, 3), activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(MaxPooling2D(pool_size=(2, 2)))
#model.add(Flatten())
model.add(Conv2D(filters, (3, 3), activation='relu', padding='same'))
model.add(BatchNormalization())
model.add(Conv2D(filters, (3, 3), activation='relu', padding='same'))
model.add(Activation('linear'))
model.add(BatchNormalization())
model.add(Dense(512, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
# Compile model
lrate = 0.01
epochs = 10
decay = lrate/epochs
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
model.compile(loss='sparse_categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])
print(model.summary())
return model
But I am getting an error Given below
Error when checking target: expected dense_35 to have 4 dimensions,
but got array with shape (1157, 1)
Please tell me what mistake I am making and how to fix this. I have attached snapshot of model summary
One thing you have probably forgotten to do is adding a Flatten layer right before the first Dense layer:
model.add(BatchNormalization())
model.add(Flatten()) # flatten the output of previous layer before feeding it to Dense layer
model.add(Dense(512, activation='relu'))
You need it because Dense layer does not flatten its input; rather, it is applied on the last dimension.
Although dense_35 needs to feed with 4 dimension data, according to the error, the network feed with 2 dimension data which is the label vector.

Negative dimension size caused by subtracting 2 from 1 for 'max_pooling2d_3/MaxPool' (op: 'MaxPool') with input shapes: [?,1,148,32]

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150),padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3),padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten()) # this converts our 3D feature maps to 1D feature
vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
#sgd = optimizers.SGD(lr=0.0001, decay=1e-6, momentum=0.9)
model.compile(loss='sparse_categorical_crossentropy',
`optimizer=Adam(lr=0.001), # Adam optimizer with 1.0e-4 learning rate
metrics = ['accuracy']) # Metrics to be evaluated by the model
When I compile the above code i get this error
Negative dimension size caused by subtracting 2 from 1 for 'max_pooling2d_8/MaxPool' (op: 'MaxPool') with input shapes: [?,1,75,32].
I tried with the same padding and it still doesn't work
Pretty sure if you change
model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150),padding='same'))
to
model.add(Conv2D(32, (3, 3), input_shape=(150, 150, 3),padding='same'))
(you may have to change the shape of your data too)
it will work as intended.

Categories

Resources