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.
Related
I'm developing a keras model for binary classification using cell genetic information from an h5ad file.
My training data is a 35000 x 19222 float matrix.
Labels:
labels = adata.obs.tier_0_hallmark_corrected
labels = labels.map({'Tumor': 1, 'Normal':0})
labelsSample = labels.iloc[:35000] #shape: (35000,)
The training samples:
expression = adata.to_df()#this is taken from a file that contains genetic information
expressionSample = expression.iloc[:35000] #Shape: (35000, 19222)
Keras model:
input_dim = 19222
model = Sequential()
model.add(Conv2D(64, 3, activation='selu', input_shape = (input_dim,)))
model.add(Conv2D(64, 3, activation='selu'))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Conv2D(128, 3, activation='selu'))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Conv2D(128, 3, activation='selu'))
model.add(Dropout(0.5))
model.add(BatchNormalization())
model.add(Dense(1, activation='sigmoid'))
model.summary()
When I execute the model I get: ValueError: Input 0 of layer "conv2d_21" is incompatible with the layer: expected min_ndim=4, found ndim=2. Full shape received: (None, 19222). I assume I have to reshape the input data into the model but I don't really know what shape should it have. I'm pretty new to DL so help is much appreciated ;)
You have a problem with the shape of the input.
You should investigate a bit the content of your train data. Conv2D expects an input_shape of 4. You are inserting a shape of 2 (1922 and the batch size that is taken automatically).
For example, if train data are images 28x28 RGB (three channels) the input_shape would be (28, 28, 3). So you would have 4 dimensions (including batch size).
You have to understand better the content of your data and possibly reshape it. Or maybe this is not the right architecture for you.
As the OP was saying in the comments the final solution was to change Conv2D to Conv1D.
Okay I'm new to this I'm trying to classify Traffic Sign images Im actually following a notebook from Kaggle, after building the Keras model
from keras.models import Sequential
from keras.layers import Conv2D, MaxPool2D, Dense, Flatten, Dropout
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(5,5), activation='relu', input_shape=X_train.shape[1:]))
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(rate=0.25))
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2)))
model.add(Dropout(rate=0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(43, activation='softmax'))
#Compilation of the model
model.compile(
loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)
now for the test part after fitting the model the code i found is like this
y_test=pd.read_csv("C:/Users/Louay/input/test.csv")
labels=y_test['Path'].to_numpy()
y_test=y_test['ClassId'].values
data=[]
for f in labels:
image=cv2.imread('C:/Users/Louay/input/Test/'+f.replace('Test/', ''))
image_from_array = Image.fromarray(image, 'RGB')
size_image = image_from_array.resize((height, width))
data.append(np.array(size_image))
X_test=np.array(data)
X_test = X_test.astype('float32')/255
pred = model.predict_classes(X_test)
this works and it predicts the classes of all images in the test set correctly my problem is when I tried to predict only 1 image from the test set okay I thought I would repeat the same image processing part and then use predict_classes() so my code should be like this
image=cv2.imread('C:/Users/Louay/input/Test/00000.png')
image_from_array = Image.fromarray(image, 'RGB')
size_image = image_from_array.resize((height, width))
test=np.array(size_image)
pred = model.predict_classes(test.astype('float32')/255)
okay I'm working on 1 image so I thought I don't need the data[] list where I append all processed images but when I run the code I get this error
ValueError: Input 0 of layer sequential_1 is incompatible with the layer: : expected min_ndim=4, found ndim=3. Full shape received: [None, None, 3]
I know I'm doing something wrong but before correcting my code I really want to understand why am I getting this error what's causing it, what's actually happening?
Conv2D expects 4+D tensor with shape: batch_shape + (channels, rows, cols) if data_format='channels_first' or 4+D tensor with shape: batch_shape + (rows, cols, channels) if data_format='channels_last'.
Add extra dimension to your input using tf.expand_dims
Working sample code
import tensorflow as tf
image = tf.zeros([10,10,3])
input_shape = tf.expand_dims(image, axis=0).shape.as_list()
x = tf.random.normal(input_shape)
y = tf.keras.layers.Conv2D(
2, 3, activation='relu', input_shape=input_shape[1:])(x)
print(y.shape)
Output
(1, 8, 8, 2)
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
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))
I have a CNN and like to change this to a LSTM, but when I modified my code I receive the same error: ValueError: Input 0 is incompatible with layer gru_1: expected ndim=3, found ndim=4
I already change ndim but didn't work.
follow my cnn
def build_model(X,Y,nb_classes):
nb_filters = 32 # number of convolutional filters to use
pool_size = (2, 2) # size of pooling area for max pooling
kernel_size = (3, 3) # convolution kernel size
nb_layers = 4
input_shape = (1, X.shape[2], X.shape[3])
model = Sequential()
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
border_mode='valid', input_shape=input_shape))
model.add(BatchNormalization(axis=1))
model.add(Activation('relu'))
for layer in range(nb_layers-1):
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(BatchNormalization(axis=1))
model.add(ELU(alpha=1.0))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation("softmax"))
return model
and follow how i like to did my LSTM
data_dim = 41
timesteps = 20
num_classes = 10
model = Sequential()
model.add(LSTM(256, return_sequences=True, input_shape=(timesteps, data_dim)))
model.add(Dropout(0.5))
model.add(LSTM(128, return_sequences=True, input_shape=(timesteps, data_dim)))
model.add(Dropout(0.25))
model.add(LSTM(64))
model.add(Dropout(0.2))
model.add(Dense(num_classes, activation='softmax'))
What I was doing wrong?
Thanks
The LSTM code is fine, it executes with no errors for me.
The error you are seeing is related to internal incompatibility of the tensors within the model itself, not related to training data, in which case you'll get an "Exception: Invalid input shape"
What's confusing in your error is that it refers to a GRU layer, which isn't contained anywhere in your model definition. If your model only contains LSTM, you should get an error that calls out the LSTM layer that it conflicts with.
Perhaps check
model.get_config()
and make sure all the layers and configs are what you intended.
In particular, the first layer should say this:
batch_input_shape': (None, 20, 41)